django - 从相关模型中读取特定领域
问题描述
我有这个简单的关系设置和工作,但现在我需要修改它并且遇到了问题。以前是“获取与当前用户相关的产品名称”,现在是“获取与当前用户相关的产品名称、开始日期和结束日期”。
对于前者,我通过以下方式得到它:
# models.py
class Products(models.Model):
id = models.AutoField(primary_key=True)
code = models.CharField(unique=True, max_length=16)
name = models.CharField(max_length=255, blank=True, null=True)
short_name = models.CharField(max_length=128)
start_date= models.DateField(blank=True, null=True)
end_date = models.DateField(blank=True, null=True)
users = models.ManyToManyField(User, through='UserToProduct')
stage = models.CharField(max_length=32, blank=True, null=True)
def __str__(self):
return self.name
class Meta:
db_table = 'Products'
class UserToProduct(models.Model):
user = models.ForeignKey(User, related_name='user_product', db_column='user_id', null=True, on_delete=models.CASCADE)
product = models.ForeignKey(Product, related_name='product', db_column='product_id', null=True, on_delete=models.CASCADE)
stamp = models.DateTimeField(blank=True, null=True)
def __str__(self):
return u'%s' % self.product
class Meta:
db_table = 'User_to_Product'
unique_together = ('user', 'product')
ordering = ['-product']
并使用以下序列化程序:
# serializers.py
class ProductListSerializer(serializers.ModelSerializer):
product = serializers.CharField()
product_id = serializers.IntegerField()
class Meta:
model = Products
fields = [
'product_id',
'product'
]
class GetHomeSerializer(serializers.Serializer):
id = serializers.IntegerField()
product_list = ProductListSerializer(required=False, many=True)
def validate(self, data):
if data:
data['product_list'] = UserToProduct.objects.filter(user=data['id']).prefetch_related('product').filter(product__stage='active')
return data
现在我正在尝试将我的查询修改为以下内容:
class ProductListSerializer(serializers.ModelSerializer):
product = serializers.CharField()
product_id = serializers.IntegerField()
start_date = serializers.DateField()
class Meta:
model = UserToProduct
fields = [
'product_id',
'product',
'start_date'
]
... #stuff in between
data['product_list'] = UserToProduct.objects.filter(user=data['id']).prefetch_related('product').filter(product__stage='active').values('product_id', 'product', 'product__start_date')
并将该字段添加到ProductListSerializer
. 我得到错误:
KeyError: "Got KeyError when attempting to get a value for field `start_date` on serializer `ProductListSerializer`.\nThe serializer field might be named incorrectly and not match any attribute or key on the `dict` instance.\nOriginal exception text was: 'start_date'."
还尝试了以下方法:
class ProductListSerializer(serializers.ModelSerializer):
id= serializers.IntegerField()
name = serializers.CharField()
start_date = serializers.DateField()
class Meta:
model = Products
fields = [
'id',
'name',
'start_date'
]
... #stuff in between
data['product_list'] = UserToProduct.objects.filter(user=data['id']).prefetch_related('product').filter(product__stage='active').values('product__id', 'product__name', 'product__start_date')
这会导致相同的错误,即id
出现错误的字段。
尝试替换values()
为.select_related(products__product)
,这只会导致:
Choices are: user, product
试过了.select_related(product)
,它说:
Original exception text was: 'UserToProduct' object has no attribute 'name'.
这里给出了什么?
解决方案
使用source
参数将嵌套关系指定为,
class ProductListSerializer(serializers.ModelSerializer):
product = serializers.CharField()
product_id = serializers.IntegerField()
start_date = serializers.DateField(source='product.start_date') # chage is here <<<<<
class Meta:
model = UserToProduct
fields = [
'product_id',
'product',
'start_date'
]
而且,你的validate()
方法不好,不应该是这样。如果不满足某些特定条件,则validate 方法应该是raise
一些。例子:ValidationError
class SampleSerializer(serializers.Serializer):
name = serializers.CharField()
age = serializers.IntegerField()
def validate(self, attrs):
if attrs['age']: # if age is there
if attrs['age'] < 18: # validation check for
raise serializers.ValidationError("You are under 18. Not allowed")
return attrs
def validate_age(self, age):
if age < 18: # validation check for
raise serializers.ValidationError("You are under 18. Not allowed")
return age
推荐阅读
- javascript - 无法使用从 Fetch API 返回的数据
- javascript - 您可以通过函数表达式实现 Javascript 类吗?
- c++ - 使用 Visual Studio 在 C++ 中获取异常行号
- python - 我对 scipy.signal.lfilter() 做错了什么?
- python - 如何绘制图像的有限区域?
- python - 让 TensorFlow 在 ARM Mac 上使用 GPU
- android - GradientDrawable 圆角半径不起作用
- r - 删除列中具有重复测量的变量中至少一个 NA 值的所有个体
- typing - 在 mypy 中使用函数签名作为可调用参数的类型
- python-3.x - Dask 是否通过使用 parquet 分区来执行 groupby 任务?