在反向关系上添加序列化程序 - Django Rest Framework
Posted
技术标签:
【中文标题】在反向关系上添加序列化程序 - Django Rest Framework【英文标题】:Add Serializer on Reverse Relationship - Django Rest Framework 【发布时间】:2016-05-19 01:18:28 【问题描述】:我有一个Cart
模型和一个CartItem
模型。 CartItem
模型有一个 ForeignKey
到 Cart
模型。
使用 Django Rest Framework 我有一个视图,API 用户可以在其中显示Cart
,显然我想在响应中包含CartItem
。
我这样设置我的序列化器:
class CartSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
cartitem_set = CartItemSerializer(read_only=True)
class Meta:
model = Cart
depth = 1
fields = (
'id',
'user',
'date_created',
'voucher',
'carrier',
'currency',
'cartitem_set',
)
我的问题是第二行,cartitem_set = CartItemSerializer(read_only=True)
。
我收到 AttributeErrors 说 'RelatedManager' object has no attribute 'product'
。 ('product' 是CartItem
模型中的一个字段。如果我从CartItemSerializer
中排除产品,我只会得到一个带有下一个字段的新 AttributeError ,我会报错。
我的猜测是,出于某种原因,Django REST 框架不支持添加序列化程序来反转这样的关系。我错了吗?我该怎么做?
PS
我之所以要使用CartItemSerializer()
,是因为我想控制响应中显示的内容。
【问题讨论】:
试试cartitem_set = CartItemSerializer(read_only=True, many=True)
你的 CartItem 模型外键是什么样的?
【参考方案1】:
Ahmed Hosny 的回答是正确的。它需要将many
参数设置为True
才能工作。
CartSerializer
的最终版本如下所示:
class CartSerializer(serializers.ModelSerializer):
cartitem_set = CartItemSerializer(read_only=True, many=True) # many=True is required
class Meta:
model = Cart
depth = 1
fields = (
'id',
'date_created',
'voucher',
'carrier',
'currency',
'cartitem_set',
)
【讨论】:
我们可以将名称 caritem_set 更改为 items 吗? 您可以通过以下方式更改名称:items = CartItemSerializer(read_only=True, many=True, source='cartitem_set') 您可以从related_name 更改caritem_set 名称。在类 CartItem 中:cart = models.ForeignKey(Cart, related_name='items') ,然后在序列化程序中的“字段”中,您必须使用名称项目 是否可以使用这个解决方案然后过滤集合中返回的项目? 它的语法是什么样的?我目前已将源设置为 source='caritem_set' 以更改名称,但由于它是一个字符串,我将如何将过滤器或查询集传递给它?感谢您的帮助,马库斯。【参考方案2】:在模型中定义相关名称并在序列化器关系中使用该相关名称很重要:
class Cart(models.Model):
name = models.CharField(max_length=500)
class CartItem(models.Model):
cart = models.ForeignKey(Cart, related_name='cart_items')
items = models.IntegerField()
然后在您的序列化程序定义中使用这些确切的名称:
class CartSerializer(serializers.ModelSerializer):
cart_items = CartItemSerializer(read_only=True)
class Meta:
model = Cart
fields = ('name', 'cart_items',)
【讨论】:
这并没有解决问题。当我尝试使用cart_items = CartItemSerializer(read_only=True)
时仍然得到'RelatedManager' object has no attribute 'product'
错误
在原始问题中,他保留了隐含的相关名称:caritem_set
是的,这对于反向关系的工作非常重要【参考方案3】:
共享您的整个代码是明智的,即模型和序列化程序类。但是,也许这可以帮助调试您的错误,
我的序列化程序类
class CartItemSerializer(serializers.ModelSerializer):
class Meta:
model = CartItem
fields = ('id')
class CartSerializer(serializers.ModelSerializer):
#take note of the spelling of the defined var
_cartItems = CartItemSerializer()
class Meta:
model = Cart
fields = ('id','_cartItems')
现在是模型
class CartItem(models.Model):
_cartItems = models.ForeignKey(Subject, on_delete=models.PROTECT)
#Protect Forbids the deletion of the referenced object. To delete it you will have to delete all objects that reference it manually. SQL equivalent: RESTRICT.
class Meta:
ordering = ('id',)
class Cart(models.Model):
class Meta:
ordering = ('id',)
django-rest-framework中关系的详细概述,请参考他们的官方documentation
【讨论】:
以上是关于在反向关系上添加序列化程序 - Django Rest Framework的主要内容,如果未能解决你的问题,请参考以下文章