简体   繁体   中英

Django 2: Multiple slugs in url

I am currently following a django tutorial by sentdex . The tutorial is making a clone of https://pythonprogramming.net/ . In the tutorial he uses only one slug in the url, but I think its more convenient to have multiple slugs beacause the urls will be more organized. For example, a link to a tutorial on pythonprogramming.net looks like this: https://pythonprogramming.net/build-supercomputer-raspberry-pi/ . What i want it to look like on my project is mydomain.com/data-analsyis/build-supercomputer/1/ . The url would be domain/category/series/episode/ , instead of domain/episode/ .

# urls.py
from django.urls import path
from . import views

app_name = "main"

urlpatterns = [
    path('', views.homepage, name="homepage"),  # View categories
    path("register/", views.register, name="register"),
    path("logout/", views.logout_request, name="logout"),
    path("login/", views.login_request, name="login"),
    path("<slug:series_slug>/", views.slugs, name="series_blocks"),  # Views all the series in that category
    path("<slug:series_slug>/<slug:tutorial_slug>/", views.slugs, name="tutorial_blocks"),  # View all tutorials in series
    path("<slug:series_slug>/<slug:tutorial_slug>/<int:id>/", views.slugs, name="tutorial_blocks"),  # View spesific tutorial nr.
]

Note: I think it's better to have 3 different functions than the views.slug

# Models.py
from django.db import models
from datetime import datetime


class TutorialCategory(models.Model):
    category = models.CharField(max_length=100)
    summary = models.CharField(max_length=200)
    slug = models.CharField(max_length=100)

    class Meta:
        verbose_name_plural = "Kategorier"

    def __str__(self):
        return self.category


class TutorialSeries(models.Model):
    series = models.CharField(max_length=200)
    category = models.ForeignKey(TutorialCategory, default=1, verbose_name="Kategori", on_delete=models.SET_DEFAULT)
    summary = models.CharField(max_length=200)
    slug = models.CharField(max_length=100)  # Not from tutorial, but this is the tutorial slug

    class Meta:
        verbose_name_plural = "Serier"

    def __str__(self):
        return self.series


class Tutorial(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    published = models.DateTimeField("date published", default=datetime.now())
    series = models.ForeignKey(TutorialSeries, default=1, verbose_name="Serie", on_delete=models.SET_DEFAULT)
    id = models.AutoField(primary_key=True)  # This was originally a slug, but now it's the episode number

    def __str__(self):
        return self.title

.

# Views.py
def slugs(request, series_slug):
    categories = [c.slug for c in TutorialCategory.objects.all()]
    if series_slug in categories:
        match_series = TutorialSeries.objects.filter(category__slug=series_slug)
        series_urls = {}
        for m in match_series.all():
            part_one = Tutorial.objects.filter(series__series=m.series).earliest("published")
            series_urls[m] = part_one.id
        return render(request, "main/category.html", {"part_ones": series_urls})

    tutorials = [t.slug for t in Tutorial.objects.all()]
    if series_slug in tutorials:
        this_tutorial = Tutorial.objects.get(series_slug=series_slug)
        return render(request, "main/tutorial.html", {"tutorial": this_tutorial})

The problem I originally had was all the tutorials showed up, not only those from the series . To show only the series worked fine. But now, after trying to fix this, I don't really know what to do. I have change the views.py a lot, but now it's the original(from sendtex), and changed the tutorial slug to an Id and giving Tutorial series an slug.

How can I get views.py to only show tutorials in specific series , ect. and have multiple slugs in url?

To start, you should create a dedicated view for each of your url pattern:

# urls.py
urlpatterns = [
    ...
    path("<slug:category_slug>/", views.category_blocks, name="category_blocks"),  # Views all the series in that category
    path("<slug:category_slug>/<slug:series_slug>/", views.series_blocks, name="series_blocks"),  # View all tutorials in series
    path("<slug:category_slug>/<slug:series_slug>/<int:tutorial_id>/", views.episode_blocks, name="episode_blocks"),  # View spesific tutorial nr.
]

# views.py
def category_blocks(request, category_slug):
    # logic to display all tutorial with category is `category_slug`

def series_blocks(requests, category_slug, series_slug):
    # logic to display all tutorial with category is `category_slug` and series is `series_slug` 

def tutorial_blocks(requests, category_slug, series_slug, tutorial_id):
    # logic to display all tutorial with category is `category_slug`, series is `series_slug` and tutorial is `tutorial_id`

The logic is similar to what you have already code. Don't forget to check that tutorial.series.slug match series_slug and series.category match category_slug

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM