Reputation: 25
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?
Upvotes: 2
Views: 3995
Reputation: 472
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
Upvotes: 3