Understand Wagtail SourceCode - wagtail

when reviewing the Wagtail sourcecode:
class Page(AbstractPage, index.Indexed, ClusterableModel, metaclass=PageBase):
title = models.CharField(
verbose_name=_('title'),
max_length=255,
help_text=_("The page title as you'd like it to be seen by the public")
)
slug = models.SlugField(
verbose_name=_('slug'),
allow_unicode=True,
max_length=255,
help_text=_("The name of the page as it will appear in URLs")
)
I do not understand _('title') & _('slug'), can anyone share some hints ?

The "_(...)" function will be imported from the top of the file as:
from django.utils.translation import gettext_lazy as _
From the Django docs:
These functions store a lazy reference to the string – not the actual
translation. The translation itself will be done when the string is
used in a string context, such as in template rendering.
https://docs.djangoproject.com/en/3.2/topics/i18n/translation/#lazy-translation

Related

Get src of image file stored in dtabase?

I have a dessert model in django with a property called picture:
class Dessert(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(max_length=1000, blank=True)
picture = models.ImageField(upload_to ='uploads/desserts-pics/', max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2, validators=[MinValueValidator(1)])
tags = models.ManyToManyField(Tag, related_name="desserts")
def __str__(self):
return self.name + " ($" + str(self.price) +")"
And i want to show the image in my front with react, like this:
<img src={dessert.picture}>
dessert is an instance of the Dessert model witch i got from a request, but the picture is a file not an image, how the hell do i get the src? sorry, i know it's a silly question but i didn't find the answer anywhere else.
I am not a react user. However, the HTML tag you show (if it's similar) would need some changes to display the image field of your model instance. Let's assume you have a simple view that shows a dessert, like...
def show_dessert(request):
d = Dessert.objects.get(id=1)
context = {'d':d}
return render(request, "pages/my_template.html", context)
With d as your desert object, you would show the image using .url, like:
<img src="{{d.picture.url}}">
Find more information on serving files and photos in Django docs here.
This answer also assumes you have correctly configured your static files settings. More info about that here.

In Wagtail, get counts of Pages in each Tag, but only counting live() Pages

In Wagtail I want to get a list of Tags, each with a count of the number of Pages tagged, but only counting live() pages.
Let's say I have this set-up, from the docs:
from django.db import models
from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey
from taggit.models import TagBase, ItemBase
class BlogTag(TagBase):
class Meta:
verbose_name = "blog tag"
verbose_name_plural = "blog tags"
class TaggedBlog(ItemBase):
tag = models.ForeignKey(
BlogTag, related_name="tagged_blogs", on_delete=models.CASCADE
)
content_object = ParentalKey(
to='demo.BlogPage',
on_delete=models.CASCADE,
related_name='tagged_items'
)
class BlogPage(Page):
...
tags = ClusterTaggableManager(through='demo.TaggedBlog', blank=True)
I can get a list of BlogTags, each with a count of the number of BlogPages tagged with it, by doing this (I think that's what it's doing...?):
from django.db.models.aggregates import Count
BlogTag.objects.annotate(count=Count("tagged_blogs"))
But I can't get my head round how to filter this to only count pages that are live() (or that have some other Page-related quality).
I think this two-stage process works. First get all the Page IDs filtered by whatever you need, like live(). Then filter the BlogTags by those
page_ids = Page.objects.live().values_list("id", flat=True)
BlogTag.objects.filter(
tagged_blogs__content_object_id__in=page_ids
).annotate(count=Count("tagged_blogs"))
I thought I'd have to filter the second query to only get BlogTags with a count greater than 0 but it doesn't include tags with no pages anyway.
I don't know if this is the best solution, given it starts with having to get a list of all live pages, so maybe there's a better solution?

Slug translation issue in wagtail

I've been around the Internet the whole day reading about the following issue, in wagtail if I registered the following model for translation like this:
class RecipientsPage(Page):
intro = RichTextField(null=True, blank=True)
banner_image = models.ForeignKey(
"wagtailimages.Image",
on_delete=models.SET_NULL,
related_name="+",
null=True,
blank=False,
help_text=_("the Image shouldn't exceed ") + "1350 * 210",
)
content_panels = Page.content_panels + [
FieldPanel("intro"),
ImageChooserPanel("image"),
]
this is how I registered the model:
#register(RecipientsCountriesPage)
class RecipientsCountriesPage(TranslationOptions):
fields = ("intro",)
It causes a problem, because like this I'll have two slugs following the two titles (The original English one and the Arabic translated one), if I change the Arabic slug manually to equal the English one it'll work, but it's not efficient to do so for each page manually
I've read about the issue a lot like in here:
https://github.com/infoportugal/wagtail-modeltranslation/issues/195
I've found also the following question with no answer
How do you translate the slug value of a page?
I've also read that I can override some of the wagtail Page methods but without further explanation and I'm a bit lost, what's the best way to overcome this issue?
I did it using Django signals
#receiver(pre_save)
def set_arabic_slug_on_new_instance(sender, instance, **kwargs):
if isinstance(instance, Page):
instance.slug_ar = instance.slug_en

How would I extend the wagtailmenus LinkPage to add a generic picture

I have been using the AbstractLinkPage model from wagtailmenus in my site for a while now. I find it quite useful.
Source: wagtailmenus AbstractLinkPage model
My site is building cards from children pages and adds banner images from children pages automatically to these cards. Some of the children pages are LinkPages.
How can I extend the subclassed LinkPage (from AbstractLinkPage) to add a generic image which can be used as a card image?
I have added the field:
class LinkPage(AbstractLinkPage):
card_image = models.ForeignKey(
get_image_model_string(),
null=True,
blank=True,
related_name='+',
on_delete=models.SET_NULL,
)
content_panels = AbstractLinkPage.content_panels + [
ImageChooserPanel("card_image"),
]
However the image card_image field does not show in the admin interface.
Any help to move forward is appreciated.
Wagtailmenus uses it's own tabbed interface (in wagtailmenus.panels):
linkpage_tab = ObjectList(
linkpage_panels, heading=_("Settings"), classname="settings"
)
linkpage_edit_handler = TabbedInterface([linkpage_tab])
So what you have to do is to create a new ObjectList:
from wagtailmenus.panels import linkpage_panels
from wagtail.admin.edit_handlers import ObjectList, TabbedInterface
my_linkpage_tab = ObjectList(
linkpage_panels + [ImageChooserPanel("card_image")],
heading=_("Settings"), classname="settings"
)
.. and add it to your class:
class LinkPage(AbstractLinkPage):
[..]
edit_handler = TabbedInterface([my_linkpage_tab])

Wagtail Custom Pages?

I'm totally new to Wagtail/ Django.
Here's what I am trying to achieve:
I'd like to have an ability in the backend of my Wagtail CMS install to create 'pages' or 'posts' that follow a strict template.
The template would have custom fields like 'header' and aim content' etc.
I'm sure that this is possible, I'd just be interested to know how I'd go about achieving this?
For example, does anyone know if Wagtail has a plugin or other to enable this?
Thanks for all help/ direction.
You want to create pages and posts that follow a strict template: that's exactly what Django and Wagtail let you do. But there's one catch: Wagtail takes this a step further and lets you move entire sections of a page — these are called Streamfields. It's an amazing feature, to be honest.
Here's an example to get you started (note: this is untested and not linted)
# -*- coding: utf-8 -*-
"""Basic Page model."""
from django.db import models
from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel, StreamFieldPanel
from wagtail.core.fields import StreamField
from wagtail.core.models import Page
from your_custom_app.streams import streamfields
class BasicPage(Page):
"""A basic page class."""
template = "templates/pages/basic_page.html"
parent_page_type = ["pages.HomePage", "pages.BasicPage"]
subpage_types = ["pages.BasicPage"]
header = models.CharField(max_length=100)
content = StreamField(
('streamfield_name', streamfields.CustomStreamfield()),
# ... More streams
null=True,
blank=True,
)
# Other additional fields you want on your page.
# Panels are how you lay out your pages in the /admin/
content_panels = [
FieldPanel("title", classname="full title"),
FieldPanel("header"),
# FieldPanel("other_fields"),
StreamFieldPanel("content"),
]
settings_panels = Page.settings_panels + [] # Custom settings panel
promote_panels = Page.promote_panels + [] # Custom promote panel
class Meta:
"""Meta information."""
verbose_name = "Basic Page"
verbose_name_plural = "Basic Pages"
You can also download and setup the Wagtail Bakery Demo, it has a lot of great examples in it.

Resources