简体   繁体   中英

Use slug instead of pk in Django detail view

I want to use the slug in URL for my detail view instead of the primary key. But I don't know what I must change. My project files are:

models.py

from django.db import models
from django.utils import timezone

class Kategorie(models.Model):
    title = models.CharField(max_length=250, verbose_name="Kategoria")
    slug = models.SlugField(unique=True, max_length=250, verbose_name="Przyjazny adres url")

    class Meta:
        verbose_name="Kategoria"
        verbose_name_plural="Kategorie"

    def __str__(self):
        return self.title


class Wpisy(models.Model):
    title = models.CharField(max_length=400, verbose_name="Tytuł")
    slug = models.SlugField(unique=True, max_length=400,verbose_name="Przyjazny adres url")
    content = models.TextField()
    created_date = models.DateTimeField(blank=True, null=True, verbose_name="Data utworzenia")
    category = models.ForeignKey(Kategorie, verbose_name="Kategoria", on_delete=models.CASCADE)

    class Meta:
        verbose_name="Wpis"
        verbose_name_plural="Wpisy"


    def __str__(self):
        return self.title

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.lista_bajek, name="lista_bajek"),
    path('bajki/',views.lista_bajek, name='lista_bajek'),
    path('bajki/(?P<pk>\d+)/$', views.detale_bajki, name='detale_bajki'),
]

views.py

from django.shortcuts import render, get_object_or_404
from .models import Wpisy

def lista_bajek(request):
    lista_bajek = Wpisy.objects.all()
    context ={'lista_bajek': lista_bajek,}
    return render(request, 'bajki/lista_bajek.html', context=context)

def detale_bajki(request, pk):
    detale_bajki = get_object_or_404(Wpisy, pk=pk)
    return render(request, 'bajki/detale_bajki.html', {'detale_bajki': detale_bajki})

template file:

{% extends 'bajki/index.html'%}
{% block content %}
<!DOCTYPE html>
<html>
<head>
    <title>Bajki</title>
</head>
<body>
{% for bajki in lista_bajek %}
Tytuł : <a href="{% url 'detale_bajki' pk=bajki.pk %}">{{bajki.title}} </a><br>

{% endfor %}
{% endblock %}
</body>
</html>

Can somebody tell me what I must to change to have a nice SEO address, for example /bajki/winnie-the-pooh ?

Your first problem is that your detail path is invalid:

path('bajki/(?P<pk>\d+)/$', views.detale_bajki, name='detale_bajki'),

If you want to use a regex, then use re_path . With path you should use <converter:name> instead.

path('bajki/<int:pk>/', views.detale_bajki, name='detale_bajki'),

Then, if you want to use a slug in the URL then change it to:

path('bajki/<slug>/', views.detale_bajki, name='detale_bajki'),

You'll then need to update the view:

def detale_bajki(request, slug):
    detale_bajki = get_object_or_404(Wpisy, slug=slug)

Finally, you need to use the slug when you reverse the URL, eg:

{% url 'detale_bajki' slug=bajki.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