基于另一个模型的值对 Django 模型之间的复杂关系进行建模

时间:2021-07-21 14:55:55

标签: django django-models django-rest-framework

我正在尝试为包含一系列成分的食谱建模。在这些成分中,价格字段取决于另一个模型的值(供应商的位置)。例如,我的食谱可能包含:水、牛肉和盐。

每种成分都有一个价格,这取决于用户所在的位置。 IE。如果我的用户来自德克萨斯州,牛肉和水的价格可能会发生变化,因此食谱的总价也会发生变化。

现在我正在使用以下方法:


class Product(models.Model):
    name = models.CharField(_('Name'), max_length=255, help_text=_('Product name'))   
    price = models.FloatField(_('Sale price'), default=0)
    supplier = models.ForeignKey(Supplier, blank=True, null=True, related_name='supplier_products',
                                 on_delete=models.CASCADE)
 
class IngredientRecipe(models.Model):
    product_name = models.CharField(_('Name'), max_length=255, help_text=_('Product name'), blank=True)
    recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE, related_name='ingredients')
    quantity = models.FloatField(_('Quantity'))

class Recipe(models.Model):
    user = models.ForeignKey(User, null=True, on_delete=models.CASCADE, related_name='user_recipes')
    title = models.CharField(_('Recipe title'), max_length=255, help_text=_('Recipe. Example: american chicken salad'),
                             blank=True)

我使用此模型和序列化程序来显示与所选位置对应的价格:

class VerySimpleRecipeSerializer(serializers.ModelSerializer):
    cost = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = Recipe
        fields = ['id', 'title', 'cost',]

    def get_cost(self, obj):
        ingredients_names = obj.ingredients.values('product_name', 'quantity')
        total_price = 0
        try:
            location_id = self.context['request'].query_params.get('location', None)
            products = Product.objects.annotate(min_price=Min('price')).filter(
                Q(supplier__location_id=location_id) & Q(name__in=[x.get('product_name', None) for x in ingredients_names]),
                is_active=True, min_price__lte=F('price')).order_by()
        except KeyError:
            products = Product.objects.annotate(min_price=Min('price')).filter(
                Q(name__in=[x.get('product_name', None) for x in ingredients_names]), is_active=True
                min_price=F('price')).order_by()

        for ingredient in ingredients_names:
            product = products.filter(name=ingredient.get('product_name', None)).last()
            if product:
                total_price += ingredient.get('quantity', 0) * product.price
        return total_price

似乎可以,但是当我添加更多 SerializerMethods 来计算基于供应商位置的其他字段时,性能会受到很大影响。此外,我在使用 @cached_properties 时遇到问题,因为我无法在模型的方法中获取 self.context['request'].query_params.get('location', None)

我希望有人能给我另一个观点来解决这个问题。

先谢谢你!

0 个答案:

没有答案
相关问题