【问题标题】:django custom blog post urlsdjango 自定义博客文章网址
【发布时间】:2020-11-13 17:16:24
【问题描述】:

我正在通过构建一个简单的博客应用程序来学习 django。虽然这一切都完成了,但我目前有个别帖子的网址格式为https://my_site_dot_com/blog/entry/38/,其中数字 38 对应于所述帖子的主键。 我想要的是格式为https://my_site_dot_com/blog/entry/this_is_custom_title/,其中“this_is_custom_title”对应于帖子的标题。我不知道如何做到这一点。任何人都可以提供任何帮助吗? 我的模型看起来像:

class Entry(models.Model):
    entry_title = models.CharField(max_length=50)
    entry_text = models.TextField()
    image = models.FileField(upload_to="media", blank=True)
    entry_date = models.DateTimeField(auto_now_add=True)
    entry_author = models.ForeignKey(User, on_delete=models.CASCADE)

        class Meta:
            verbose_name_plural = "blog"
    
        def __str__(self):
            return self.entry_title

我希望 entry_title 指向自定义 url 而不是主键。

我的urls.py 看起来像这样:

urlpatterns = [
    path('', HomeView.as_view(), name="blog-home"),
    path('entry/<int:pk>/', EntryView.as_view(), name="entry-detail"),
    path('create_entry/', CreateEntryView.as_view(success_url='/'), name='create_entry'),
]

编辑: 发帖的班级是这样的:

class EntryView(DetailView):
    model = Entry
    template_name = 'blog/entry_detail.html'
    data_set = random_info()
    stuff_for_post = {
        "info": data_set
    }

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['rand_im'] = random_image()
        context['tags'] = ['tag1','tag2','tag3']

        return context

我是 django 的绝对菜鸟,来自 android/java。所以请给一个通俗易懂的解释。 提前致谢

【问题讨论】:

    标签: python django django-urls url-pattern


    【解决方案1】:

    您可以向 Entry 模型和 get_absolute_url 方法添加一个 slug 字段。不要忘记从 Django 的 url 模块中导入 reverse 函数。

    from django.urls import reverse
    
    class Entry(models.Model):
        entry_title = models.CharField(max_length=50)
        entry_text = models.TextField()
        image = models.FileField(upload_to="media", blank=True)
        entry_date = models.DateTimeField(auto_now_add=True)
        entry_author = models.ForeignKey(User, on_delete=models.CASCADE)
        slug = models.SlugField()
    
        def get_absolute_url(self):
            return reverse('entry_detail', kwargs={'slug': self.slug})
    
        class Meta:
            verbose_name_plural = "blog"
    
        def __str__(self):
            return self.entry_title
    

    然后,在您应用的 urls.py 模块中,将以下 url 模式添加到 urlpatterns 列表中。别忘了加载对应的视图,我猜这种情况下可能是EntryView

    from django.urls import path
    from .views import EntryView
    
    urlpatterns = [
        ...
        path('<slug:slug>', EntryView.as_view(), name='entry_detail'), # new
        ...
    ]
    

    那么 slug 应该替换 url 中的主键模式。

    更进一步,您可以在模型中使用一种方法,例如对标题进行 slugify。 (在模型中定义方法,然后从模型的 save 方法调用它,通过覆盖 save 方法)

    https://docs.djangoproject.com/en/3.0/ref/utils/#django.utils.text.slugify

    【讨论】:

    • 这似乎不起作用。 url 模式现在看起来像 127.0.0.1:8000/blog/2,我收到错误页面未找到 (404)。有什么问题?
    • 整个错误是 Page not found (404) Request Method: GET Request URL: 127.0.0.1:8000/blog/2 Raised by: blog.views.EntryView 找不到与查询匹配的条目
    【解决方案2】:

    目前您正在通过您的网址传递一个整数。您需要做的就是稍微修改它以通过 url 传递一个字符串。 Here 是一个类似的问题,讨论了如何实现这一点。

    至于您需要对代码进行的更改,urls.py 需要更新

    path('entry/<str:title>/', EntryView.as_view(), name="entry-detail")
    

    您还没有提供您的博客文章视图,但它看起来像这样:

    def post(request, title):
        template = "template.html"
        post = Posts.objects.filter(entry_title==title)
        return render(request, template, {'post':post})
    
    

    【讨论】:

    • 我正在使用基于类的方法。我已经编辑了我的问题以显示课程的样子。我该如何进行?
    【解决方案3】:

    如果您使用基于类的视图,您应该使用 slug。 首先在您的 Entry 模型中添加一个新字段 entry_slug 并覆盖 save 方法以便自动生成 entry_slug 字段:

    class Entry(models.Model):
        entry_title = models.CharField(max_length=50)
        entry_slug = models.CharField(max_length=50)
        ...
    
        def save(self, *args, **kwargs):
                self.entry_slug = slugify(self.entry_title )
                super(Entry, self).save(*args, **kwargs) 
    

    您可以通过将 pk 替换为 entry_slug 来做到这一点:

    path('entry/<slug:entry_slug>/', EntryView.as_view(), name="entry-detail")
    

    【讨论】:

    • 当我这样做时,我得到这个错误:Generic detail view EntryView must be called with an object pk or a slug in the URLconf.
    最近更新 更多