How to set multiple ParentalKeys to Wagtail TaggedItemBase tag class

蹲街弑〆低调 提交于 2020-12-23 08:19:07

问题


I have two different page models (no subclassing, separate apps with only similar fields being common ones like "model name", "id", "parts") , let's say, cars and motorcycles. I'm making a separate page with a table of their parts (which also needs to contain columns like "id" which i assume can be a pk,"web store link", and "used by" which will show all Bike and Car models that use the part); Since they can share a few of the same parts, I want for them to be connected to the same Tag model (instead of having "CarPageTag" and "BikePageTag"); What I've tried so far :

  • I tried to make a separate app for "parts". I figured how to include that class from other app and it works with either car or motorcycle, but not both, because of this error:

AssertionError: ParentalKey(['CarsBlogApp.CarDetailPage', 'BikesBlogApp.BikeDetailPage']) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string 'self'

  • I had a simple solution working in plain Django app via ManyToManyField (but I need the wagtail autofill tag selection page in admin)
  • I looked all over django, wagtail and taggit docs
  • I looked through all youtube tutorials

Edit: adding models.py the way I thought It'll work:

PartsApp/models.py:

from django.db import models
from wagtail.core.models import Page
from wagtail.admin.edit_handlers import FieldPanel
from modelcluster.fields import ParentalKey
from taggit.models import TaggedItemBase

class PartsPage(Page):

    templates = "parts/parts_page.html"
    subpage_types = []
    max_count = 1
    parent_page_type = ['home.HomePage']
    paragraph = models.CharField(
        max_length=100,
        blank=False,
        null=False,
        help_text='Overwrites the default title',
    )

    content_panels = Page.content_panels + [
        FieldPanel("paragraph"),
    ]

    class Meta:
        verbose_name = "Needed supplies Page"
        verbose_name_plural = "Needed supplies Pages"

class PartTagPage(TaggedItemBase):
    content_object = ParentalKey(
        ['CarApp.CarDetailPage','BikeApp.BikeDetailPage'],
        related_name='tagged_items',
        on_delete=models.CASCADE,
    )

And CarsApp/models.py:

from django.db import models
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.core.fields import StreamField
from wagtail.core.models import Page
from wagtail.images.edit_handlers import ImageChooserPanel
from blocks import blocks
from modelcluster.fields import ParentalKey
from modelcluster.contrib.taggit import ClusterTaggableManager
from taggit.models import TaggedItemBase
from PartsApp.models import PartTagPage

class CarListingPage(Page):
    template = "CarsApp/car_listing_page.html"
    subpage_types = ['CarsApp.CarDetailPage']
    parent_page_type = ['home.HomePage']
    max_count = 1
    paragraph = models.CharField(
        max_length=100,
        blank=False,
        null=False,
        help_text='Overwrites the default title',
    )

    content_panels = Page.content_panels + [
        FieldPanel("paragraph"),
    ]

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        all_cars = CarsDetailPage.objects.live().public().order_by('-first_published_at')

        if request.GET.get('tag', None):
            tags = request.GET.get('tag')
            all_cars = all_cars.filter(tags__slug__in=[tags])

        context["cars"] = all_animals
        return context

class CarDetailPage(Page):
    subpage_types = []
    parent_page_types = ['CarsApp.CarsListingPage']
    tags = ClusterTaggableManager(through='PartsApp.PartTagPage', blank=True)
    name = models.CharField(
        max_length=100,
        blank=False,
        null=False,
    )
    model = models.CharField(
        max_length=100,
        blank=False,
        null=False,
    )
    car_image = models.ForeignKey(
        "wagtailimages.Image",
        blank=False,
        null=True,
        related_name="+",
        on_delete=models.SET_NULL,
    )
    description = models.TextField(max_length=10000)

    content_panels = Page.content_panels + [
        FieldPanel("model"),
        FieldPanel("name"),
        FieldPanel("description"),
        FieldPanel("tags"),
        ImageChooserPanel("car_image"),
    ]

The BikesApp/models.py is pretty much the same. Again, these do not work.


回答1:


Setting up separate CarPageTag and BikePageTag models is the solution you want (assuming they're subclasses of TaggedItemBase, as per the pattern shown in the Wagtail documentation).

TaggedItemBase is not a tag model itself - it just defines the relation between the page model and the tag model (which, in this case, is taggit.Tag, the standard tag model provided as default by the django-taggit library). Therefore, CarPageTag is setting up a relation between CarPage and taggit.Tag, and BikePageTag is setting up a relation between BikePage and taggit.Tag - both are using the same tag model.

If you did want cars and bikes to maintain their own independent set of tags, you'd need a different pattern - custom tag models.



来源:https://stackoverflow.com/questions/61719223/how-to-set-multiple-parentalkeys-to-wagtail-taggeditembase-tag-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!