Transfer Class-based view to another - django

I created a DetailView class that can receive links from categories or posts from a website. In the “get_object ()” method, I identify if it is Category or Post models (by url slug). The URLs for this class are listed below:
/category/
/category/subcategory/
/category/post/
/category/subcategory/post/
The class got too long because the categories and posts have specific behaviors.
I was wondering if it is possible to "transfer" one class to another to handle specific information?
For example:
GenericView redirect to CategoryView after identifying that it is the url: / category / or for PostView, if it is / category / post /
NOTE: I am transferring the Wordpress site to Django, so I cannot change the url structure.
Is there any way to do this? Do you suggest another better solution?

Related

Django Rest Framework - create object with field value from URL

Is it possible to use a ModelViewSet to create an instance from a POST request where one of the field values is specified in the URL?
EG: POST /teams/3/members with data name = Bob should create Member(team_id=3, name="Bob")
Conceptually similar to filtering against the url
Yes, you can do it and quite simple, look here, that would be your url:
re_path('teams/(?P<team_id>\d+)/members/', views.MemberViewSet.as_view({'post': 'create_member'}), name='members'),
and in views just use team_id as an argument:
#class MemberViewSet
def create_member(request, team_id):
...

Wagtail url prefix for a custom Page model

This question is probably trivial, but I am unable to see a simple solution.
I have custom page model representing Post:
class PostPage(Page):
I would like to make all instances of this model (all Posts) accessible only with url prefix
/posts/
Example:
User creates new Post, the assigned slug will be
awesome-first-post
What should happen is, that
/awesome-first-post/
will result in 404, while
/posts/awesome-first-post/
will display the post.
Note: I want this prefix only for the specific model Postpage. Other pages should be served directly from their slug.
In Wagtail, page URLs are formed from the list of slugs of the page's parent and ancestor pages, based on the page's position in the tree - the developer doesn't specify them directly. So, to get the URL /posts/awesome-first-post/, create a page with the slug posts (usually you'd create a dedicated PostIndexPage page model to serve as a listing page), and create the page awesome-first-post as a child of that one (by clicking the '+' icon next to the Posts page in the explorer listing view).
If you want to make sure that users only ever create PostPages as children of the PostIndexPage, use a subpage_types / parent_page_types setting, for example:
class PostPage(Page):
# ...
parent_page_types = ['PostIndexPage']

Need Guidance for django wagtail

currently i'm trying to Integrating Wagtail with existing django project.
I'm new in wagtail, and still learning about wagtail
class BlogPage(Page):
body = RichTextField(blank=True)
categories = ParentalManyToManyField('blog.BlogCategory', blank=True)
location = models.ForeignKey('blog.Location', on_delete=models.PROTECT)
and then i register the category and the location model as snippets.
how's the best practice for build page contains of BlogPage with
certain category / location ?
and how to call that page from django's menu
or maybe where can i find documentation for integrating wagtail to existing django project
Thank you
I think you're looking for a Blog Listing Page, where you can list all your blog posts and then have blog posts based on a certain category.
You'll probably want to use a RoutablePageMixin (if you're not creating an SPA with Vue or React). A RoutablePageMixin lets you automatically create additional child pages, without having to create Wagtail child pages.
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
class BlogListingPage(RoutablePageMixin, Page):
"""BlogListingPage class."""
template = 'cms/blog/blog_listing_page.html'
subpage_types = ['pages.BlogPage']
# ... other fields here
#route(r'^category/(?P<cat_slug>[-\w]*)/$', name='category_list')
def category_list(self, request, cat_slug):
"""Return posts in a certain category."""
context = self.get_context(request)
posts = BlogPage.objects.live().filter(categories__slug=cat_slug).order_by('-pub_date')
context['posts'] = posts
return render(request, 'cms/blog/blog_category_page.html', context)
Note I did not test this code, you may need to fix any errors and adjust this for your needs.
The above code will take your blog listing page (say its localhost:8000/blog/) and create a category listing page (ie. localhost:8000/blog/category/topic-slug/)
That topic-slug will be passed into the category_list() method, where you can then filter your BlogPage's based on the category(ies) it's in. It will add posts to your page, and render a different listing page, where you can customize your template.
It's been a while since I checked, but the Wagtail Bakery Demo probably has examples of this in there (and a lot of really sweet goodies).
You can read more about Wagtail Routable Pages at https://docs.wagtail.io/en/latest/reference/contrib/routablepage.html as well.

Django: How to set up a single view for multiple urls where each url points to subclass of a base model?

I have the following urls:
browse/college
browse/department
browse/subjects
I have Tag model where College, Department and Subject are all subclasses on Tag. All the urls will call a single view.
I want to create a view called browse_specfic_tag(request, model_name)
I was thinking of converting model name to model using get_model and do something like,
TagModel = get_model(model_name..)
but I am going to tie url name with model which might not be a good thing to do if I decided to rename either of them.
Any better way to do this?
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
…
The proper way of solving this is passing an extra option to the view. See related documentation entry.
Example:
url('^college/$', 'tag_view', {'model': College})
def tag_view(request, model):
records = model.objects.filter(…)
Furthermore, actions should not be included in URL's name. URLs should identify resources. Therefore I would skip the browse part of the URL.

reverse django url to object, not view. possible?

I have a set of URLs for which I would like to retrieve the django model associated with this url, not the django view which is what the reverse URL Dispatcher does. The code would ideally look something like this:
urls_to_lookup = get_urls_to_lookup()
models = []
for url in urls_to_lookup:
model = retrieve_django_model(url)
models.append(model)
Since the urls I would like to lookup have unique models associated with them (via the #permalink decorator), it seems like this is possible but my google skillz are coming up empty handed. Thanks for your help!
EDIT In case it helps brainstorming solutions, I'm pulling these URLs from Google Analytics for all blog posts and I want to dynamically display most frequently viewed pages. The URL itself is helpful, but I would like to grab the title, teaser, etc for each blog post for display and that is all stored in the database.
If you are trying to create a sitemap; there's the sitemaps contrib app.
If you are trying to print out all the URLs in a nice format, see this answer.
I'm trying to think of a reason for having such a feature, but it escapes me. However, this should do what you want (not tested):
from django.db import models
def retrieve_django_model(url):
m_instances = [m for m in models.get_models() \
if m.objects.all().count()]
for m in m_instances:
if m.objects.all().order_by('?')[0].get_absolute_url() == url:
return m
else:
return None
Since we can only fetch the absolute url from instances not models, the initial list comprehension filters out those models for which there are no instances, and hence we cannot get the absolute URL.