Estoy usando el marco de descanso de django para crear una API. Tengo los siguientes modelos:
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
Para crear un serializador para las categorías, haría:
class CategorySerializer(serializers.ModelSerializer):
items = serializers.RelatedField(many=True)
class Meta:
model = Category
... y esto me proporcionaría:
[{'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'}]
¿Cómo haría para obtener lo contrario de un serializador de artículos, es decir:
[{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'}]
He leído los documentos sobre relaciones inversas para el resto del marco, pero parece ser el mismo resultado que los campos no inversos. ¿Me estoy perdiendo algo obvio?
python
django
django-rest-framework
la puerta del infierno
fuente
fuente
Relational field must provide a 'queryset' argument, or set read_only='True'
category_name = serializers.RelatedField(source='category', queryset=Category.objects.all())
supongo.AssertionError:...
use esta respuesta stackoverflow.com/a/44530606/5403449En la versión 3.6.3 de DRF esto funcionó para mí
class ItemSerializer(serializers.ModelSerializer): category_name = serializers.CharField(source='category.name') class Meta: model = Item fields = ('id', 'name', 'category_name')
Puede encontrar más información aquí: Argumentos principales de los campos del serializador
fuente
Otra cosa que puede hacer es:
Item
modelo que devuelva el nombre de la categoría yReadOnlyField
.Tu modelo se vería así.
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
Su serializador se vería así. Tenga en cuenta que el serializador obtendrá automáticamente el valor de la
category_name
propiedad del modelo al nombrar el campo con el mismo nombre.class ItemSerializer(serializers.ModelSerializer): category_name = serializers.ReadOnlyField() class Meta: model = Item
fuente
Esto funcionó bien para mi:
class ItemSerializer(serializers.ModelSerializer): category_name = serializers.ReadOnlyField(source='category.name') class Meta: model = Item fields = "__all__"
fuente
Trabajó el 08/08/2018 y en DRF versión 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',)
Usando el Meta
read_only_fields
podemos declarar exactamente qué campos deben ser read_only. Entonces necesitamos declarar elforeign
campo en el Metafields
(mejor ser explícito como dice el mantra: zen de python ).fuente
Solución simple
source='category.name'
dondecategory
está la clave externa y.name
su atributo.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__"
fuente
Esta solución es mejor porque no es necesario definir el modelo de origen. Pero el nombre del campo del serializador debe ser el mismo que el nombre del campo de clave externa
class ItemSerializer(serializers.ModelSerializer): category = serializers.SlugRelatedField(read_only=True, slug_field='title') class Meta: model = Item fields = ('id', 'name', 'category')
fuente