I'm using the django rest framework to create an API. I have the following models:
class Category(models.Model):
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class Item(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey(Category, related_name='items')
def __unicode__(self):
return self.name
To create a serializer for the categories I'd do:
class CategorySerializer(serializers.ModelSerializer):
items = serializers.RelatedField(many=True)
class Meta:
model = Category
... and this would provide me with:
[{'items': [u'Item 1', u'Item 2', u'Item 3'], u'id': 1, 'name': u'Cat 1'},
{'items': [u'Item 4', u'Item 5', u'Item 6'], u'id': 2, 'name': u'Cat 2'},
{'items': [u'Item 7', u'Item 8', u'Item 9'], u'id': 3, 'name': u'Cat 3'}]
How would I go about getting the reverse from an Item serializer, ie:
[{u'id': 1, 'name': 'Item 1', 'category_name': u'Cat 1'},
{u'id': 2, 'name': 'Item 2', 'category_name': u'Cat 1'},
{u'id': 3, 'name': 'Item 3', 'category_name': u'Cat 1'},
{u'id': 4, 'name': 'Item 4', 'category_name': u'Cat 2'},
{u'id': 5, 'name': 'Item 5', 'category_name': u'Cat 2'},
{u'id': 6, 'name': 'Item 6', 'category_name': u'Cat 2'},
{u'id': 7, 'name': 'Item 7', 'category_name': u'Cat 3'},
{u'id': 8, 'name': 'Item 8', 'category_name': u'Cat 3'},
{u'id': 9, 'name': 'Item 9', 'category_name': u'Cat 3'}]
I've read through the docs on reverse relationships for the rest framework but that appears to be the same result as the non-reverse fields. Am I missing something obvious?
This question is related to
python
django
django-rest-framework
In the DRF version 3.6.3 this worked for me
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.CharField(source='category.name')
class Meta:
model = Item
fields = ('id', 'name', 'category_name')
More info can be found here: Serializer Fields core arguments
this worked fine for me:
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.ReadOnlyField(source='category.name')
class Meta:
model = Item
fields = "__all__"
Worked on 08/08/2018 and on DRF version 3.8.2:
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.ReadOnlyField(source='category.name')
class Meta:
model = Item
read_only_fields = ('id', 'category_name')
fields = ('id', 'category_name', 'name',)
Using the Meta read_only_fields
we can declare exactly which fields should be read_only. Then we need to declare the foreign
field on the Meta fields
(better be explicit as the mantra goes: zen of python).
This solution is better because of no need to define the source model. But the name of the serializer field should be the same as the foreign key field name
class ItemSerializer(serializers.ModelSerializer):
category = serializers.SlugRelatedField(read_only=True, slug_field='title')
class Meta:
model = Item
fields = ('id', 'name', 'category')
Another thing you can do is to:
Item
model that returns the category name and ReadOnlyField
.Your model would look like this.
class Item(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey(Category, related_name='items')
def __unicode__(self):
return self.name
@property
def category_name(self):
return self.category.name
Your serializer would look like this. Note that the serializer will automatically get the value of the category_name
model property by naming the field with the same name.
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.ReadOnlyField()
class Meta:
model = Item
Simple solution
source='category.name'
where category
is foreign key and .name
it's attribute.
from rest_framework.serializers import ModelSerializer, ReadOnlyField
from my_app.models import Item
class ItemSerializer(ModelSerializer):
category_name = ReadOnlyField(source='category.name')
class Meta:
model = Item
fields = "__all__"
Source: Stackoverflow.com