- ID
- 2f37c7bc-6cb2-47ae-a513-f634e5c4cfbb
EP-627 Exp 232: Cookbook MVP
#+begin_src python
from cookbooks.models import Cookbook
from cookbooks.serializers import _auto_select_hero_image_from_sections
def _batch_pairing_featured_urls_by_id(pairing_ids: set[int]) -> dict[int, str | None]:
if not pairing_ids:
return {}
return {p.id: p.featured_img_url for p in Pairing.objects.only("id", "featured_img").filter(id__in=pairing_ids)}
def _batch_product_usable_image_urls_by_id(product_ids: set[int]) -> dict[int, str | None]:
if not product_ids:
return {}
result: dict[int, str | None] = {}
for product in Product.objects.only("id", "card_image", "large_image").filter(id__in=product_ids):
result[product.id] = product.card_image_url or product.large_image_url or None
return result
def _auto_select_cover_image_source_and_url_from_sections(
sections: list[dict[str, Any]],
) -> tuple[_CoverImageSource, str] | None:
"""Pick hero/cover image: all pairing items cookbook-wide (section then item order), then all products."""
pairing_sequence = [id_ for _, id_ in _iter_pairing_cover_sources_global(sections)]
pairing_urls = _batch_pairing_featured_urls_by_id(set(pairing_sequence))
for pid in pairing_sequence:
url = pairing_urls.get(pid)
if url:
return ("pairing", pid), url
product_sequence = [id_ for _, id_ in _iter_product_cover_sources_global(sections)]
product_urls = _batch_product_usable_image_urls_by_id(set(product_sequence))
for prod_id in product_sequence:
url = product_urls.get(prod_id)
if url:
return ("product", prod_id), url
return None
def _sections_data(cookbook):
return [
{
"position": section.position,
"items": [
{"pairing_id": item.pairing_id, "product_id": item.product_id, "position": item.position}
for item in section.items.all()
],
}
for section in cookbook.sections.all()
]
# Adjust filter as needed — e.g. all active cookbooks missing a hero image
qs = Cookbook.objects.filter(hero_image__isnull=True, is_active=True).prefetch_related("sections__items")
updated = []
for cb in qs:
url = _auto_select_hero_image_from _sections(_sections_data(cb))
if url:
updated = []
for cb in qs:
url = _auto_select_hero_image_from_sections(_sections_data(cb))
if url:
cb.hero_image = url
updated.append(cb)
Cookbook.objects.bulk_update(updated, ["hero_image"])
print(f"Updated {len(updated)} of {qs.count()} cookbooks")
#+end_src
#+begin_src python
from cookbooks.models import Cookbook
from cookbooks.serializers import _auto_select_hero_image_from_sections
cookbooks = Cookbook.objects.prefetch_related("sections__items").all()
updated = 0
skipped = 0
for cookbook in cookbooks:
sections = [
{
"position": section.position,
"items": [
{
"position": item.position,
"pairing_id": item.pairing_id,
"product_id": item.product_id,
}
for item in section.items.all()
],
}
for section in cookbook.sections.all()
]
hero_image = _auto_select_hero_image_from_sections(sections)
if hero_image:
cookbook.hero_image = hero_image
cookbook.save(update_fields=["hero_image"])
updated += 1
else:
skipped += 1
print(f"Updated: {updated}, Skipped (no image found): {skipped}")
#+end_src
Example cookbook PUT data:
#+begin_src json
{
"id": 1,
"name": "Summer Grilling",
"slug": "summer-grilling",
"description": "Light meals for warm evenings.",
"is_featured": false,
"is_active": true,
"sort_order": 0,
"cookbook_type": "thematic",
"hero_image_pairing_id": 125451,
"dietary_tag_ids": [1, 3],
"author": {
"id": 1,
"slug": "chef-jane",
"name": "Chef Jane",
"social_handle": "@chefjane"
},
"sections": [
{
"name": "Mains",
"position": 0,
"items": [
{ "item_type": "pairing", "position": 0, "pairing_id": 125451 },
{ "item_type": "pairing", "position": 1, "pairing_id": 461309 },
{ "item_type": "pairing", "position": 2, "pairing_id": 461408 },
{ "item_type": "pairing", "position": 3, "pairing_id": 464473 }
]
},
{
"name": "Add-ons",
"position": 1,
"items": [
{ "item_type": "product", "position": 0, "product_id": 696 },
{ "item_type": "product", "position": 1, "product_id": 735 },
{ "item_type": "product", "position": 2, "product_id": 1977 },
{ "item_type": "product", "position": 3, "product_id": 1961 }
]
}
]
}
#+end_src