AltSchool / dynamic-rest

Dynamic extensions for Django REST Framework
MIT License
831 stars 109 forks source link

DynamicRelationField not detected #231

Open gonvaled opened 6 years ago

gonvaled commented 6 years ago

I am using dynamic-rest. According to the documentation, I have this model with a dynamically generated foreign key:

    class PscSerializer(DynamicModelSerializer):

        class Meta:
            model = PSC
            name = 'psc'
            fields = ('id', 'description', 'created', 'modified', 'pscno', 'productno', 'serviceno', 'luns')

        luns = DynamicRelationField('LunSerializer', many=True)

Which produces:

Exception Type: AttributeError at /api/v1/pscs/ Exception Value: luns is not a valid field for <class 'pscs.models.PSC'>

Sure, luns is not a field in the PSC model, but a dynamic field. What is going on? What am I doing wrong here?

I am using:

Django==2.0.4
djangorestframework==3.7.7
dynamic-rest==1.8.0

And:

» python --version
Python 3.6.4
ryochiji commented 6 years ago

DynamicRelationField has to refer to an actual relational field on the model. If it's completely "dynamic", as in you want the value to be calculated entirely in the serializer, try DynamicMethodField.

freemansion commented 6 years ago

I had same trouble as @gonvaled until I found @ryochiji's comment about DynamicMethodField. From this comment, as for me, was helpful information that DynamicRelationField supposed to be used for relational fields only (I've tried to use it for reversed relationship). Though at the documentation briefly mentioned about DynamicMethodField, I think it could be helpful for the newbies to have more examples.

Here is my example of an UserSerializer with reversed relationship, where ListingItem model has foreign key User:

ListingItem.py

from django.db import models

class ListingItem(models.Model):
    title       = models.CharField(max_length=150)
    subtitle    = models.CharField(max_length=300)
    owner       = models.ForeignKey(User, on_delete=models.CASCADE)

UserSerializer.py

from dynamic_rest import fields as fields
from dynamic_rest import serializers as serializers

class UserSerializer(serializers.DynamicModelSerializer):

    ads = fields.DynamicMethodField()

    class Meta:
        model = User
        name = 'user'
        fields = ('id', 'email', 'ads')
        deferred_fields = ('ads')

    def get_ads(self, obj):
        items = ListingItem.objects.filter(owner__pk=obj.id)
        serializer = ListingItemSerializer(items, many=True)
        return serializer.data

Note: Ideally this example should contain attribute requires at the DynamicMethodField initializer for drest optimization strategy. Will update it once figure out how to make it work properly.

KrystofS commented 2 years ago

Hi, has there been any progress on this issue?