我们现在做的不是那种单独给某人使用的博客系统,而是一个多用户的系统了,即每个注册用户都可以发布文章。那么,如果读者想查看某个作者的全部文章,该如何做?这是一个非常合理的功能需求,如下图所示。

semanage命令 查看所有的_MySQL

既然要查阅某个作者的文章,那么就需要在请求时提供该作者的用户名,这种查找方式我们已经有经验了,读者如果忘记了过去的经验,请查阅本书前面的相关内容。

4.2.1 查看某作者的文章列表

首先要修改./article/list_views.py文件中的article_titles()视图函数,代码如下。

1 def article_titles(request,username=None): #①
2     if username:
3         user = User.objects.get(username=username) #②
4         article_title = ArticlePost.objects.filter(author=user) #③
5     else:
6         article_title = ArticlePost.objects.all()

语句①的参数列表用了username=None,这种方式兼顾两种可能,一种是直接请求所有文章标题,另一种是请求某个用户(作者)的文章标题。

语句②用于得到某个用户(作者)对象,并且用在语句③中,因为在ArticlePost类中,有author=models.ForeignKey(User,related_name="article")。

在模板文件中对作者名字增加超链接,实现单击作者名字查看该作者全部文章标题的功能。编辑./templates/article/list/article_titles.html文件,for循环块内的代码修改如下。

1 <div class="list-group">
2         <a href="{{article.get_url_path}}" class="list-group-item active">
3             <h4 class="list-group-item-heading"></h4></a>
4             <p class="list-group-item-text">作者:<a href="{% url 'article:author_articles'article.author.username %}">
5                 {{article.title}}{{article.author.username}}</a></p>
6             <p class="list-group-item-text">概要:{{article.body|slice:'70'|linebreaks}}</p>
7 
8</div>

这里依然使用了熟悉的{% url 'article:author_articles' article.author.username %}方式,并通过article.author.username传递username的值。

接着在./article/urls.py文件中增加URL配置代码。

1 re_path('list-article-titles/(?P<username>[-\w]+)/$',list_view.article_titles,name="author_articles"),

上述步骤完成后,检查Django服务是否已经运行。在服务运行的情况下访问项目,单击导航栏中的“文章”选项,可以查看所有文章标题。在每篇文章标题下面,作者的名称已经是超链接了,单击它可以查看该作者的全部文章标题,如下图所示。

上述步骤完成后,检查Django服务是否已经进行。在服务运行的情况下访问项目,单击导航栏中的“文章”选项,可以查看所有文章标题。在每篇文章标题下面,作者的名称已经是超链接了,单击它可以查看该作者的全部文章标题,如下图所示。

请认真观察浏览器地址栏中URL的特点。

至此,还没有结束。当用户查看某篇文章内容时,里面也有作者名称,还要做同样的链接。所以,要编辑./templates/article/list/article_detail.html文件,找到显示用户名的HTML标记符,用跟上面一样的处理方法,增加<a href="{% url 'article:author_articles' article.author.username %}">超链接。

semanage命令 查看所有的_数据库_02

不要忘记保存。刷新页面后测试新功能,这样就实现了本节开头所提出的功能需求。

其实,这里所呈现的作者文章标题列表页可以继续美化,比如显示该作者的有关信息,我们曾经在用户个人信息设置中让用户填写了不少内容呢!要实现这个功能,就需要对视图函数进行重写,再次编辑./article/list_views.py文件中的article_titles()函数。为了避免读者在反复修改时出现差错,下面列出全部代码。

1 def article_titles(request,username=None):
 2     if username:
 3         user = User.objects.get(username=username)
 4         article_title = ArticlePost.objects.filter(author=user)
 5         try:
 6             userinfo = user.userinfo #④
 7         except:
 8             userinfo = None
 9     else:
10         article_title = ArticlePost.objects.all()
11 
12     paginator = Paginator(article_title,2)
13     page = request.GET.get('page')
14     try:
15         current_page = paginator.page(page)
16         articles = current_page.object_list
17     except PageNotAnInteger:
18         current_page = paginator.page(1)
19         articles = current_page.object_list
20     except EmptyPage:
21         current_page = paginator.page(paginator.num_pages)
22         articles = current_page.object_list
23 
24     if username:
25         return render(request,"article/list/author_articles.html",{"articles":articles,"page":current_page,
26                                                                    "userinfo":userinfo,"user":user})  #⑤
27     return render(request,"article/list/article_titles.html",{"articles":articles,"page":current_page})

语句④用于创建该用户的UserInfo对象实例。读者是否还记得我们在编写关于用户信息的数据模型时,创建了UserInfo数据模型类,并且跟User类建立了“一对一”的关系。要通过User类的实例得到UserInfo类的信息,可以使用类似user.userinfo的模式,其中user是User类的实例,而userinfo就是UserInfo,只不过这里一定要用英文小写,这是规定。

在这里使用了try...except...,主要原因是有的用户可能没有填写自己的个人信息。

语句⑤则是当判断要访问某个用户的文章标题列表时,将userinfo也传到模板文件里。

接下来创建一个新的模板文件。在./templates/article/list目录中创建名为author_articles.html的文件,并输入如下代码。

1 {% extends "base.html" %}
 2 {% load staticfiles %}
 3 {% block title %}articles{% endblock %}
 4 {% block content %}
 5 <div class="row text-center vertical-middle-sm">
 6     <h1>阅读,丰富头脑,善化行为</h1>
 7 </div>
 8 <div class="container">
 9     <div class="col-md-8">
10         {% for article in articles %}
11         <div class="list-group">
12             <a href="{{article.get_url_path}}" class="list-group-item active">
13                 <h4 class="list-group-item-heading">{{article.title}}</h4>
14             </a>
15             <p class="list-group-item-text">作者:<a href="{% url 'article:author_articles' article.author.username %}">{{article.author.username}}</a> </p>
16             <p class="list-group-item-text">概要:{{article.body|slice:'70'|linebreaks}}</p>
17         </div>
18         {% endfor %}
19 {% include "paginator.html" %}
20     </div>
21     <div class="col-md-4">
22         <div>
23             {% if userinfo.photo %}
24             <img src="{{ userinfo.photo | striptags }}" class="img-circle" id="my_photo" name="user_face">
25             {% else %}
26             <img name="user_face" src="{% static 'images/newton.jpg' %}" class="img-circle" style = "width:150px;" id="my_photo">
27             {% endif %}
28         </div>
29         <div>
30             <p>{{ user.username }}</p>
31     {% if userinfo %}
32             <p>{{ userinfo.company }}</p>
33             <p>{{ userinfo.aboutme }}</p>
34     {% else %}
35             <p>这个作者太懒了,什么也没有留下。</p>
36     {% endif %}
37         </div>
38     </div>
39 </div>
40 {% endblock %}

 在文章标题列表页面的右边,显示该作者的某些信息,相关代码与作者的个人信息代码相似。

最后还要看一下效果,如下图所示。

semanage命令 查看所有的_semanage命令 查看所有的_03

 

4.2.2 知识点

1、数据库简介

作为一名网站开发程序员,必须要了解数据库知识,不要认为在Django中通过ORM操作数据库就足够了,这仅适用于某些项目,可能在有其他要求的醒目上没救不能使用ORM了,因此必须了解数据库并使用SQL。

  • SQLite

SQLite(http://www.sqlite.org)是一个轻型数据库,它不需要独立的数据库服务器,可以在所有主要的操作系统上运行。在本书的实例中就采用了这种数据库。读者可以查询项目根目录,它的操作与文件操作一样。

虽然SQLite比较袖珍,但可以支持高达2TB大小的数据库,每个数据库都是以单个文件的形式存在的,这些数据以B-Tree数据结构形式存储在磁盘上。尽管如此,读者也不要在真是的项目中使用它,除非保存的数据确实很少。

  • PostgreSQL

PostgreSQL(https://www.postgresql.org)号称是“世界上最先进的开源数据库”,之所以如此,首先因为它是开源的,曾经还有一个号称开源的MySQL,但“它变了”,现在只有PostgreSQL能扛起开源的大旗了。其次,PostgreSQL的确有它的特点,比如它的数据类型非常丰富,很多数据库都比不上它;它有专门的IP类型,别的数据库没有。再次,也是最值得一提的,PostgreSQL有用一支非常货源的开发队伍,目前的提交人员已经超过三十人,特别是有众多hacker的积极参与。PostgreSQL的稳定性非常高,受到了开发者的青睐。“稳定压倒一切”,是我们选择数据库的一个重要标准。当然,一般数据库有的PostgreSQL一样也不少,比如适合众多操作系统、有众多接口等。

总之,PostgreSQL值得学习研究,更值得拥有。

  • MySQL

MySQL(https://www.mysql.com)曾经是做网站开发的程序员最喜欢的数据库,虽然现在仍有很多网站中哎使用它,但毕竟是属于Oracle旗下的产品了,不再是自由软件了。目前,Oracle采用了双授权政策,将MySQL分为社区版和商业版,一些中小网站也在使用它。MySQL有着很多优点,所以在网站开发中依然有着举足轻重的地位,特别是在Linux作为操作系统、Apache或Nginx作为Web服务器、MySQL作为数据库、PHP/Perl/Python作为服务器端脚本解释器这种绝配组合中,地位相当稳固。

2、数据库设置

本书中示例的项目采用了Django项目创建之后的默认数据库SQLite,除这个数据库外,Django项目还支持使用常见的PostgreSQL、MySQL和Oracle。另外,通过第三方模块,还可以支持IBM DB2、Microsoft SQL Server等。

数据库的位置在settings.py(在本书的项目中,位置在./testsite/settings.py),设置DATABASES变量的值即可。下面是默认的SQLite数据库配置。

1 DATABASES = {
2     'default': {
3         'ENGINE': 'django.db.backends.sqlite3',
4         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
5     }
6 }

如果是PostgreSQL数据库,则可以参考如下配置方式。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql', #数据库服务器
        'NAME': 'mydatabase',  #自己为数据库确定一个名称
        'USER':'mydatabaseuser', #登录数据库的用户名
        'PASSWORD':'mypassword', #上述用户登录数据库的密码
        'HOST':'127.0.0.1',
        'PORT':'5432',
    }
}