从相关模型中读取特定领域
Reading in specific fields from related model
我已经建立并运行了这个简单的关系,但现在我需要修改它并且 运行 遇到了问题。之前是 "get the names of products related to the current user," 但现在是 "get the names, start dates, and ending dates of products related to the current user."
对于前者,我是通过以下方式得到它的:
# 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
是有错误的字段。
尝试用 .select_related(products__product)
替换 values()
,结果是:
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(<b>source='product.start_date'</b>) # chage is here <<<<<
class Meta:
model = UserToProduct
fields = [
'product_id',
'product',
'start_date'
]
而且,你的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
我已经建立并运行了这个简单的关系,但现在我需要修改它并且 运行 遇到了问题。之前是 "get the names of products related to the current user," 但现在是 "get the names, start dates, and ending dates of products related to the current user."
对于前者,我是通过以下方式得到它的:
# 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
是有错误的字段。
尝试用 .select_related(products__product)
替换 values()
,结果是:
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(<b>source='product.start_date'</b>) # chage is here <<<<<
class Meta:
model = UserToProduct
fields = [
'product_id',
'product',
'start_date'
]
而且,你的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