Django开发博客系统(09-views优化与补充)

本节主要进行了:

post_list视图函数的重构,分类信息的获取与展示,侧边栏信息的获取与展示,html代码的重构

post_list视图函数的重构

在我们的post_list视图函数中,其实逻辑已经稍微有一点复杂了,这是因为我们把多个URL的处理逻辑都放到了一个函数里,所以我们要对它进行重构.

首先是功能的抽取,对于post_list来说,只需要通过tag_id和category_id拿到对应的对象就行,那么这两个功能我们可以将他们放到类中来实现.

再Post类中新增几个方法:

 1 ...前面省略
 2 @staticmethod
 3 def get_by_tag(tag_id):
 4     try:
 5         tag = Tag.objects.get(id=tag_id)
 6     except Tag.DoesNotExist:
 7         tag = None
 8         post_list = []
 9     else:
10         post_list = tag.post_set.filter(status=Post.STATUS_NORMAL).select_related('owner', 'category')
11 
12     return post_list, tag
13 
14 @staticmethod
15 def get_by_category(category_id):
16     try:
17         category = Category.objects.get(id=category_id)
18     except Category.DoesNotExist:
19         category = None
20         post_list = []
21     else:
22         post_list = category.post_set.filter(status=Post.STATUS_NORMAL).select_related('owner', 'category')
23 
24     return post_list, category
25 
26 @classmethod
27 def latest_posts(cls):
28     queryset = cls.objects.filter(status=cls.STATUS_NORMAL)
29     return queryset

重构后的post_list函数:

 1 def post_list(request, category_id=None, tag_id=None):
 2     tag = None
 3     category = None
 4 
 5     if tag_id:
 6         post_lists, tag = Post.get_by_tag(tag_id)
 7     elif category_id:
 8         post_lists, category = Post.get_by_category(category_id)
 9     else:
10         post_lists = Post.latest_posts()
11 
12     context = {
13         'category': category,
14         'tag': tag,
15         'post_lists': post_lists,
16     }
17 
18     return render(request, 'list.html', context=context)

显然简洁了很多.

扫描二维码关注公众号,回复: 10419906 查看本文章

分类信息的获取与展示

对于数据操作的部分,我们选择放到Model层,我们应该把分类分为两类,一个是置顶的分类,一个是普通的分类.我们应该要通过一个函数来返回它们.

在Category类中新增方法

 1 @classmethod
 2 def get_navs(cls):
 3     categories = cls.objects.filter(status=cls.STATUS_NORMAL)
 4     nav_categories = []
 5     normal_categories = []
 6     for cate in categories:
 7         if cate.is_nav:
 8             nav_categories.append(cate)
 9         else:
10             normal_categories.append(cate)
11 
12     return {
13         'navs': nav_categories,
14         'normal': normal_categories,
15     }

这里采取了稍微麻烦一点的方法做,简单的方法可以这样写:

1 nav_categories = categories.filter(is_nav=True)
2 normal_categories = categories.filter(is_nav=False)

第二种方法虽然相比较起来更简单,但是却要执行两次数据库操作,而第一次只会执行一次数据库操作.当然,如果分类的数据很多的话,孰优孰劣也不好说,还得根据实际开发情况来写.

最后在视图函数return之前加一句

1 context.update(Category.get_navs())

侧边栏信息的获取与展示

 在侧边栏展示中我们需要获取最热文章与最新文章,但在之前的Post中并没有定义阅读量之类的,所以这里添加定义

1 pv = models.PositiveIntegerField(default=1)
2 uv = models.PositiveIntegerField(default=1)

添加一个获取最热文章的方法

1     @classmethod
2     def hot_posts(cls):
3         return cls.objects.filter(status=cls.STATUS_NORMAL).order_by('-pv').only('title', 'id')

在这里用到了only,因为侧边栏展示并不需要其他信息,对于only的使用请参考之前写的QuerySet使用,或者查阅文档.

写完之后记得迁移一下,因为模型的字段发生了改变.

接着开始编写侧边栏相关的代码.

首先在Model中处理数据源,对于SideBar,我们给它定义了四种类型,HTML,最新文章,最热文章,最近评论

我们可以在类中定义一个方法,根据不同的类型返回不同的值.

 1 DISPLAY_HTML = 1
 2 DISPLAY_LATEST = 2
 3 DISPLAY_HOT = 3
 4 DISPLAY_COMMENT = 4
 5 SIDE_TYPE = (
 6     (DISPLAY_HTML, 'HTML'),
 7     (DISPLAY_LATEST, '最新文章'),
 8     (DISPLAY_HOT, '最热文章'),
 9     (DISPLAY_COMMENT, '最近评论'),
10 )
11 ...
12 @property
13 def content_html(self):
14     from blogApp.models import Post
15     from comment.models import Comment
16 
17     result = ''
18 
19     if self.display_type == self.DISPLAY_HTML:
20         result = self.content
21     elif self.display_type == self.DISPLAY_LATEST:
22         context = {
23             'posts': Post.latest_posts()
24         }
25         result = render_to_string('config/blocks/sidebar_posts.html', context)
26     elif self.display_type == self.DISPLAY_HOT:
27         context = {
28             'posts': Post.hot_posts()
29         }
30         result = render_to_string('config/blocks/sidebar_posts.html', context)
31     elif self.display_type == self.DISPLAY_COMMENT:
32         context = {
33             'comments': Comment.objects.filter(status=Comment.STATUS_NORMAL)
34         }
35         result = render_to_string('config/blocks/sidebar_comments.html', context)
36 
37     return result
1 <ul>
2     {% for post in posts %}
3         <li><a href="{% url 'blog:post-detail' post.id %}">{{ post.title }}</a></li>
4     {% endfor %}
5 </ul>
sidebar_posts.html
 1 <ul>
 2     {% for comment in comments %}
 3         <li>
 4             <a href="{% url 'blog:post' comment.target_id %}">
 5                 {{ comment.target.title }}
 6             </a>
 7         </li>
 8         {{ comment.nickname }} : {{ comment.content }}
 9     {% endfor %}
10 </ul>
sidebar_comments.html

html代码的重构

 在我们的list.html和detail.html中,因为要展示分类和侧边栏,已经充斥着大量的重复代码,这样显然是不好的,如果以后要修改也会很麻烦,这里可以通过继承来解决这个问题.

首先抽象一个基础模板.建立一个base.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>{% block title %}
 6         首页
 7     {% endblock %}-友利奈绪</title>
 8 </head>
 9 <body>
10 <div>
11     顶部分类:
12     {% for cate in navs %}
13         <a href="{% url 'blog:category-list' cate.id %}">{{ cate.name }}</a>
14     {% endfor %}
15 </div>
16 <hr>
17 
18 {% block main %}
19 {% endblock %}
20 
21 <hr>
22 <div>
23     底部分类:
24     {% for cate in normal %}
25         <a href="{% url 'blog:category-list' cate.id %}">{{ cate.name }}</a>
26     {% endfor %}
27 </div>
28 <div>
29     侧边栏展示:
30     {% for sidebar in sidebars %}
31         <h4>{{ sidebar.title }}</h4>
32         {{ sidebar.content_html }}
33     {% endfor %}
34 </div>
35 </body>
36 </html>

这里的{% block %}{% endblock %}可以理解为抽象类里的抽象方法,是需要子类去实现的.

list.html

 1 {% extends 'base.html' %}
 2 
 3 {% block title %}
 4     {% if tag %}
 5         标签页: {{ tag.name }}
 6 
 7     {% elif category %}
 8         分类页: {{ category.name }}
 9 
10     {% else %}
11         Posts
12     {% endif %}
13 {% endblock %}
14 
15 {% block main %}
16     <ul>
17         {% for post in post_lists %}
18             <li>
19                 <a href="{% url 'blog:post-detail' post.id %}">{{ post.title }}</a>
20                 <div>
21                     <span>作者:{{ post.owner.username }}</span>
22                     <span>分类:{{ post.category.name }}</span>
23                 </div>
24                 <p>{{ post.desc }}</p>
25             </li>
26         {% endfor %}
27     </ul>
28 {% endblock %}

detail.html

 1 {% extends 'base.html' %}
 2 {% block title %}
 3     {{ post.title }}--友利奈绪
 4 {% endblock %}
 5 {% block main %}
 6     {% if post %}
 7         <h1>{{ post.title }}</h1>
 8         <div>
 9             <span>作者:{{ post.owner.username }}</span>
10             <span>分类:{{ post.category.name }}</span>
11         </div>
12         <hr>
13         <p>
14             {{ post.content }}
15         </p>
16     {% endif %}
17 {% endblock %}

这样代码就减少了冗余,后期维护成本也没那么高,在书中还说了解耦硬编码,不过在我之前的编写中我一直都是这样做的,所以就不重复说了.

另外说句题外话,本来写博客是为了提高自己的表达能力,结果现在看来我就像一个无情的贴代码机器,实在是有点..emmm

还有就是我在有道云笔记上面记的笔记直接贴上来一直在转圈圈,有点难受..害,明天继续加油吧.

猜你喜欢

转载自www.cnblogs.com/ylnx-tl/p/12623429.html
今日推荐