Używam struktury django rest do tworzenia API. Mam następujące modele:
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
Aby utworzyć serializator dla kategorii, zrobiłbym:
class CategorySerializer(serializers.ModelSerializer):
items = serializers.RelatedField(many=True)
class Meta:
model = Category
... a to zapewni mi:
[{'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'}]
Jak powinienem zająć się uzyskaniem odwrotności z serializatora pozycji, tj .:
[{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'}]
Przeczytałem dokumentację dotyczącą odwrotnych relacji dla pozostałej struktury, ale wydaje się, że jest to ten sam wynik, co pola nieodwrotne. Czy brakuje mi czegoś oczywistego?
python
django
django-rest-framework
wrota do piekieł
źródło
źródło
Relational field must provide a 'queryset' argument, or set read_only='True'
category_name = serializers.RelatedField(source='category', queryset=Category.objects.all())
Przypuszczam.AssertionError:...
skorzystaj z tej odpowiedzi stackoverflow.com/a/44530606/5403449W wersji DRF 3.6.3 to zadziałało
class ItemSerializer(serializers.ModelSerializer): category_name = serializers.CharField(source='category.name') class Meta: model = Item fields = ('id', 'name', 'category_name')
Więcej informacji można znaleźć tutaj: podstawowe argumenty pól serializatora
źródło
Inną rzeczą, którą możesz zrobić, jest:
Item
modelu, która zwraca nazwę kategorii iReadOnlyField
.Twój model wyglądałby tak.
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
Twój serializator wyglądałby tak. Zwróć uwagę, że serializator automatycznie pobierze wartość
category_name
właściwości modelu przez nazwanie pola o tej samej nazwie.class ItemSerializer(serializers.ModelSerializer): category_name = serializers.ReadOnlyField() class Meta: model = Item
źródło
to działało dobrze dla mnie:
class ItemSerializer(serializers.ModelSerializer): category_name = serializers.ReadOnlyField(source='category.name') class Meta: model = Item fields = "__all__"
źródło
Pracowano w dniu 08/08/2018 i nad wersją 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',)
Za pomocą Meta
read_only_fields
możemy dokładnie zadeklarować, które pola powinny być tylko do odczytu. Następnie musimy zadeklarowaćforeign
pole w Metafields
(lepiej, aby było jasne, jak mówi mantra: zen z Pythona ).źródło
Proste rozwiązanie
source='category.name'
gdziecategory
jest klucz obcy i.name
jego atrybut.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__"
źródło
To rozwiązanie jest lepsze, ponieważ nie ma potrzeby definiowania modelu źródłowego. Ale nazwa pola serializatora powinna być taka sama, jak nazwa pola klucza obcego
class ItemSerializer(serializers.ModelSerializer): category = serializers.SlugRelatedField(read_only=True, slug_field='title') class Meta: model = Item fields = ('id', 'name', 'category')
źródło