我正试图创建一个博客,并希望文章按类别划分。 Django:2.1,Python:3.7
我不明白如何更改urlpatterns中显示类别名称而不是<int:pk>
的路径。在哪里可以查看Django代码示例?
我尝试执行path('category.title'),但是它不起作用。
这是我的模型。py:
from django.db import models
from django.conf import settings
from django.urls import reverse
class Category(models.Model):
title = models.CharField(max_length=50)
image = models.ImageField(upload_to='', blank=True)
def __str__(self):
return self.title
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
image = models.ImageField(upload_to='', blank=True)
cat = models.ForeignKey(
Category, on_delete=models.CASCADE, null=True,
)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', args=[str(self.id)])
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='comments')
comment = models.CharField(max_length=100)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
def __str__(self):
return self.comment
def get_absolute_url(self):
return reverse('article_list')
这是urls.py:
from django.urls import path
from . import views
from .models import Category
urlpatterns = [
path('', views.ArticleViewList.as_view(), name='article_list'),
path('<int:pk>/edit/', views.ArticleUpdateView.as_view(), name='article_edit'),
path('<int:pk>/delete/', views.ArticleDeleteView.as_view(), name='article_delete'),
path('<int:pk>', views.ArticleDetailView.as_view(), name='article_detail'),
path('new/', views.ArticleCreateView.as_view(), name='article_new'),
]
这是基于类的视图,用于返回文章列表:
class ArticleViewList(LoginRequiredMixin, ListView):
model = models.Article
template_name = 'article_list.html'
login_url = 'login'
1)我希望在地址栏中显示类别的标题 2)我想知道使用基于类的视图是一个好的决定 3)我想知道如何在模板循环中显示特定类别的文章
答案 0 :(得分:1)
期望您的网址看起来像:
/
-所有帖子的列表,不分类别
/category1
-类别1中所有帖子的列表
/category1/1
-帖子#1的详细信息(可选,必须或必须不属于category1)
您需要做几件事:
1)您需要将SlugField
添加到类别模型-这是将在url中使用的实际字符串,因为对url中的内容有一些限制。
models.py:
class Category(models.Model):
title = models.CharField(max_length=50)
slug = models.SlugField(unique=True)
image = models.ImageField(upload_to='', blank=True)
def __str__(self):
return self.title
2)修改urlpatterns
以要求slug
urls.py:
urlpatterns = [
path('', ArticleViewList.as_view(), name='article_list'),
path('<slug:catslug>', ArticleViewList.as_view(), name='article_list'),
path('<slug:catslug>/<int:pk>', ArticleDetailView.as_view(), name='article_detail'),
]
3)为您的ArticleViewList
添加查询集过滤器,因此您将仅按其类别字段值包括特定类别的文章。
views.py:
from django.shortcuts import get_object_or_404
class ArticleViewList(LoginRequiredMixin, ListView):
model = Article
template_name = 'article_list.html'
login_url = 'login'
def get_queryset(self):
queryset = super().get_queryset()
if 'catslug' in self.kwargs:
category_slug = self.kwargs['catslug']
category = get_object_or_404(Category, slug=category_slug)
queryset = queryset.filter(cat=category)
return queryset
4)(可选)通过修改查询集,也可以从url强制检查您的文章详细信息视图是否属于特定类别。
views.py:
class ArticleDetailView(LoginRequiredMixin, DetailView):
model = Article
template_name = 'article_item.html'
login_url = 'login'
def get_queryset(self):
queryset = super().get_queryset()
category_slug = self.kwargs['catslug']
category = get_object_or_404(Category, slug=category_slug)
queryset = queryset.filter(cat=category)
return queryset
使用CBV是个不错的决定-因为您的所有视图都很简单,而且正是CBV的目标。它将使您拥有小的可读代码。
您可以使用{% regroup %}
按类别对文章进行分组:
article_list.html:
{% regroup object_list by cat as categories %}
{% for category in categories %}
{{ category.grouper }}:</br>
{% for object in category.list %}
{{ object }}<br>
{% endfor %}
{% endfor %}
答案 1 :(得分:0)
使用基于类的视图很好,但是使用函数视图也可以很好地工作,实际上在这种情况下可以使用函数,但是您可以更改一些内容,并且也可以用于基于类的视图。只要您知道自己想要什么,它们的工作原理几乎相同。关于的问题 在链接中使用标题而不是主键。
django通过将其编码为安全格式将在URL中转义空格和特殊字符,但仍会理解。这就是为什么我认为与使用唯一ID相比,这个想法不是最好的,但是如果您仍然需要它,
也许您的网址中需要这样的内容
from django.conf.urls import url
url(regex=r'^(?P<category>[\w ]+)/$', view=category_article, name='category_articles'),
并在您看来
from.models import Category, Article
def category_article(request, category):
cat = Category.objects.get(title=category)
categories = Category.objects.all()
articles_in_category = Article.objects.filter(cat=cat)
context = {
'categories':categories,
'articles':articles_in_category,
}
// render this two now to template
//I could not coz I dont know path to your template
当您想链接到此链接时,会使用标题代替
{% for category in categories %}
<a href="{% url 'category_articles' category.title %}">{{category.title}}</a>
{% endfor %}
或者如果您想使用文章指向其类别中的其他元素
{% for article in articles %}
<a href="{% url 'category_articles' article.cat.title %}">{{category.title}}</a>
{% endfor %}
您对我的问题不太清楚,但希望我能回答您的测验,