06_视图与模板_01

上一篇我们讲到了博客 URL 的结构,但遗漏了两个比较重要的 404 页面 和 文件上传 的 URLs, 另外,搜索页面 也要单独起来。 视图和模板是 Django 个人博客教程的主要内容,但内容相对比较多,文章篇幅统筹方面稍微麻烦了些,后面几篇文章都会根据各个页面或功能来进行阐述。 思考 这篇文章主要做 首页 和 文章详情页 的视图,在开始之前还是要先思考几个问题。 博客名称、副标题、SEO 关键词、博客描述等要写死在 html 模板页面吗? PC 和 手机端 能否兼容? Django 的模板可以分离开来然后给其他模板调用吗? 本文目标 将博客全局部分常量用统一写到 docspace/options.py 里面 采用 Bootstrap 框架写兼容 PC 和 Wap 的页面 涉及知识点 Bootstrap 框架 SEO 搜索引擎优化 Step1、博客静态首页 构建一个博客首页先从一个静态页开始就会更清晰明朗一些,下面是我写的静态博客首页 PC版 和 Wap版 的上半页部分: PC首页 Wap首页 Step2、博客全局常量管理 在 docspace/options.py 添加下面代码 # 博客站点 site_url = 'http://www.iloxp.com/' real_url = 'http://www.iloxp.com/' # 博客 SEO site_name = "Django 博客教程" site_keywords = ['idcops', 'django博客', 'django个人博客', 'django教程', '极简博客'] site_description = "一个分享 django 通用代码,idcops 运维管理平台,django 个人博客教程,一个极简主义者,没有太多内容的博客。" # 主题包 theme = 'docspace' # 首页文章列表默认每页预取多少篇文章 posts_per_page = 10 # 限制前端最多能获取多少篇文章 posts_per_page_max = 27 # RSS 地址页默认每页预取多少篇文章 posts_per_rss = 10 Step3、文章 url 和固定连接 # `docspace/urls.py`.`urlpatterns` from django.urls import path from docspace import views urlpatterns = [ # ... path('', views.IndexView.as_view(), name='index'), path('//', views.detail_article, name='detail_article'), ] # `docspace/models.py`.`Article` 添加下面方法 def get_absolute_url(self): opts = self._meta if opts.proxy: opts = opts.concrete_model._meta kwargs = {'post_type': self.post_type, 'pk': self.pk} path = reverse('detail_article', kwargs=kwargs) # url = 'https://{}{}'.format('www.iloxp.com', path) return path Step4、首页视图和文章详情页视图 # `docspace/views.py` from django.shortcuts import HttpResponse from django.views.generic import ListView from django.conf import settings from django.contrib.sites.shortcuts import get_current_site # Create your views here. from docspace.models import Article from docspace.choices import ( ArticleStatusItems, ArticleTypeItems ) from docspace.options import ( posts_per_page, posts_per_rss, theme, posts_per_page_max, site_name, keywords, description ) theme = getattr(settings, 'theme', theme) posts_per_page = getattr(settings, 'posts_per_page', posts_per_page) posts_per_page_max = getattr( settings, 'posts_per_page_max', posts_per_page_max ) _PAGINATE = 'paginate_by' class BasicListView(ListView): paginate_by = posts_per_page model = Article def get_paginate_by(self, queryset): self.paginate_by = self.request.GET.get(_PAGINATE, self.paginate_by) if int(self.paginate_by) > posts_per_page_max: messages.warning( self.request, _('Show up to %{posts_per_page_max}s articles.' % {'posts_per_page_max': posts_per_page_max}) ) self.paginate_by = posts_per_page_max return self.paginate_by class IndexView(BasicListView): def get_template_names(self): """ `docspace/templates/docspace/index.html` """ return ['{}/index.html'.format(theme)] def get_queryset(self): queryset = super(IndexView, self).get_queryset() ordering = self.get_ordering() or ['-created'] _effective = dict( status=ArticleStatusItems.PUBLISHED, post_type__in=[ArticleTypeItems.ARTICLE, ArticleTypeItems.PAGE] ) only_fileds = [ 'updated', 'created', 'author', 'title', 'content', 'category' ] _select = ['author', ] _prefetch = ['category', 'tags'] queryset = self.model.objects.filter( **_effective).only( *only_fileds).select_related( *_select).prefetch_related( *_prefetch).order_by(*ordering) return queryset def get_context_data(self, **kwargs): context = super(IndexView, self).get_context_data(**kwargs) seo = dict( site_keywords=','.join(keywords), site_description=description ) _extra = { 'site': get_current_site(self.request), 'site_name': site_name, 'seo': seo } print(_extra) context.update(**_extra) return context get_template_names 在配置 options.theme = docspace 的情况下,会生成 docspace/templates/docspace/index.html _extra 是一个如下结构的字典 { 'site': , 'site_name': 'Django 博客教程', 'seo': { 'keywords': 'idcops,django博客,django个人博客,django教程,极简博客', 'description': '一个极简主义者,没有太多内容的博客。' } } Step4、Bootstrap 和首页模板 原本打算使用 Bootstrap 5.0.x 的,但去官网下载的时候发现还不是稳定发行版,所以这里还是用回到 Bootstrap 4.6.x 版。 下载 Bootstrap 4.6.x 并解压css 和 js 到 docspace/static/docspace/dist/ 目录下 index.html 内容 {% spaceless %} {% load i18n static %} {% get_current_language as LANGUAGE_CODE %} {% block seo %} {% endblock seo %} {% block extra-meta %} {% endblock %} {%block title%} {{site_name|default:"Django 博客教程"}} | {{seo.description | default:"一个极简主义者,没有太多内容的博客。"}}{%endblock%} {% block extra-meta-css %} {% endblock %}
{% block header %} {% include 'docspace/header.html' %} {% endblock header %}
{% block main %} {% include 'docspace/main.html' %} {% endblock main %}
3. footer
{% endspaceless %} 为了有更清晰的层级,这边使用了 Django 模板的 include 方法来引用子模版页内容 spaceless 模板标签会在渲染的是删除 html 不必要的空格 {{site_name|default:"Django 博客教程"}} 当模板变量 site_name 为空时调用 default 指定的内容 header.html 内容 main.html 内容
{% block home-stream %} {% include 'docspace/home-stream.html' %} {% endblock home-stream %}
{%for item in object_list%} {%endfor%} {% if page_obj %}
{% endif %}
{%block site-content%} {%endblock site-content%}
home-stream.html 内容 {% load static %}
Django个人博客教程-1:开发环境之编译安装python3.7

开发环境之编译安装 python3.7

上一篇文章《Django个人博客教程-1:开发环境》我们简单介绍了Django个...

...

再谈一个管理后台列表功能应有的素质

大家能看到的这个号第1篇文章《无心朝政,列表功能分析下》...

Step5、文章详情页视图 def detail_article(request, post_type, pk): return HttpResponse("post_type: {}, pk: {}".format(post_type, pk)) 先写个函数简单解析一下 url,访问结果如下: 文章类型页 页面类型页 下一篇文章将继续视图和模板内容:《Django 个人博客教程-07:视图与模板_02》,主要工作就是将静态首页转成动态首页。 系列文章: 《Django 个人博客教程-00:开篇》 《Django 个人博客教程-01:开发环境与项目初始化》 《Django 个人博客教程-02:自定义字段与模型抽象类》 《Django 个人博客教程-03:用户模型和博客链接》 《Django 个人博客教程-04:文章模型和评论模型》 《Django 个人博客教程-05:管理站点与博客URLs》 《Django 个人博客教程-06:视图与模板_01》当前文章 《Django 个人博客教程-07:视图与模板_02》下一篇 欢迎分享给其他人或点击在看