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
Post a Comment