Reputation: 53
So I was trying to access a serializer using the serializer name, and the model query set as a parameter, using the python gettattr() function. After running the code, Django returns the following error:
'str' object has no attribute '<module 'django.db.models' from 'C:\\Python310\\lib\\site-packages\\django\\db\\models\\__init__.py'>'
However I can't really understand what it means, I've been stuck on trying to access the serializer this way, as I have a dyanmic url.
Anyhelp with the problem or explanation of the error would be appreciated.
I was expecting the serializer to be processed normally, and return the data in the respone, I implemented it this way.
@api_view(['GET'])
def List_all_part(request, part):
table = apps.get_model('Parts', part)
model = table.objects.all()
serializer = getattr(str(part.lower()), str(models))
return Response(serializer.data)
Upvotes: 0
Views: 754
Reputation: 229
i'm not sure if i got your problem but the best way to use a dynamic serializer is to create function that will return the needed one example:
@api_view(['GET'])
def List_all_part(request, part):
table = apps.get_model('Parts', part)
model = table.objects.all()
serializer = dynamic_serializer(model.model)
return Response(serializer.data)
and the definition of the dynamic_serializer function will be like:
def dynamic_serializer(model_class):
class DynamicSerializer(serializers.ModelSerializer):
class Meta:
model = model_class
if model_class == cpu:
fields = ('id', 'field_cpu1', 'field_cpu2', 'field_cpu3')
elif model_class == other_model:
fields = ('id', 'field_other_model1', 'field_other_model2', 'field_other_model3')
else:
fields = ('id', 'field_another_model1', 'field_another_model2', 'field_another_model3')
return DynamicSerializer
PS: getattr doesn't take a string as first argument. You have to pass an object or instance as first argument and an str as second argument thats why you have the error: 'str' object has no attribute '<QuerySet []>' because you are looking for a QuerySet on an str, and in your case i think the getattr is not useful, unless you declare the cpu attribute in your model class as a serializer object
Upvotes: 0
Reputation: 357
What you need is to load your serializer class from the module it's defined in. You can use getattr but you need to use the loaded module object as the first parameter, not a str. So simply import you serializer module, and pass it as first argument to getattr.
Also you can use other means for dynamic class loading, but this would be simpler. Also the result of the getattr will be the desired serializer class, after that you need to call it with the data you want to be serialized. e.g.
import serializers
@api_view(['GET'])
def List_all_part(request, part):
table = apps.get_model('Parts', part)
model = table.objects.all()
serializer_class = getattr(serializers, str(models))
serializer = serializer_class(model, many=True)
return Response(serializer.data)
Upvotes: 1
Reputation: 1141
getattr
doesn't take a string
as first argument. You have to pass an object/instance
In [8]: class Test:
...: def __init__(self):
...: self.foo = "bar"
...: def bar(self):
...: return "foo"
...:
In [9]: t = Test()
In [10]: getattr(t, "foo")
Out[10]: 'bar'
In [11]: getattr(t, "bar")()
Out[11]: 'foo'
In [12]:
Upvotes: 1
Reputation: 155
I think you may have a typo in models
.
@api_view(['GET'])
def List_all_part(request, part):
table = apps.get_model('Parts', part)
model = table.objects.all()
- serializer = getattr(str(part.lower()), str(models))
+ serializer = getattr(str(part.lower()), str(model))
return Response(serializer.data)
Upvotes: 1