My model looks like this:
class MenuItem(models.Model):
name = models.CharField(max_length=500)
components = models.ManyToManyField(Component, through=MenuItemComponent)
class Component(models.Model):
name = models.CharField(max_length=500)
class MenuItemComponent(models.Model):
menuItem = models.ForeignKey('MenuItem')
component = models.ForeignKey(Component)
isReplaceable = models.BooleanField()
What I'd like to do is expose a list of Components (NOT MenuItemComponents) in given MenuItem that would include the isReplaceable field. So far I have:
#views.py
class MenuItemComponentList(generics.ListAPIView):
"""
Displays components for given MenuItem
"""
model = MenuItemComponent
serializer_class = MenuItemComponentSerializer
def get_queryset(self):
itemId = self.kwargs['itemId']
return MenuItemComponent.objects.filter(menuItem__pk=itemId)
#serializers.py
class MenuItemComponentSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = MenuItemComponent
Which exposes a list of MenuItemComponents and forces clients to make multiple calls in order to retrieve all Components. Exposing Components list with additional data from isReplaceable field would solve the problem.
EDIT
In the end I'd like to get a list that lists Component elements but the elements are exteded with isReplaceable field from MenuItemComponent model:
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"url": "http://localhost:8000/api/component/1/",
"name": "component 1",
"isReplaceable": true
},
{
"url": "http://localhost:8000/api/component/2/",
"name": "component 2",
"isReplaceable": false
}
]
}
In function based views we can pass extra context to serializer with "context" parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with "self. context". From example, to get "exclude_email_list" we just used code 'exclude_email_list = self.
The ModelSerializer class is the same as a regular Serializer class, except that: It will automatically generate a set of fields for you, based on the model. It will automatically generate validators for the serializer, such as unique_together validators. It includes simple default implementations of .
Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
DRF allows you to expose a REST framework based on your django data models with very little code needed. To get a basic REST API that supports Create-Read-Update-Delete operations on your data you have to do two things: You specify a serializer that tells drf how to go from your model to a JSON representation.
First, create a view that will return the MenuItemComponent instances that you're interested in.
class ListComponents(generics.ListAPIView):
serializer_class = MenuItemComponentSerializer
def get_queryset(self):
"""
Override .get_queryset() to filter the items returned by the list.
"""
menuitem = self.kwargs['menuitem']
return MenuItemComponent.objects.filter(menuItem=menuitem)
Then you need to create a serializer to give you the representation you want. Your example is a bit more interesting/involved than the typical case, so it'd look something like this...
class MenuItemComponentSerializer(serializers.Serializer):
url = ComponentURLField(source='component')
name = Field(source='component.name')
isReplaceable = Field()
The fields 'name' and 'isReplaceable' can simply use the default read-only Field
class.
There's no field that quite meets your 'url' case here, so we'll create a custom field for that:
class ComponentURLField(serializers.Field):
def to_native(self, obj):
"""
Return a URL, given a component instance, 'obj'.
"""
# Something like this...
request = self.context['request']
return reverse('component-detail', kwargs=kwargs, request=request)
I think that should all be about right.
That's for a read-only serialization - if you wanted a writable serialization you'd need to look into overriding the restore_object
method on the serializer, and using WritableField
, or something along those lines.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With