Я использую структуру 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'}]
Я прочитал документы об обратных отношениях для остальной структуры, но, похоже, это тот же результат, что и не обратные поля. Я упускаю что-то очевидное?
python
django
django-rest-framework
врата ада
источник
источник
Relational field must provide a 'queryset' argument, or set read_only='True'
category_name = serializers.RelatedField(source='category', queryset=Category.objects.all())
Я полагаю.AssertionError:...
воспользуетесь этим ответом, stackoverflow.com/a/44530606/5403449В версии 3.6.3 DRF это сработало для меня
class ItemSerializer(serializers.ModelSerializer): category_name = serializers.CharField(source='category.name') class Meta: model = Item fields = ('id', 'name', 'category_name')
Более подробную информацию можно найти здесь: Основные аргументы полей сериализатора
источник
Еще вы можете сделать следующее:
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
источник
это сработало для меня:
class ItemSerializer(serializers.ModelSerializer): category_name = serializers.ReadOnlyField(source='category.name') class Meta: model = Item fields = "__all__"
источник
Работали 08.08.2018 и на 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',)
Используя Meta,
read_only_fields
мы можем точно указать, какие поля должны быть read_only. Затем нам нужно объявитьforeign
поле в Metafields
(лучше быть явным, как гласит мантра: zen of python ).источник
Простое решение,
source='category.name'
гдеcategory
внешний ключ и.name
его атрибут.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__"
источник
Это решение лучше, потому что не нужно определять исходную модель. Но имя поля сериализатора должно совпадать с именем поля внешнего ключа.
class ItemSerializer(serializers.ModelSerializer): category = serializers.SlugRelatedField(read_only=True, slug_field='title') class Meta: model = Item fields = ('id', 'name', 'category')
источник