问题
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