鹡鸰中的类别无法解析

Categories in wagtail not resolving

我在这里做错了什么?正如我不断收到的无法将关键字类别解析为字段错误。

这一行抛出的异常

services = services.filter(categories__category__name=category)

但是,通过代码,可以看到 service_categories 字段与 ServiceCategory 之间存在关联,通过 ServiceCategoryServicePage 关联名称为“类别”。所以我在想不应该抛出 Cannot resolve field 的异常错误。在这一点上的任何帮助将不胜感激。

def get_service_context(context):
    context['all_categories'] = ServiceCategory.objects.all()
    context['root_categories'] = ServiceCategory.objects.filter(
    parent=None,
    ).prefetch_related(
    'children',
    ).annotate(
    service_count=Count('servicepage'),
    )
    return context

class ServiceIndexPage(Page):
    header_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    heading = models.CharField(max_length=500, null=True, blank=True)
    sub_heading = models.CharField(max_length=500, null=True, blank=True)
    body = RichTextField(null=True, blank=True)

    def get_context(self, request, category=None, *args, **kwargs):
        context = super(ServiceIndexPage, self).get_context(request, *args, **kwargs)

        services = self.get_children().live().order_by('-first_published_at') #.prefetch_related('categories', 'categories__category')

        if category is None:
            if request.GET.get('category'):
                category = get_object_or_404(ServiceCategory, slug=request.GET.get('category'))
        if category:
            if not request.GET.get('category'):
                category = get_object_or_404(ServiceCategory, slug=category)
            services = services.filter(categories__category__name=category)

        # Pagination
        page = request.GET.get('page')
        page_size = 10
        if hasattr(settings, 'SERVICE_PAGINATION_PER_PAGE'):
        page_size = settings.SERVICE_PAGINATION_PER_PAGE

        if page_size is not None:
            paginator = Paginator(services, page_size)  # Show 10 services per page
            try:
                services = paginator.page(page)
            except PageNotAnInteger:
                services = paginator.page(1)
            except EmptyPage:
                services = paginator.page(paginator.num_pages)


        context['services'] = services
        context['category'] = category
        context = get_service_context(context)

        return context


@register_snippet
class ServiceCategory(models.Model):
    name = models.CharField(max_length=250, unique=True, verbose_name=_('Category Name'))
    slug = models.SlugField(unique=True, max_length=250)
    parent = models.ForeignKey('self', blank=True, null=True, related_name="children")
    date = models.DateField(auto_now_add=True, auto_now=False, null=True, blank=True)
    description = RichTextField(blank=True)

    class Meta:
        ordering = ['-date']
        verbose_name = _("Service Category")
        verbose_name_plural = _("Service Categories")

    panels = [
        FieldPanel('name'),
        FieldPanel('parent'),
        FieldPanel('description'),
    ]

    def __str__(self):
        return self.name

    def clean(self):
        if self.parent:
            parent = self.parent
            if self.parent == self:
                raise ValidationError('Parent category cannot be self.')
            if parent.parent and parent.parent == self:
                raise ValidationError('Cannot have circular Parents.')

    def save(self, *args, **kwargs):
        if not self.slug:
            slug = slugify(self.name)
            count = ServiceCategory.objects.filter(slug=slug).count()
            if count > 0:
                slug = '{}-{}'.format(slug, count)
            self.slug = slug
        return super(ServiceCategory, self).save(*args, **kwargs)

class ServiceCategoryServicePage(models.Model):
    category = models.ForeignKey(ServiceCategory, related_name="+", verbose_name=_('Category'))
    page = ParentalKey('ServicePage', related_name='categories')
    panels = [
        FieldPanel('category'),
    ]



class ServicePage(Page):
    header_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name=_('Header image')
    )
    service_title = models.CharField(max_length=300, null=True, blank=True)
    body = StreamField([
        ('h1', CharBlock(icon="title", classanme="title")),
        ('h2', CharBlock(icon="title", classanme="title")),
        ('h3', CharBlock(icon="title", classanme="title")),
        ('h4', CharBlock(icon="title", classanme="title")),
        ('h5', CharBlock(icon="title", classanme="title")),
        ('h6', CharBlock(icon="title", classanme="title")),
        ('paragraph', RichTextBlock(icon="pilcrow")),
        ('aligned_image', ImageBlock(label="Aligned image", icon="image")),
        ('pullquote', PullQuoteBlock()),
        ('raw_html', RawHTMLBlock(label='Raw HTML', icon="code")),
        ('embed', EmbedBlock(icon="code")),
    ])
    date = models.DateField("Post date")
    service_categories = models.ManyToManyField(ServiceCategory, through=ServiceCategoryServicePage, blank=True)

    feed_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name=_('Feed image')
    )

    search_fields = Page.search_fields + [
        index.SearchField('body'),
        index.SearchField('service_title'),
        index.SearchField('title'),]


    def get_absolute_url(self):
        return self.url


    def get_service_index(self):
        # Find closest ancestor which is a service index
        return self.get_ancestors().type(ServiceIndexPage).last()


    def get_context(self, request, *args, **kwargs):
        context = super(ServicePage, self).get_context(request, *args, **kwargs)
        context['services'] = self.get_service_index().serviceindexpage
        context = get_service_context(context)
        return context

    class Meta:
        verbose_name = _('Service page')
        verbose_name_plural = _('Services pages')

    parent_page_types = ['services.ServiceIndexPage']


ServicePage.content_panels = [
    FieldPanel('title', classname="full title"),
    FieldPanel('service_title'),
    ImageChooserPanel('header_image'),
    FieldPanel('date'),
    InlinePanel('categories', label=_("Categories")),
    StreamFieldPanel('body'),
    ImageChooserPanel('feed_image'),
]

当您拨打self.get_children()在线时:

services = self.get_children().live().order_by('-first_published_at')

结果是 Page 个对象的查询集,其中仅包含所有页面类型共有的基本字段,例如 title - 因此,无法根据 categories。发生这种情况是因为 Wagtail 无法知道 ServiceIndexPage 的子页面都是 ServicePages - 请参阅 以获得更完整的解释。

但是,您可以按如下方式重写此行:

services = ServicePage.objects.child_of(self).live().order_by('-first_published_at')

我们可以确定查询集 ServicePage.objects.child_of(self) 将仅包含 ServicePage 个对象,因此现在应该可以过滤 categories