1

これらのモデルを持つ (簡略化):

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 メソッドでカスタム マネージャーを定義し、ベースの 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))))

しかし、次の 2 つの問題があります。

  1. ユーザーをこのマネージャーに渡すことができません (テスト用にハードコードされています)
  2. この注釈が必要な場合に状況に合わせてプロキシ モデルを作成できません (以下を参照)。これは、Ingredient モデルのデフォルト マネージャーを置き換えた場合にのみ機能します。

代わりに使用される成分のデフォルト関連マネージャーの場合、このコードは機能しません。

class RecipeWithUserInfo(Recipe):
    class Meta:
        proxy = True

    objects = UserRecipesManager()
    ingredients = UserIngredientsManager()

Ingredient モデルのデフォルト マネージャーを置き換えた場合にのみ機能します (ただし、それは私が望むものではありません)。

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

0 に答える 0