Emad G
Emad G

Reputation: 53

Python Django - Trying to make a dynamic name from string to call serializer function

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

Answers (4)

Ahmed Kolsi
Ahmed Kolsi

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

Mohsen Mahmoodi
Mohsen Mahmoodi

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

josuebrunel
josuebrunel

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

Igor
Igor

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

Related Questions