在Django中,有时几个页面中要显示的数据一样,或者说一个页面中,点击链接只会刷新其中一部分内容,其他的不变。
这样,我们就可以将相同的、需要渲染在模板中的数据,写成全局的,这样减少代码的重复书写
例如:
当点击某一个月份文章归档时,只有文章那一块会发生变化,其他都不变化
然后,我们就需要将其他的做成全局的。
在views.py中
def global_params(request):
# 该函数中用于保存一些全局变量,每个/多个视图函数都要使用并且代码都没有发生变化的变量。所以可以对这些重复性的代码进行优化,直接设置为全局变量,不用在渲染模版的时候每次都传递这些变量。
# 查询所有分类信息
category_list = Category.objects.all()
# 查询所有广告信息
ad_list = Ad.objects.all()
archive_list = Article.objects.archive_date(article_list=Article.objects.all())
# 评论排行
# [{'article': 1, 'count': 3},{}]
article_dict_list = Comment.objects.values('article').annotate(count=Count('article')).order_by('-count')
# 从查询结果集合QuerySet中,根据article的id,取出这个文章的Model对象。
result_list = [Article.objects.get(id=article_dict['article']) for article_dict in article_dict_list]
if len(result_list) > 6:
result_list = result_list[:6]
# 浏览排行
# 三目运算符:a = if b>c? 10:20
# if条件成立,则取Article.objects.all().order_by('-click_num')[:6]的值;if条件不成立,则取else:Article.objects.all().order_by('-click_num')的值;
click_list = Article.objects.all().order_by('-click_num')[:6] if len(Article.objects.all()) >= 6 else Article.objects.all().order_by('-click_num')
# 标签云
tag_list = Tag.objects.all()
return {
'category_list': category_list,
'ad_list': ad_list,
'archive_list': archive_list,
'comment_list': result_list,
'click_list': click_list,
'tag_list': tag_list
}
def process_paginator(request, article_list):
paginator = Paginator(article_list, 1)
try:
page_number = int(request.GET.get('page', '1'))
page = paginator.page(page_number)
except (PageNotAnInteger, EmptyPage, InvalidPage):
page = paginator.page(1)
return page
def index(request):
# 所有文章信息
article_list = Article.objects.all()
page = process_paginator(request, article_list)
title = '最新文章'
# 文章归档:
# 第一种方法就是定义一个普通的函数archive_article。
# archive_list = archive_article(article_list)
# 第二种方式:通过自定义管理器Manager方法实现,通过这种方法,可以实现Article.objects.xxx()的调用方式;
# 1. 在models.py中自定义一个管理器(一定要继承于内置的Manager类。);
# 2. 在需要使用的Model类中,注册这个管理器,那么这个Model就可以使用这个管理器方法了;
# archive_list = Article.objects.archive_date(article_list=article_list)
return render(request, 'index.html', locals())
def archive(request, year, month):
# 查询发布日期中含有:2018-10 的数据
article_list = Article.objects.filter(date_publish__icontains=year+'-'+month)
page = process_paginator(request, article_list)
return render(request, 'index.html', locals())
其中的global_params函数里面写的都是下面的函数渲染模板都需要用到的,那么除了将这些数据单独写在一个函数之外,还需要在settings.py中设置:
哪个APP下的哪个文件下的哪个函数是全局的
这个实现了
其中,在global_params函数中,有一点,将对文章的创建时间的处理封装成了Article类的对象
能有Article.objects.调用的都是all() get() filter() 是Django封装好的,可直接调用。但是我们也可以自己封装一个,使其能够Article,objects…调用
在models.py中封装:
class ArticleManager(models.Manager):
def archive_date(self, article_list):
archive_list = []
# 需要获取所有的文章model对象。
for article in article_list:
# 将每一个文章的发布日期都获取出来,按照'%Y/%m'进行格式化
pub_date = article.date_publish.strftime('%Y/%m')
if pub_date not in archive_list:
# 如果这个时间字符串不在article_list这个列表中,就把这个年月添加进去
archive_list.append(pub_date)
return archive_list
class Article(models.Model):
objects = ArticleManager()
title = models.CharField(max_length=50, verbose_name='文章标题')
desc = models.CharField(max_length=50, verbose_name='文章简介')
content = models.CharField(max_length=255, verbose_name='文章内容')
click_num = models.IntegerField(verbose_name='点击量', default=0, editable=True)
comment_num = models.IntegerField(verbose_name='评论量', default=0, editable=True)
date_publish = models.DateTimeField(auto_now_add=True, verbose_name='发布时间')
tag = models.ManyToManyField(Tag, verbose_name='所属标签')
category = models.ForeignKey(Category, verbose_name='所属分类', on_delete=models.DO_NOTHING, blank=True, null=True)
注意两点:一、封装的类要继承自models.Manager
二、在要进行Article.objects.调用的Article类中,写上
objects = ArticleManager()
这样,才可以,在views.py中写:Article.objects.archive_date()
archive_date是封装那个类中的函数
还有,注意传参,一定要一致