您现在的位置是:网站首页>>编程开发编程开发

Django个人博客开发(八)前端动态页面开发

发布时间:2018-04-14 12:04:01分类:编程开发阅读:1259

    概述

    本节继续在视图文件blog/views.py中添加视图函数,以完成前端各页面的动态数据渲染。在应用URL文件blog/urls.py中添加相应的路由,然后完善各前端页面和模块的链接。

    前端动态页面开发思路图


    1、视图函数,文件blog/views.py

    1.1添加文章详情页视图

    为了让文章详情请求能清晰知道文章标题,而不仅仅是个id数字,因此使用“article-detail/2/DjangoGe-Ren-Bo-Ke-Kai-Fa/”的URL形式,参数包含文章id和文章slug

    from django.shortcuts import render,get_object_or_404
    from django.conf import settings
    from django.db.models import Q  # filter(~Q(name=''))过滤表示不等于
    from .models import Category, Tag, Article, Comment, Links
    
    # 文章详情页视图
    def article_detail(request, id, slug):
        # 返回匹配id和slug的文章对象,否则的404错误
        article = get_object_or_404(Article, id=id, slug=slug)
    return render(request, 'blog/article.html', locals())
    1.2添加文章列表页视图

    文章列表有两种情况,一种为指定文章类目下的文章列表,另一种为指定标签下的文章列表。当列表数据过多,就需要对列表数据进行分页浏览,因此需要给文章列表使用分页。

    from django.shortcuts import render, get_object_or_404
    from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
    from django.conf import settings
    from django.db.models import Q  # filter(~Q(name=''))过滤表示不等于
    from .models import Category, Tag, Article, Comment, Links
    
    # 文章列表页视图
    def article_list(request, category_id=None, tag_id=None, page=1):
        # 从配置文件中获取每页显示文章数
        per_page = settings.PER_PAGE
        # 根据url中匹配的值,判断是文章类目列表还是标签文章列表
        if category_id:
            category = get_object_or_404(Category, id=category_id)
            articles_list = Article.objects.filter(category_id=category_id)
        else:
            tag = get_object_or_404(Tag, id=tag_id)
            articles_list = tag.article.all()
    
        # 实例化分页对象
        paginator = Paginator(articles_list, per_page)
        try:
            current_page = paginator.page(page)
        except PageNotAnInteger:
            current_page = paginator.page(1)
        except EmptyPage:
            current_page = paginator.page(paginator.num_pages)
        # 当前页(某一页/第一页/最后一页)的所有文章记录对象
        articles = current_page.object_list
    
        return render(request, 'blog/articlelist.html', locals())
    2 请求路由,文件blog/urls.py

    2.1添加文章详情页路由

    from django.conf.urls import url
    from django.views.generic import TemplateView   # 通用视图,可直接将静态映射为视图函数
    from  . import views
    
    urlpatterns = [
        url(r'^$', views.index, name='home'),
        url(r'^article-detail/(?P<id>\d+)/(?P<slug>[-\w]+)/$', views.article_detail, name='article_detail'),    # 将正则匹配的id和slug传递给视图函数
    ]
    由于文章详情页请求使用“article-detail/2/DjangoGe-Ren-Bo-Ke-Kai-Fa/”的URL形式,而idslug都是针对当前文章实例,因此可以在文章数据模型类中定义一个get_absolute_url()方法,返回当前文章的请求URL,从而在需要文章请求URL的位置,直接调用该文章的get_absolute_url()方法。

    blog/models.py文件Article数据模型类中添加get_absolute_url()方法

    from django.shortcuts import reverse
    # 文章表数据模型
    class Article(models.Model):
    ……部分省略……
        # 获取文章详情链接URL
        def get_absolute_url(self):
            return reverse('blog:article_detail', args=[self.id, self.slug])    # reverse()函数通过url别名返回对应的url路径
    2.2添加文章列表页路由

    文章列表页分为分类文章列表和标签文章列表两类,以url路径中含有/tag/的为标签文章列表。而每类文章列表页路由分为两种情况,一种为不通过分页链接进入列表页,没有page参数;另一种是通过分页链接切换列表页,则包含page参数。

    urlpatterns = [
        url(r'^article-list/(?P<category_id>\d+)/$', views.article_list, name='article_list'),    # 通过导航进入的列表没有page参数,则使用视图函数的默认值page=1
        url(r'^article-list/(?P<category_id>\d+)/(?P<page>\d)/$', views.article_list, name='article_list'),
        url(r'^article-list/(tag)/(?P<tag_id>\d+)/$', views.article_list, name='article_list'),    # 通过标签链接进入的列表没有page参数,则使用视图函数默认值page=1,注意标签页列表路径含有/tag/
    url(r'^article-list/(tag)/(?P<tag_id>\d+)/(?P<page>\d)/$', views.article_list, name='article_list'),
    ]
    3、前端模板

    3.1文章详情页模板,文件blog/article.html

    {% extends "blog/baseblock/subbase.html" %}
    {% load staticfiles %}
    
    {% block title %}{{ article.title }}{% endblock %}
    
    {% block content_box %}
        <div class="f_box">
          <p class="a_title">{{ article.title }}</p>
          <p class="p_title"></p>
          <p class="box_p"><span>发布时间:{{ article.publish | date:'Y-m-d H:m:s' }}</span><span>分类:{{ article.category.name }}</span><span>阅读:9999</span></p>
          <!-- 可用于内容模板 -->
        </div>
        <ul class="about_content">
          {{ article.content | safe }}
        </ul>
            <!--    <div class="nextinfos">
          <p>上一篇:<a href="/">区中医医院开展志愿服务活动</a></p>
          <p>下一篇:<a href="/">广安区批准“单独两孩”500例</a></p>
        </div>--> 
            <!-- 可用于内容模板 --> 
            
            <!-- container代码 结束 -->
    {% endblock %}
    3.2文章列表页模板,文件blog/articlelist.html

    {% extends "blog/baseblock/subbase.html" %}
    {% load staticfiles %}
    
    {% block title %}
        {% if tag %}
        【{{ tag.name }}】文章列表
        {% else %}
        【{{ category.name }}】文章列表
        {% endif %}    
    {% endblock %}
    
    {% block content_box %}
        <div class="bloglist f_l">
          {% include "blog/baseblock/list.html" %}
          <div class="blank"></div>
            {# 文章列表分为文章类目文章列表和文章标签文章列表,因此针对这两种情况判断指定不同的分页 #}
            {% if tag %}
            <div class="pagelist">
                页次:{{ current_page.number }}/{{ current_page.paginator.num_pages }}&nbsp;
                每页:{{ per_page }}&nbsp;总数:{{ current_page.paginator.count }}&nbsp;<a href="{% url 'blog:article_list' 'tag' tag.id 1 %}">首页</a>
                {% if current_page.has_previous %}
                <a href="{% url 'blog:article_list' 'tag' tag.id current_page.previous_page_number %}">上一页</a>
                {% endif %}
                {% if current_page.has_next %}
                <a href="{% url 'blog:article_list' 'tag' tag.id current_page.next_page_number %}">下一页</a>
                {% endif %}
                <a href="{% url 'blog:article_list' 'tag' tag.id current_page.paginator.num_pages %}">尾页</a>
            </div>
            {% else %}
            <div class="pagelist">
                页次:{{ current_page.number }}/{{ current_page.paginator.num_pages }}&nbsp;
                每页:{{ per_page }}&nbsp;总数:{{ current_page.paginator.count }}&nbsp;<a href="{% url 'blog:article_list' category.id 1 %}">首页</a>
                {% if current_page.has_previous %}
                <a href="{% url 'blog:article_list' category.id current_page.previous_page_number %}">上一页</a>
                {% endif %}
                {% if current_page.has_next %}
                <a href="{% url 'blog:article_list' category.id current_page.next_page_number %}">下一页</a>
                {% endif %}
                <a href="{% url 'blog:article_list' category.id current_page.paginator.num_pages %}">尾页</a>
            </div>
            {% endif %}
        </div>
        <div class="r_box f_r">
          {% include "blog/baseblock/photorecommend.html" %}
          {% include "blog/baseblock/hitsort.html" %}
          {% include "blog/baseblock/tags.html" %}
          {% include "blog/baseblock/links.html" %}
    {#      <div class="ad"> <img src="{% static 'blog/images/03.jpg' %}"> </div>#}
        </div>
    {% endblock %} 
    4、完善各模块及之间链接

    4.1 页头,文件blog/baseblock/header.html

    {% for nav_jszt in nav_jszt_category %}
    <li><a href="{% url 'blog:article_list' nav_jszt.id %}">{{ nav_jszt.name }}</a></li>
    {% endfor %}
    
    {% for nav_shsb in nav_shsb_category %}
    <li><a href="{% url 'blog:article_list' nav_shsb.id %}">{{ nav_shsb.name }}</a></li>
    {% endfor %}
    4.2 阅读排行,文件blog/baseblock/hitsort.html

    {% for article in hits_articles %}
    <li><a href="{{ article.get_absolute_url }}" target="_blank" title="【{{ article.category.name }}】{{ article.title }}">{{ article.title }}</a></li>
    {% endfor %}
    4.3 图文推荐,文件blog/baseblock/photorecommend.html

    {% for article in recommend_articles %}
    <li><a href="{{ article.get_absolute_url }}" title="{{ article.title }}"><img src="{{ article.picture.url }}"><b>{{ article.title | truncatechars:18 }}</b></a>
    <p><span class="tulanmu"><a href="#">{{ article.category.name }}</a></span><span class="tutime">{{ article.publish | date:'Y-m-d' }}</span></p>
    </li>
    {% endfor %}
    4.4 标签云,文件blog/baseblock/tags.html

    {% for tag in tags %}
    <li><a href="{% url 'blog:article_list' 'tag' tag.id %}">{{ tag.name }}({{ tag.article_count }})</a></li>
    {% endfor %}

    4.5 文章列表,文件blog/baseblock/list.html

    {% for article in articles %}
    <h3><a href="{{ article.get_absolute_url }}">【{{ article.category.name }}】{{ article.title }}</a></h3>
    <figure><img src="{% if article.picture %}{{ article.picture.url }}{% else %}{% static 'blog/images/img_2.jpg' %}{% endif %}" alt="【{{ article.category.name }}】{{ article.title }}"></figure>
    <ul>
    <p>{{ article.abstract }}</p>
    <a title="【{{ article.category.name }}】{{ article.title }}" href="{{ article.get_absolute_url }}" class="readmore">阅读全文&gt;&gt;</a>
    </ul>
    <p class="dateview"><span>{{ article.publish | date:'Y-m-d' }}</span><span>阅读:9999次</span><span>分类:[<a href="{% url 'blog:article_list' article.category.id %}">{{ article.category.name }}</a>]</span></p>
    {% empty %}
    <p>还没有发布文章</p>
    {% endfor %}
    4.6 子基础模板,文件blog/baseblock/subbase.html

    {% if tag %}
    <h2 class="nh1"><span>您现在的位置是:<a href="/">网站首页</a>>><a href="{% url 'blog:article_list' 'tag' tag.id %}">【{{ tag.name }}】</a></span><b>【{{ tag.name }}】</b></h2>
    {% elif category %}
    <h2 class="nh1"><span>您现在的位置是:<a href="/">网站首页</a>>><a href="{% url 'blog:article_list' category.id %}">{{ category.name }}</a></span><b>{{ category.name }}</b></h2>
    {% else %}
    <h2 class="nh1"><span>您现在的位置是:<a href="/">网站首页</a>>><a href="{% url 'blog:article_list' article.category_id %}">{{ article.category.name }}</a></span><b>{{ article.category.name }}</b></h2>
    {% endif %}

    代码查看:https://github.com/xdao07/xdsite/tree/v0.0.5

    代码下载:git clone --branch v0.0.5 https://github.com/xdao07/xdsite.git