从相关模型中读取特定领域

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