中間モデルとカスタム query_param を使用して、動的に選択されたオブジェクトをレンダリングしたいと考えています。
たとえば、次のようなクエリを作成したいとします。
http://api.url/v1/recipes/19/?location=1
query_params として送信された場所に基づいて、その成分を含むシリアル化された Recipe オブジェクトを取得します。
レシピ オブジェクト:
{
"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
よろしくお願いします!