The breads models provide functionality for managing bread products in the bakery demo. This includes bread pages with ingredients, types, countries of origin, and a paginated index page.
Type classification for the bread (e.g., sourdough, baguette). References BreadType snippet. Uses related_name="+" to avoid reverse relation conflicts.
class BreadsIndexPage(Page): """ Index page for breads. This is more complex than other index pages on the bakery demo site as we've included pagination. We've separated the different aspects of the index page to be discrete functions to make it easier to follow """ introduction = models.TextField(help_text="Text to describe the page", blank=True) image = models.ForeignKey( "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", help_text="Landscape mode only; horizontal width between 1000px and 3000px.", )
class Country(models.Model): """ A Django model to store set of countries of origin. It is made accessible in the Wagtail admin interface through the CountrySnippetViewSet class in wagtail_hooks.py. This allows us to customize the admin interface for this snippet. In the BreadPage model you'll see we use a ForeignKey to create the relationship between Country and BreadPage. This allows a single relationship (e.g only one Country can be added) that is one-way (e.g. Country will have no way to access related BreadPage objects). """ title = models.CharField(max_length=100) sort_order = models.IntegerField(null=True, blank=True, db_index=True) api_fields = [ APIField("title"), ] def __str__(self): return self.title class Meta: verbose_name = "country of origin" verbose_name_plural = "countries of origin"
Snippet model for bread ingredients with draft state and revision support.
Full Class Definition
class BreadIngredient(Orderable, DraftStateMixin, RevisionMixin, models.Model): """ A Django model to store a single ingredient. It is made accessible in the Wagtail admin interface through the BreadIngredientSnippetViewSet class in wagtail_hooks.py. This allows us to customize the admin interface for this snippet. We use a piece of functionality available to Wagtail called the ParentalManyToManyField on the BreadPage model to display this. The Wagtail Docs give a slightly more detailed example https://docs.wagtail.org/en/stable/getting_started/tutorial.html#categories """ name = models.CharField(max_length=255) revisions = GenericRelation( "wagtailcore.Revision", content_type_field="base_content_type", object_id_field="object_id", related_query_name="bread_ingredient", for_concrete_model=False, ) panels = [ FieldPanel("name"), ] api_fields = [ APIField("name"), ] def __str__(self): return self.name class Meta: verbose_name = "bread ingredient" verbose_name_plural = "bread ingredients" ordering = ["sort_order", "name"]
class BreadType(RevisionMixin, models.Model): """ A Django model to define the bread type It is made accessible in the Wagtail admin interface through the BreadTypeSnippetViewSet class in wagtail_hooks.py. This allows us to customize the admin interface for this snippet. In the BreadPage model you'll see we use a ForeignKey to create the relationship between BreadType and BreadPage. This allows a single relationship (e.g only one BreadType can be added) that is one-way (e.g. BreadType will have no way to access related BreadPage objects) """ title = models.CharField(max_length=255) revisions = GenericRelation( "wagtailcore.Revision", content_type_field="base_content_type", object_id_field="object_id", related_query_name="bread_type", for_concrete_model=False, ) panels = [ FieldPanel("title"), ] api_fields = [ APIField("title"), ] def __str__(self): return self.title class Meta: verbose_name = "bread type" verbose_name_plural = "bread types"
# Get all breads with their ingredientsfrom bakerydemo.breads.models import BreadPage, BreadIngredient, BreadTypebreads = BreadPage.objects.live()for bread in breads: print(f"{bread.title} ({bread.bread_type})") print(f"Origin: {bread.origin}") print("Ingredients:") for ingredient in bread.ordered_ingredients: print(f" - {ingredient.name}")# Create a new bread ingredientingredient = BreadIngredient( name="Whole Wheat Flour", sort_order=1)ingredient.save()# Get all bread typestypes = BreadType.objects.all()for bread_type in types: print(bread_type.title)