Wagtail Tutorial Series:
To learn more about Wagtail CMS, please check Build Blog With Wagtail CMS (4.0.0)
- Create Wagtail Project
- Modern Frontend Techs for Wagtail
- Dockerizing Wagtail App
- Add Blog Models to Wagtail
- How to write Wagtail page template
- Create Stylish Wagtail Pages with Tailwind CSS
- How to use StreamField in Wagtail
- Wagtail Routable Page
- Add Pagination Component to Wagtail
- Customize Wagtail Page URL
- Add Full Text Search to Wagtail
- Add Markdown Support to Wagtail
- Add LaTeX Support & Code Highlight In Wagtail
- How to Build Form Page in Wagtail
- How to Create and Manage Menus in Wagtail
- Wagtail SEO Guide
- Online Demo http://wagtail-blog.accordbox.com/
- Source code: https://github.com/AccordBox/wagtail-tailwind-blog
Wagtail Tips:
- Wagtail Tip #1: How to replace ParentalManyToManyField with InlinePanel
- Wagtail Tip #2: How to Export & Restore Wagtail Site
Write style in Wagtail:
- How to use SCSS/SASS in your Django project (Python Way)
- How to use SCSS/SASS in your Django project (NPM Way)
Other Wagtail Topics:
Introduction
After reading this Wagtail tip article, you will get:
- The problem
ParentalManyToManyField
might bring to your project. - How to replace
ParentalManyToManyField
using Wagtail InlinePanel
Step 1 - Add ParentalManyToManyField to your project
In Wagtail doc, ParentalManyToManyField
is imported to help user build relationship between category and page. Below is the code snippet
class PostPage(Page):
categories = ParentalManyToManyField('blog.BlogCategory', blank=True)
content_panels = Page.content_panels + [
FieldPanel('categories', widget=forms.CheckboxSelectMultiple),
]
@register_snippet
class BlogCategory(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=80)
panels = [
FieldPanel('name'),
FieldPanel('slug'),
]
def __str__(self):
return self.name
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"
As you can see, we register BlogCategory
as Wagtail snippet so we can add, edit in Wagtail snippet admin.
The magic here is the categories = ParentalManyToManyField('blog.BlogCategory', blank=True)
and code in content_panels
, now we can manage category of the post page using checkbox list.
Step 2 - Find out the problem
Cheers, now you have made Category work in your Wagtail project. but there are two problems with this solution.
- If the category list is very long, is there a way to solve this problem? Can we just add category that we want to choose? What if you want to do nested Category?
- If you want to migrate the data of your Wagtail project to another place using
Django dumpdata&loaddata
, you will find out the category are gone even there is no error during the process.
To clarify the second point, you can do this
./manage.py dumpdata --natural-foreign --indent 2 -e auth.permission -e contenttypes -e wagtailcore.groupcollectionpermission -e wagtailimages.rendition -e sessions > data.json
# config to use new db
./manage.py migrate
./manage.py loaddata data.json
./manage.py runserver
Then you can check in Wagtail admin, you will see the category of the post is gone.
Note: You can get a Github project at the bottom of this article to test on your own.
If you check the data.json by yourself, you will see even we use natual-foreign
to dump the data, the category info of page is still pk. I think that is why the loaddata fail here.
The only way to solve this problem is to write code to migrate data.
Step 3 - How to replace ParentalManyToManyField
What if you want to replace ParentalManyToManyField? Here I will show you how:
class PostPage(Page):
content_panels = Page.content_panels + [
InlinePanel('categories2', label='category'),
]
class BlogPageBlogCategory(models.Model):
page = ParentalKey('blog.PostPage', on_delete=models.CASCADE, related_name='categories2')
blog_category = models.ForeignKey(
'blog.BlogCategory', on_delete=models.CASCADE, related_name='blog_pages')
panels = [
SnippetChooserPanel('blog_category'),
]
class Meta:
unique_together = ('page', 'blog_category')
Here we create BlogPageBlogCategory
as intermediate model, we can also add other fields as we like in the future.
The page
is ForeignKey to our PostPage and blog_category
is ForeignKey to BlogCategory.
unique_together
here make sure no duplicate category are saved for one post.
Note: I use field name categories2
to distinguish with previous categoryies
, but you should replace when copy&paste.
After you are done, please migrate your database and modify your template file to make that work.
If you have problem in this part, just feel free to contact me and I'd like to help if I have time.
Step 4 - Check again in Wagtail admin
With InlinePanel
, now category is more flexible, and we can add more settings to let us search, add category , or reorder category.
What is more, if you want to build nested Category in your Wagtail project, you can also use this way (I will talk about it in another blog).
Conclusion
You can get all source code of this article here Wagtail ParentalManyToManyField Example
In this Wagtail tip, we learned why we need to avoid using ParentalManyToManyField
and how to replace by creating intermediate model and InlinePanel
.
Wagtail Tutorial Series:
To learn more about Wagtail CMS, please check Build Blog With Wagtail CMS (4.0.0)
- Create Wagtail Project
- Modern Frontend Techs for Wagtail
- Dockerizing Wagtail App
- Add Blog Models to Wagtail
- How to write Wagtail page template
- Create Stylish Wagtail Pages with Tailwind CSS
- How to use StreamField in Wagtail
- Wagtail Routable Page
- Add Pagination Component to Wagtail
- Customize Wagtail Page URL
- Add Full Text Search to Wagtail
- Add Markdown Support to Wagtail
- Add LaTeX Support & Code Highlight In Wagtail
- How to Build Form Page in Wagtail
- How to Create and Manage Menus in Wagtail
- Wagtail SEO Guide
- Online Demo http://wagtail-blog.accordbox.com/
- Source code: https://github.com/AccordBox/wagtail-tailwind-blog
Wagtail Tips:
- Wagtail Tip #1: How to replace ParentalManyToManyField with InlinePanel
- Wagtail Tip #2: How to Export & Restore Wagtail Site
Write style in Wagtail:
- How to use SCSS/SASS in your Django project (Python Way)
- How to use SCSS/SASS in your Django project (NPM Way)
Other Wagtail Topics: