Получение значения внешнего ключа с помощью сериализаторов django-rest-framework
Я использую среду django rest для создания API.
У меня есть следующие модели:
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
Чтобы создать сериализатор для категорий, которые я сделал бы:
class CategorySerializer(serializers.ModelSerializer):
items = serializers.RelatedField(many=True)
class Meta:
model = Category
... и это обеспечило бы мне:
[{'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'}]
Как я могу получить обратное от сериализатора элемента, то есть:
[{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'}]
Я прочитал документы обратные отношения для рамки rest, но это похоже на тот же результат, что и поля без обратного, Мне что-то не хватает?
Ответы
Ответ 1
Просто используйте связанное поле без установки many=True
.
Обратите внимание, что так же, как вы хотите получить результат с именем category_name
, но фактическое поле category
, вам нужно использовать аргумент source
в поле сериализатора.
Следующее должно предоставить вам необходимый результат...
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.RelatedField(source='category', read_only=True)
class Meta:
model = Item
fields = ('id', 'name', 'category_name')
Ответ 2
В версии DRF 3.6.3 это сработало у меня
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.CharField(source='category.name')
class Meta:
model = Item
fields = ('id', 'name', 'category_name')
Ответ 3
Другая вещь, которую вы можете сделать, это:
- создать свойство в вашей модели
Item
, которая возвращает название категории и
- выставить его как
ReadOnlyField
.
Ваша модель будет выглядеть так.
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
Ваш сериализатор будет выглядеть так. Обратите внимание, что сериализатор автоматически получит значение свойства модели category_name
, назвав поле с тем же именем.
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.ReadOnlyField()
class Meta:
model = Item
Ответ 4
это работало нормально для меня:
class ItemSerializer(serializers.ModelSerializer):
category_name = serializers.ReadOnlyField(source='category.name')
class Meta:
model = Item
fields = "__all__"
Ответ 5
Работал 08.08.2008 и на DRF версии 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',)
Используя метаданные read_only_fields
мы можем объявить, какие именно поля должны быть read_only. Затем нам нужно объявить foreign
поле в мета- fields
(лучше быть явным, когда идет мантра: дзен питона).
Ответ 6
Простое решение source='category.name'
где category
это внешний ключ и .name
it атрибут.
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__