From af0ab93980b7f11cfe8f4208879c096b7438f515 Mon Sep 17 00:00:00 2001 From: David Ray Date: Fri, 24 Feb 2017 05:57:46 -0500 Subject: [PATCH 1/2] Fixes #64; add M2M example for bread model --- bakerydemo/base/wagtail_hooks.py | 10 ++++-- .../migrations/0005_auto_20170224_1047.py | 31 +++++++++++++++++++ bakerydemo/breads/models.py | 24 ++++++++++++++ bakerydemo/templates/breads/bread_page.html | 12 +++++++ 4 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 bakerydemo/breads/migrations/0005_auto_20170224_1047.py diff --git a/bakerydemo/base/wagtail_hooks.py b/bakerydemo/base/wagtail_hooks.py index 024a4e3..2439065 100644 --- a/bakerydemo/base/wagtail_hooks.py +++ b/bakerydemo/base/wagtail_hooks.py @@ -1,7 +1,7 @@ from wagtail.contrib.modeladmin.options import ( ModelAdmin, ModelAdminGroup, modeladmin_register) -from bakerydemo.breads.models import Country, BreadType +from bakerydemo.breads.models import Country, BreadIngredient, BreadType from bakerydemo.base.models import People, FooterText ''' @@ -21,9 +21,13 @@ ''' -class BreadTypeAdmin(ModelAdmin): +class BreadIngredientAdmin(ModelAdmin): # These stub classes allow us to put various models into the custom "Wagtail Bakery" menu item # rather than under the default Snippets section. + model = BreadIngredient + + +class BreadTypeAdmin(ModelAdmin): model = BreadType @@ -35,7 +39,7 @@ class BreadModelAdminGroup(ModelAdminGroup): menu_label = 'Bread Categories' menu_icon = 'fa-suitcase' # change as required menu_order = 200 # will put in 3rd place (000 being 1st, 100 2nd) - items = (BreadTypeAdmin, BreadCountryAdmin) + items = (BreadIngredientAdmin, BreadTypeAdmin, BreadCountryAdmin) class PeopleModelAdmin(ModelAdmin): diff --git a/bakerydemo/breads/migrations/0005_auto_20170224_1047.py b/bakerydemo/breads/migrations/0005_auto_20170224_1047.py new file mode 100644 index 0000000..1f6dcfd --- /dev/null +++ b/bakerydemo/breads/migrations/0005_auto_20170224_1047.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-02-24 10:47 +from __future__ import unicode_literals + +from django.db import migrations, models +import modelcluster.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('breads', '0004_auto_20170220_0111'), + ] + + operations = [ + migrations.CreateModel( + name='BreadIngredient', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ], + options={ + 'verbose_name_plural': 'Bread ingredients', + }, + ), + migrations.AddField( + model_name='breadpage', + name='ingredients', + field=modelcluster.fields.ParentalManyToManyField(blank=True, to='breads.BreadIngredient'), + ), + ] diff --git a/bakerydemo/breads/models.py b/bakerydemo/breads/models.py index 6f1d8e1..77ff23f 100644 --- a/bakerydemo/breads/models.py +++ b/bakerydemo/breads/models.py @@ -1,6 +1,9 @@ +from django import forms from django.db import models from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +from modelcluster.fields import ParentalKey, ParentalManyToManyField + from wagtail.wagtailadmin.edit_handlers import FieldPanel, StreamFieldPanel from wagtail.wagtailcore.fields import StreamField from wagtail.wagtailcore.models import Page @@ -28,6 +31,25 @@ class Meta: verbose_name_plural = "Countries of Origin" +@register_snippet +class BreadIngredient(models.Model): + """ + Standard Django model used as a Snippet in the BreadPage model. + Demonstrates ManyToMany relationship. + """ + name = models.CharField(max_length=255) + + panels = [ + FieldPanel('name'), + ] + + def __str__(self): + return self.name + + class Meta: + verbose_name_plural = 'Bread ingredients' + + @register_snippet class BreadType(models.Model): """ @@ -68,11 +90,13 @@ class BreadPage(BasePageFieldsMixin, Page): on_delete=models.SET_NULL, related_name='+' ) + ingredients = ParentalManyToManyField('BreadIngredient', blank=True) content_panels = BasePageFieldsMixin.content_panels + [ StreamFieldPanel('body'), FieldPanel('origin'), FieldPanel('bread_type'), + FieldPanel('ingredients', widget=forms.CheckboxSelectMultiple), ] search_fields = Page.search_fields + [ diff --git a/bakerydemo/templates/breads/bread_page.html b/bakerydemo/templates/breads/bread_page.html index e8cb799..1b6f8ff 100644 --- a/bakerydemo/templates/breads/bread_page.html +++ b/bakerydemo/templates/breads/bread_page.html @@ -9,5 +9,17 @@

{{ page.title }}

{{ page.origin }}

{{ page.bread_type }}

+ {% with ingredients=page.ingredients.all %} + {% if ingredients %} +

Ingredients:

+ + {% endif %} + {% endwith %} {{ page.body }} {% endblock content %} From 619ceb6406fe6c2252484375bfc11b16e7a6a497 Mon Sep 17 00:00:00 2001 From: David Ray Date: Sat, 25 Feb 2017 03:53:31 -0500 Subject: [PATCH 2/2] wrap ingredients field within a collapsible multi field paenl --- bakerydemo/breads/models.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/bakerydemo/breads/models.py b/bakerydemo/breads/models.py index 77ff23f..b390ee0 100644 --- a/bakerydemo/breads/models.py +++ b/bakerydemo/breads/models.py @@ -2,9 +2,11 @@ from django.db import models from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger -from modelcluster.fields import ParentalKey, ParentalManyToManyField +from modelcluster.fields import ParentalManyToManyField -from wagtail.wagtailadmin.edit_handlers import FieldPanel, StreamFieldPanel +from wagtail.wagtailadmin.edit_handlers import ( + FieldPanel, MultiFieldPanel, StreamFieldPanel +) from wagtail.wagtailcore.fields import StreamField from wagtail.wagtailcore.models import Page @@ -96,7 +98,16 @@ class BreadPage(BasePageFieldsMixin, Page): StreamFieldPanel('body'), FieldPanel('origin'), FieldPanel('bread_type'), - FieldPanel('ingredients', widget=forms.CheckboxSelectMultiple), + MultiFieldPanel( + [ + FieldPanel( + 'ingredients', + widget=forms.CheckboxSelectMultiple, + ), + ], + heading="Additional Metadata", + classname="collapsible collapsed" + ), ] search_fields = Page.search_fields + [