Wagtail - made custom slug but page not serving from it - django

I made a custom slug because the default slug does not meet my needs and already set the url_path with the new slug. But the page is still serving with the default slug.
I've already set the url_path with the following code:
def set_url_path(self, parent):
super().set_url_path(self)
if parent:
self.url_path = parent.url_path + self.custom_slug + '/'
return self.url_path
But when I publish the page, it still returns the page with the default slug value. I thought Wagtail serves the page on url_path. What other methods or variables do I have to override for the page to be served on my custom slug?

You can not switch to some other field then slug. The slug field is used all over Wagtail to lookup url's, queries and serve the correct page.
You can programatically set the slug value to something else. The Page.slug definition is:
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 e.g
http://example.com/blog/[my-slug]/")
)
The field accepts unicode chars.
You should override Page._get_autogenerated_slug, Page.full_clean and Page.clean. Change how slug is handled and adopt to your wishes.
Note you can use some other field eg my_custom_slug as an input and use this value in your custom methods. Eg: self.my_custom_slug. However, the final result has to be stored in the slug field.
You can remove the slug field from the content panels to remove it from the admin user interface.
Finally, the slug has to comply with https://www.rfc-editor.org/rfc/rfc1738

Related

Wagtail: Limit choice dynamically based on current object

How can I limit the choices for the districtobject field in wagtail admin?
class DistrictPage(Page):
districtobject = models.ForeignKey(DistrictTranslated, on_delete=models.SET_NULL, null=True, blank=True)
I know that I can use "limit_choices_to" for basic limitations with Q. But I want to use a more dynamic approach which allows me to use the "content" of the current object. (Like self.attribute ... etc)
For example:
def my_limit_function(self):
1. get parent page
2. read date from parent page and extract this information for a filter query
I don't think you can do that in the Page class definition. I think you are going to need to customize the page form as in this example in the documentation. The values can be set in the form __init__.py. Don't forget that there won't be a parent page until your page is saved for the first time.

How to override the default wagtail page slug

I'm trying to make a wagtail pages for the astrologer based on category, country and city.
And my url's are:
https//localhost:8080/<category>
https//localhost:8080/<category>/<country>
https//localhost:8080/<category><country>/<city>
If I am trying to save the url with '/' forward slash then it removing the '/' form the slug and saving it as a string.
Ex: <category><country>/<city> to categorycountrycity
So Is it possible to override the wagtail default page slug type 'SlugField' to 'CharField'.
or is there any other solution ?
URLs are tightly tied to the page tree, and the slug is just the part which identifies the page at that level, rather than any parent levels. So if you want https://localhost:8080/<category>/<country>/<city>, you will need:
A page at https://localhost:8080/<category>/, whose slug is just the name of the category
The above category page to have a child, with the slug of just the country (which will give it the URL https://localhost:8080/<category>/<country>/)
The country page to have a child page, with the slug of just the city name (which will give it the URL https://localhost:8080/<category>/<country>/<city>).
Need other cities, make more child pages under the "country" page. Need more countries, make more child pages under the "category" page. Need more categories, make more child pages under the root page.

How to put the page title in a url pattern with Django?

If I wanted to send the blogpost id to the url pattern, and have the url automatically turn into something like www.blog.com/post/2/this-is-my-second-blogpost, how might I do that?
Inside of urls.py I have a url pattern that accepts the blogpost id, and its title. It doesn't seem to be working, and once it does, would be tedious to add the title for every page in this manner.
urls.py:path('post/<int:post_id>/<str:post_title>', views.view_post, name='view_post'),
blogposts.html template:
Read More
views.py: def view_post(request, post_id, post_title):.
Simply, add the default argument of post_title to be None. If you are wishing to get the post_title directly from the post_id, neclect the post_title, doing this won't give you error as functions already got all the satisfied argument values.
So:
def view_post(request, post_id, post_title=None):
Edit
Okay, what user wanted was about slug field. Slug field is the field type in django model. Basically, it is used for the url type. In above problem, what pyknight202 wanted was the url patter for the post_title. So, you could not use tilte directly as url as they contain spaces, so for that you have to add post_title in hyphens or underscore to be readable. Therefore, you need slug field in Post model.
https://helloworld.com/1/this-is-example
So, 1 is post_id as slug could not be unique, so you could not only retrieve from post_title therefore you need post_id too. Refs
Maybe you should use a slug field for the url instead of the combination of id and title, your url will look like example.org/title-to-object-2/.
Now you have a unique slug field with the title and the id.

Is is possible to have the Django slugfield unique per user or other model

I am setting up a site that has 'pages' that are always within a parent 'category'. Some pages will have the same title but will reside in a different category. Currently django sluggify always adds numbers to the slugs if the name would be the same:
foo/help/
bar/help-1/
Is there a way to get it to output a more intelligent slug so that the slug is unique for the page within the category.
foo/help/
bar/help/
etc/help/
etc/help-1/
I am also thinking of having some pages that are unique for a user in the same way. They would always be accessed as a sub of the user making them unique in that way
The slugify function itself (django.template.defaultfilters.slugify) only works on it's input so that's not what gets you such result.
wrt/ your original question, ie "Is it possible to have a slugfield unique per user or other model", it's just a matter of declaring the relevant fields as unique_together in your model's Meta, ie
class Category(models.Model):
# code here
class Page(models.Model):
category = models.ForeignKey(Category)
slug = models.SlugField("slug")
class Meta:
unique_together = (
("category", "slug"),
)
Then if you have some code that autogenerate / prepopulate the slug field you'll have to tweak it manually to take care of the category...

How would you populate a field based on another field

From the admin panel I want to populate a slug field based on a certain text field
eg.
Title: My Awesome Page
would automaticaly populate
Slug: my_awesome_page
There used to be a prepoulate_from option for the SlugField up to 0.96. It became an admin option after that. See here for reference on that.
Alternatively, you could override the model's save method to calculate the value of the slug field on save().
This question may be helpful, too.
There is also an app called django-autoslug which provides a field type AutoSlugField. Using that, you could have:
class Something(models.Model):
title = models.CharField(max_lenght=200)
slug = AutoSlugField(populate_from='title')
...
This AutoSlugField has many nice features, such as generating a slug so that it is unique either globally of combined with some other field (maybe a category or the year part of a DateTimeField).
See http://pypi.python.org/pypi/django-autoslug for further details.