django rest framework - SlugRelatedField queryset -


i struggling figure out queryset slugrelatedfield. data such have bunch of object instances belong project. project has unique 'top' object. objects can have same name if below different projects.

class object(models.model):     project = models.foreignkey('project', null=false, related_name='objs')     name = models.textfield(null=false, db_index=true)     ....     class meta:         index_together = unique_together = ('project', 'name')  class project(models.model):     user = models.foreignkey(get_user_model(), null=false, related_name='+')     name = models.textfield(null=false)     top = models.onetoonefield(object, null=true, related_name='+')     ....  class objectserializer(nonnullserializer):     class meta:         model = object         fields = ('name',)  class projectserializer(nonnullserializer):     objs = objectserializer(many=true, required=false)     top = serializers.slugrelatedfield(slug_field='name', queryset=object.objects.filter(????))      class meta:         model = project         fields = ('id', 'name', 'objs', 'top') 

what queryset going top if want find only 1 object belongs correct project? in other words, how deserialize this:

[{     'name' : 'project1',     'objs' : [{         'name': 'one'     }],     'top': 'one' }, {     'name' : 'project2',     'objs' : [{         'name': 'one'     }],     'top': 'one'     <-- should point 1 under project2, not 1 under project1 }] 

i have solution solves problem in case, try explain here.

the problem, abstracted:

suppose have hierarchy foo top-level objects, each associated several bars:

class foo(model):     pass  class bar(model):     bar_text = charfield()     foo = foreignkey(foo, related_name='bars') 

then can use slugrelatedfield trivially read serializations of foo, mean serializer:

class fooserializer(modelserializer):      bars = serializers.slugrelatedfield(slug_field='bar_text',                                           many=true, read_only=true)      class meta:          model = foo          fields = ('bars',) 

will produce serializations like:

{ 'bars' : [<bar_text>, <bar_text>, ...] } 

however, read only. allow writing, have provide queryset class attribute outside of methods. problem is, because have foo->bar hierarchy, don't know queryset outside of request. able override get_queryset() method, none seems exist. can't use slugrelatedfield. horribly hacky way can fix it?

my solution:

first, add @property foo model , put property in serializer:

in models.py:

class foo(model):     @property     def bar_texts(self):         return [bar.bar_text bar in self.bars.all()] 

in serializers.py:

class fooserializer(modelserializer):      class meta:          model = foo          fields = ('bar_texts',) 

this allows bar texts serialized before, still can't write (we can try - framework won't reject hit exception when trying save bar_texts attribute of foo)

so, hacky part - fix perform_create() in foo list view.

class foolist:     def perform_create(self, serializer):         # serializer contains bar_text field, want, doesn't correspond         # writeable attribute of foo. extract strings , save foo. use pop default arg in case bar_texts isn't in serialized data         bar_texts = serializer.validated_data.pop('bar_texts', [])          # save foo object; has no bars associated         foo = serializer.save()          # add bars database         bar_text in bar_texts:             foo.bars.create(bar_text=bar_text) 

i hope makes sense. works me, have find glaring bugs it


Comments

Popular posts from this blog

javascript - Bootstrap Popover: iOS Safari strange behaviour -

Magento/PHP - Get phones on all members in a customer group -

session - Logging Out Using PHP -