我想使用中间模型和自定义 query_param 呈现动态选择的对象。
例如,我想进行这样的查询:
http://api.url/v1/recipes/19/?location=1
并根据作为 query_params 发送的位置获取带有其成分的序列化配方对象:
配方对象:
{
"id": 19,
"ingredients": [
{
"id": 35, # Product id
"name": "Tomato", # Product name
"price": 2.0, # Product price
"quantity": 3,
"supplier": 12, # Supplier at location=1
},
{
"id": 36, # Product id
"name": "Cheese", # Product name
"price": 5.0, # Product price
"quantity": 2,
"supplier": 12,
},
],
"title": "Pizza"
}
如果我更改?location=
查询参数,我想获得相同的配方但获得另一个供应商的产品。
这是我当前的架构。但任何建议都非常感谢:
class Recipe(models.Model):
title = models.CharField(max_length=255)
class IngredientRecipe(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
quantity = models.FloatField(default=0.0)
product_name = models.CharField(max_length=255)
class Meta:
unique_together = ['product_name', 'recipe']
class Supplier(models.Model):
name = models.CharField(_('Name'), max_length=255)
location = models.ForeignKey(Location, on_delete=models.CASCADE)
class Product(models.Model):
name = models.CharField(max_length=255)
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
price = models.FloatField()
我正在尝试根据供应商的位置序列化 Recipe 对象及其相关成分:
class IngredientSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
class RecipeSerializer(serializers.ModelSerializer):
ingredients = serializers.SerializerMethodField()
class Meta:
model = Recipe
fields = '__all__'
def get_ingredients(self, obj):
location_id = self.context['request'].query_params.get('location', None)
product_names = IngredientRecipe.objects.filter(recipe__id=obj.id).values_list('product_name')
# Here I got the related Products by name and if specified, the supplier's location:
if location_id:
qs = Product.objects.filter(
(Q(supplier__location_id=location_id) | Q(supplier_id__isnull=True)) &
Q(is_active=True) & Q(name__in=product_names)).values_list('id', 'name', 'price')
else:
qs = Product.objects.filter(Q(is_active=True) & Q(name__in=product_names)).values_list('id', 'name',
'price')
# Here I try to remove the duplicates and keed the cheapest price:
duplicated_qs = list(set(qs))
duplicated_qs = sorted(duplicated_qs, key=lambda tup: tup[2])
keep = set()
res = []
for sub in duplicated_qs:
if sub[1] not in keep:
res.append(sub)
keep.add(sub[1])
ingredients_ids = [item[0] for item in res]
# Once I have a product list I want to serialize it with the quantity information
# and here is where I got stuck, cause I don't know how to render the context passed.
qs = Product.objects.filter(id__in=ingredients_ids)
serializer = IngredientSerializer(qs, many=True, context={'quantity': obj.quantity})
return serializer.data
谢谢大家!