关于相关模型的Django注释

时间:2016-08-20 11:20:37

标签: django django-queryset models calculated-field django-related-manager

拥有这些模型(简化):

class UserProfile(models.Model):  
    user = models.OneToOneField(User)
    products = models.ManyToManyField(Product, through='UserProduct')


class Product(models.Model):
    title = models.CharField(max_length=100, blank=False)


class UserProduct(models.Model):
    user = models.ForeignKey(UserProfile)
    product = models.ForeignKey(Product)


class Recipe(models.Model):
    ingredients = models.ManyToManyField(Product, through='Ingredient')


class Ingredient(models.Model):
    product = models.ForeignKey(Product)
    recipe = models.ForeignKey(Recipe)

在某些情况下,我需要获得每个成分上标记的食谱清单,“用户是否拥有该产品。”并且,根据给定的用户,可能是其他计算字段。 我想要的例子:

>>> Recipe.objects.get_for_user(user=user)[0].ingredients[0].is_user_have
>>> True

但是,当然,在其他情况下,我不希望该领域附加成分。

我明白我需要自定义经理。但直截了当的解决方案 - 将“is_user_have”添加为Ingredient模型的属性,使用get_for_user方法定义自定义管理器,调用base get_queryset,然后在for循环中填充该字段 - 不起作用。

更新1
我想出了如何获得我想要的注释,这是我的成分定制经理:

class UserIngredientsManager(models.Manager):
    def get_queryset(self):
    result = super(UserIngredientsManager, self).get_queryset()

    return (result
        .annotate(
            user_have_count=models.Count(
                models.Case(
                    models.When(
                        # Hardcoded !!!
                        product__userproduct__user_id=1,
                        then=True),
                    output_field=models.IntegerField())))
        .annotate(
            is_user_have=models.Case(
                models.When(
                    user_have_count__gt=0,
                    then=models.Value(True)),
                output_field=models.BooleanField(),
                default=models.Value(False))))

但有两个问题:

  1. 我无法将用户传递给此经理(其硬编码用于测试)
  2. 当我需要这个注释时,我不能为situtations创建代理模型(见下文),它只适用于我在Ingredient模型上替换默认管理器。
  3. 此代码不起作用,因为使用成分默认相关管理器:

    class RecipeWithUserInfo(Recipe):
        class Meta:
            proxy = True
    
        objects = UserRecipesManager()
        ingredients = UserIngredientsManager()
    

    仅当我在Ingredient模型上替换默认管理器时才有效(但这不是我想要的):

    class Ingredient(models.Model):
        ...
        objects = UserIngredientsManager()
    

0 个答案:

没有答案