drf-flex-fields icon indicating copy to clipboard operation
drf-flex-fields copied to clipboard

Reverse Relationships?

Open neighlyd opened this issue 6 years ago • 5 comments

Hello,

I may be missing something, so I apologize if I am, but I am unable to get DRF-Flex-Fields to work properly with a reverse relationships . Is this not something that drf-flex-fields can do or am I messing up somehow?

neighlyd avatar May 12 '18 00:05 neighlyd

Hi there, this should work with reverse relationships. You'd just need to make sure that the "source" arg matches what you've configured via the related= arg on your model FK.

Would help me debug if you could post some code of your model and serializer.

rsinger86 avatar May 12 '18 22:05 rsinger86

Hi,

Thanks for the response. I apologize for not posting code before.

It seems that the issue may not actually be related to reverse relationships as I had previously thought. Following your response, I was able to get them working using the related= argument (or, alternatively, the <model>_set notation).

It appears that the real issue I was having was actually an order of operations one. Since my reverse relation serializer is defined below the serializer in which I want to expand the set, I can't reach it (either it is undefined at runtime, or if I use quotations as per normal DRF reference, it spits an error). An example may help.

serializers.py
class ArchiveSerializer(FlexFieldsModelSerializer):
    class Meta:
        model = models.Archive
        name = 'archive'
        fields = ('id', 'name', 'website', 'notes')

    expandable_fields = {
        'record_set': (RecordSerializer, {'source': 'record_set', 'many': True})
    }

class RecordSerializer(FlexFieldsModelSerializer):
    class Meta:
        model = models.Record
        fields = ('id', 'name', 'record_type', 'reel', 'notes', 'archive')

    expandable_fields = {
        'archive': (ArchiveSerializer, {'source': 'archive'})
    }

This throws an error when the server is run, because RecordSerializer is undefined.

If I put RecordSerializer in quotes within ArchiveSerializer like so:

class ArchiveSerializer(FlexFieldsModelSerializer):
    class Meta:
        model = models.Archive
        name = 'archive'
        fields = ('id', 'name', 'website', 'notes')

    expandable_fields = {
        'record_set': ('RecordSerializer', {'source': 'record_set', 'many': True})
    }

The error goes away and the server runs. However, when I navigate to ArchiveSerializer I receive the following error:

list index out of range

It looks like it's getting tripped up on line 77 of DRF-Flex-Field's serializers.py.

Obviously, having a circular expansion would be no good, but since children often expand their parents and parents often have need to expand a set of their children I'm finding the need to reference circularly (though not expanding circularly). Is the only alternative to have two versions of RecordSerializer?

neighlyd avatar May 14 '18 20:05 neighlyd

Ah, so this is something I need to document. If you want to lazily evaluate the reference to your nested serializer class from a string inside expandable_feilds, you need to use this syntax:

expandable_fields = {
    'record_set': ('<app_name>.RecordSerializer', {'source': 'record_set', 'many': True})
}

Substitute the name of your Django app where the serializer is found for <app_name>. But if the serializer exists in the same app that it is called from, I really should allow the syntax that you used... Similar to how Django evaluates references to model FKs. I'll look to update this in a future version. Thanks for raising this issue.

rsinger86 avatar May 20 '18 17:05 rsinger86

Oh great! Thanks so much for the information. I will go ahead and refactor my code to that instead of having a bunch of extra serializers.

I appreciate it!!

neighlyd avatar May 21 '18 04:05 neighlyd

+1 for this info in the docs! Ran into the same issue by wanting to keep my serializers in alphabetical order. Thanks so much!

willcroft avatar Mar 22 '19 13:03 willcroft