Skip to content

Instantly share code, notes, and snippets.

@guglielmo
Last active December 30, 2015 15:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guglielmo/7851650 to your computer and use it in GitHub Desktop.
Save guglielmo/7851650 to your computer and use it in GitHub Desktop.
Code to reproduce a probable issue within django-rest-framework. A Place may have many acronyms. The reverse fk relationship ('acronyms') is serialized with a nested AcronymSerializer. When issuing PUT to edit the place, the old acronyms not in the json payload anymore, are not removed from the DB. The HTML form shows the error: non_field_errors…
## Models
class Place(models.Model):
name = models.CharField(max_length=255, blank=True)
slug = models.SlugField(max_length=255, null=True, blank=True)
class PlaceAcronym(models.Model):
place = models.ForeignKey('Place', related_name="acronyms")
acronym = models.CharField(_("acronym"), max_length=128,
help_text=_("An acronym for the place, e.g. 'PV'")
)
## Detail View
class PlaceDetail(generics.RetrieveUpdateDestroyAPIView):
model = Place
serializer_class = PlaceSerializer
## Serializers
class AcronymSerializer(serializers.ModelSerializer):
def get_identity(self, data):
return data
def to_native(self, value):
return '%s' % (value.acronym, )
def from_native(self, data, files):
value = super(AcronymSerializer, self).from_native({'acronym': data}, files)
return value
class Meta:
model = PlaceAcronym
fields = ('acronym',)
class PlaceSerializer(serializers.ModelSerializer):
acronyms = AcronymSerializer(many=True, allow_add_remove=True)
class Meta:
model = Place
view_name = 'maps:place-detail'
lookup_field = 'slug'
_self = serializers.HyperlinkedIdentityField(view_name='maps:place-detail')
fields = (
'_self',
'slug', 'name', 'acronyms',
)
@guglielmo
Copy link
Author

Acronyms are not specified by ID, so the AcronymSerializer needs to override the get_identity hook, and use

return data.get('acronym', None)

instead of

return data.get('id', None)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment