好久不见。小编前段时间出差,偷了个懒,真不好意思。今天我们再来看下个Django实战小案例吧。在日常Web开发过程中对数据(比如新闻和用户)的分类是必不可少的。我们会给他们分配一个类别(Category), 这个类别可能有父类别(Parent Category),有可能还有子类别(Child Category)。今天我们将教你如何利用Django实现生成动态的分类目录,这将对开发三级或联动菜单非常有用。一个惨不忍睹的效果如下所示:

Django实战: 生成树形动态分类目录

废话不多说,我们来看代码。


第一步 建立APP,设置URL

我们创建一个叫demo的项目,并利用python manage.py startapp blog创建一个名叫blog的APP,并把它加入到settings.py中INSTALLED_APP里去。另外URLs里添加blog.urls.

# demo/settings.py

urlpatterns = [
   path('admin/', admin.site.urls),
   
path('blog/', include('blog.urls')),

]


第二步 建立模型Models

我们的模型model设计非常简单,只有名字name,slug和父级分类3个字段。其中ForeignKey指向了自己,这样就可以实现一层一层地添加子分类了。slug是admin后台根据name自动生成地。slug会出现到我们链接url中去。

# blog/models.py

from django.db import models


class Category(models.Model):
   
name = models.CharField('分类名', max_length=30, unique=True)
   slug = models.SlugField('slug', max_length=40)
   parent_category = models.ForeignKey('self', verbose_name="父级分类", blank=True, null=True, on_delete=models.CASCADE)

   class Meta:
       ordering = ['name']
       verbose_name = "分类"

   def __str__(self):
       return self.name


第三步 设计URL

在blog文件夹里新建urls.py, 并加入如下代码。我们设计了两个URL,一个展示所有类别,一个展现当前类别详情。我们使用了Django自带的通用视图。一旦你使用Django通用视图,你会爱上她。

# blog/urls.py

from django.urls import path, re_path
from . import views

# namespace
app_name = 'blog'

urlpatterns = [

   
re_path(r'^category/$',
           
views.CategoryListView.as_view(), name='category_list'),
   
re_path(r'^category/(?P<slug>[-\w]+)/$',
           
views.CategoryDetailView.as_view(), name='category_detail'),

]


第四步 编写视图View

我们的view也非常简单,全靠通用Django的通用视图。

# blog/views.py

from django.views.generic import DetailView, ListView
from .models import Category


class CategoryListView(ListView):
   model = Category


class CategoryDetailView(DetailView):
   model = Category


第五步 编写模板

# blog/templates/blog/category_list.py

{% for category in category_list %}
<li><a href="{% url 'blog:category_detail' category.slug %}">{{ category.name }}</a></li>
{% endfor %}

# blog/templates/blog/category_detail.py

{% if category.parent_category %}
<p>父类别: </p>
<li><a
href="{% url 'blog:category_detail' category.parent_category.slug %}">{{ category.parent_category.name }}</a></li>
{% endif %}

<p>当前类别: </p>
<li><a
href="{% url 'blog:category_detail' category.slug %}">{{ category }}</a></li>

{% with category.category_set.all as categories %}
{% if categories %}
<p>子类别: </p>
{% for category in categories %}
<li> <a href="{% url 'blog:category_detail' category.slug %}">{{ category.name }}</a></li>
{% endfor %}
{% endif %}
{% endwith %}

注意: 上述代码中我们使用了category.parent_category来获取父类别,而使用了category.category_set.all获取的子类别。请仔细品味下我们为什么这么做。


第六步 设置admin

我们希望通过Django自带的admin添加类别,并利用prepopulated_fields自动生成slug。我们只需要在admin.py里添加如下代码。

# blog/admin.py

from django.contrib import admin
from .models import Category

# Register your models here.

class CategoryAdmin(admin.ModelAdmin):
   prepopulated_fields = {'slug': ('name',)}

admin.site.register(Category, CategoryAdmin)


第七步 查看效果

打开CMD终端进入项目所在文件夹,连续输入 python manage.py makemigrationspython manage.py migratepython manage.py runserver。如果你还没有创建后台的superuser,在runserver前,请输入python manage.py createsuperuser。后台效果图如下所示:

Django实战: 生成树形动态分类目录

当你在admin创建好类别后,你就可以通过访问http://127.0.0.1:8000/blog/category/查看所有类别了。点击某个类别链接,你可以看到父类别,当前类别和子类别。

Django实战: 生成树形动态分类目录


第八步 如何显示同级类别?

我们已经显示了父类和所有子类,那我们如何显示同一父类下的所有类别呢?我们只需要在Category的模型里增加一个获取get_same_level_category的方法,然后在模板里使用它。

def get_same_level_category(self):
   if self.parent_category:
       return self.parent_category.category_set.all().exclude(id=self.id)

这段代码的意思是:如果有父类,就获取父类下所有的子类,自身除外。模板文件新增下面一段代码。

# blog/templates/blog/category_detail.py

{% with category.get_same_level_category as categories %}
{% if categories %}
<p>当前同级类别: </p>
{% for category in categories %}
<li><a href="{% url 'blog:category_detail' category.slug %}">{{ category }}</a></li>
{% endfor %}
{% endif %}
{% endwith %}

最后整个项目的目录结构和最终效果如下图所示:

Django实战: 生成树形动态分类目录

好了,今天就到这里。如果喜欢我们的文章,请关注我们。

Django实战: 生成树形动态分类目录

相关文章:

  • 2021-11-17
  • 2021-07-07
  • 2021-09-27
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-07-30
猜你喜欢
  • 2021-11-06
  • 2021-11-28
  • 2022-12-23
  • 2021-10-01
  • 2021-12-27
  • 2021-11-28
  • 2022-12-23
相关资源
相似解决方案