[Django学习] Django基础(9)_阅读计数

一. 简单计数法

(一) 实施方法

  1. 在现有的models模型中添加readed_num字段用于记录阅读数据。

class Blog(models.Model):
	title = models.CharField(max_length=50)
	blog_type = models.ForeignKey(BlogType, on_delete=models.DO_NOTHING)
	content = RichTextUploadingField()
	author = models.ForeignKey(User, on_delete=models.DO_NOTHING)
	readed_num = models.IntegerField(default=0)

  2. 通过设定浏览器cookie规则,将用户访问时产生的cookie保存到本地;

  3. 每次访问时,读取cookie,若存在,readed_num+1

def blog_detail(request, blog_pk):
	""" render data to blog_detail.html """
	blog = get_object_or_404(Blog, pk=blog_pk)
        # 访问时,读取cookie文件进行判断
	if not request.COOKIES.get(‘blog_%s_readed‘ % blog_pk):
		blog.readed_num += 1
		blog.save()
	context = {}
	context[‘blog‘] = blog
	context[‘previous_blog‘] = Blog.objects.filter(create_time__gt=blog.create_time).last()
	context[‘next_blog‘]=Blog.objects.filter(create_time__lt=blog.create_time).first()
	response = render_to_response(‘blog/blog_detail.html‘, context)
        # 设定浏览器cookie存储规则
	response.set_cookie(‘blog_%s_readed‘ % blog_pk,‘true‘)
	return response  

(二) 优点缺点

  1. 优点

    简单,易理解

  2. 缺点

    (1) 后台编辑时,若有人访问数据,产生的阅读计数被编辑时的数据覆盖

    (2) 功能单一,无法统计某一天的阅读数

二.  对任意模型计数

博客-|    |-关联哪个模型?
教程--计数-
其他-|    |-对应哪个对象?

  若相对任意模型计数,必须知道计数的方法关联哪个模型?对应哪个模型对象?  

三. ContentType--对特定模型及对象进行管理

(一) contenttypes framework

  Django包含一个contenttypes应用程序,它可以跟踪安装在Django驱动的项目中的所有模型,为使用模型提供高级的通用接口。

  ContentType应用程序的核心是ContentType模型,通过django.contrib.contenttypes.models.ContentType引用。ContentType实例表示并存储有关在项目中安装的模型的信息,每当安装新模型时,就自动创建ContentType的新实例。

  ContentType实例具有返回它们表示的模型类和从这些模型查询对象的方法。ContentType还有一个自定义管理器 ContentTypeManager,用于添加处理ContentType和获取特定模型的ContentType实例的方法。

  您的模型和ContentType之间的关系还可以用于在您的一个模型的实例和您安装的任何模型的实例之间启用“通用”关系。

(二) 使用ContentType计数

1. 创建统计应用blogstatistics

2. 创建统计模型ReadNum

   按照contenttypes framework的文档(如图所示)创建要统计模型。

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey

# Create your models here.
class ReadNum(models.Model):
	read_num = models.IntegerField(default=0)
	content_type = models.ForeignKey(ContentType,on_delete=models.DO_NOTHING)
	object_id = models.PositiveIntegerField()
	content_object = GenericForeignKey(‘content_type‘,‘object_id‘)

3. 在blog应用中引用blogstatistics应用创建的模型

class Blog(models.Model):
	title = models.CharField(max_length=50)
	blog_type = models.ForeignKey(BlogType, on_delete=models.DO_NOTHING)
	content = RichTextUploadingField()
	author = models.ForeignKey(User, on_delete=models.DO_NOTHING)
	create_time = models.DateTimeField(auto_now_add=True)
	last_update = models.DateTimeField(auto_now=True)

	def get_read_num(self):
		try:
			ct = ContentType.objects.get_for_model(self)
			readnum = ReadNum.objects.get(content_type=ct,object_id=self.pk)
			return readnum.read_num
		except exceptions.ObjectDoesNotExist:
			return 0

	def __str__(self):
		return "<BLog: %s>" % self.title

	class Meta:
		ordering = [‘-create_time‘]

4. 在blog.views.py中引用blogstatistics应用创建的模型 

def blog_detail(request, blog_pk):
	""" render data to blog_detail.html """
	blog = get_object_or_404(Blog, pk=blog_pk)
	if not request.COOKIES.get(‘blog_%s_readed‘ % blog_pk):
		ct = ContentType.objects.get_for_model(Blog)
		if ReadNum.objects.filter(content_type=ct,object_id=blog.pk):
			readnum = ReadNum.objects.get(content_type=ct,object_id=blog.pk)
		else:
			readnum = ReadNum(content_type=ct,object_id=blog.pk)
		readnum.read_num += 1
		readnum.save()

	context = {}
	context[‘blog‘] = blog
	context[‘previous_blog‘] = Blog.objects.filter(create_time__gt=blog.create_time).last()
	context[‘next_blog‘]=Blog.objects.filter(create_time__lt=blog.create_time).first()
	response = render_to_response(‘blog/blog_detail.html‘, context)
	response.set_cookie(‘blog_%s_readed‘ % blog_pk,‘true‘)
	return response

5. 在模版页面中直接调用blog.models.Blog模型的方法get_read_num

<p class="blog-info">
    <span class="glyphicon glyphicon-tags"></span><a href="{% url ‘blogs_with_type‘ blog.blog_type.pk %}">  {{ blog.blog_type }}</a>  
    <span class="glyphicon glyphicon-calendar"></span>  {{ blog.create_time|date:"Y-m-d" }}  <span class="glyphicon glyphicon-star-empty"></span>  阅读({{blog.get_read_num}})
</p>

四. 重复代码封装--实现通用性统计计数

  通过类的继承来实现类函数的继承调用

(一) 需要封装的地方(红色标记)

def blog_detail(request, blog_pk):
	""" render data to blog_detail.html """
	blog = get_object_or_404(Blog, pk=blog_pk)
	if not request.COOKIES.get(‘blog_%s_readed‘ % blog_pk):
		ct = ContentType.objects.get_for_model(Blog)
		if ReadNum.objects.filter(content_type=ct,object_id=blog.pk):
			readnum = ReadNum.objects.get(content_type=ct,object_id=blog.pk)
		else:
			readnum = ReadNum(content_type=ct,object_id=blog.pk)
		readnum.read_num += 1
		readnum.save()

	context = {}
	context[‘blog‘] = blog
	context[‘previous_blog‘] = Blog.objects.filter(create_time__gt=blog.create_time).last()
	context[‘next_blog‘]=Blog.objects.filter(create_time__lt=blog.create_time).first()
	response = render_to_response(‘blog/blog_detail.html‘, context)
	response.set_cookie(‘blog_%s_readed‘ % blog_pk,‘true‘)
	return response
class Blog(models.Model):
	title = models.CharField(max_length=50)
	blog_type = models.ForeignKey(BlogType, on_delete=models.DO_NOTHING)
	content = RichTextUploadingField()
	author = models.ForeignKey(User, on_delete=models.DO_NOTHING)
	create_time = models.DateTimeField(auto_now_add=True)
	last_update = models.DateTimeField(auto_now=True)

	def get_read_num(self):
		try:
			ct = ContentType.objects.get_for_model(self)
			readnum = ReadNum.objects.get(content_type=ct,object_id=self.pk)
			return readnum.read_num
		except exceptions.ObjectDoesNotExist:
			return 0

	def __str__(self):
		return "<BLog: %s>" % self.title

	class Meta:
		ordering = [‘-create_time‘]

(二) 方法

1. 在blogstatistics.models中创建类,将get_read_num方法封装到该类中。

注意:get_read_num方法参数是self

class ReadNumExpandMethod():
	def get_read_num(self):
		try:
			ct = ContentType.objects.get_for_model(self)
			readnum = ReadNum.objects.get(content_type=ct,object_id=self.pk)
			return readnum.read_num
		except exceptions.ObjectDoesNotExist:
			return 0

2. 在blog.models中继承ReadNumExpandMethod类。Blog模型即可调用ReadNumExpandMethod.get_read_num(),且该方法调用的参数是self=Blog 

class Blog(models.Model, ReadNumExpandMethod):
	title = models.CharField(max_length=50)
	blog_type = models.ForeignKey(BlogType, on_delete=models.DO_NOTHING)
	content = RichTextUploadingField()
	author = models.ForeignKey(User, on_delete=models.DO_NOTHING)
	create_time = models.DateTimeField(auto_now_add=True)
	last_update = models.DateTimeField(auto_now=True)

	def __str__(self):
		return "<BLog: %s>" % self.title

	class Meta:
		ordering = [‘-create_time‘]

3. 在blogstatistics应用中新建一个python文件utils.py,对blog.views.py中关于COOKIE的内容进行封装  

from django.contrib.contenttypes.models import ContentType
from .models import ReadNum

def read_statistics_once_read(request, obj):
	ct = ContentType.objects.get_for_model(obj)
	key = "%s_%s_read" % (ct.model,obj.pk)

	if not request.COOKIES.get(key):
		if ReadNum.objects.filter(content_type=ct, object_id=obj.pk).count():
			readnum = ReadNum.objects.get(content_type=ct, object_id=obj.pk)
		else:
			readnum = ReadNum(content_type=ct, object_id=obj.pk)
		readnum.read_num += 1
		readnum.save()
	return key

4. blog.views.py中blog_detail函数即可使用该封装的函数。

def blog_detail(request, blog_pk):
	""" render data to blog_detail.html """
	blog = get_object_or_404(Blog, pk=blog_pk)
	read_cookie_key = read_statistics_once_read(request, blog)

	context = {}
	context[‘blog‘] = blog
	context[‘previous_blog‘] = Blog.objects.filter(create_time__gt=blog.create_time).last()
	context[‘next_blog‘]=Blog.objects.filter(create_time__lt=blog.create_time).first()
	response = render_to_response(‘blog/blog_detail.html‘, context)
	response.set_cookie(read_cookie_key,‘true‘)
	return response


注明:学习资料来自“再敲一行代码的个人空间”以及“杨仕航的博客”  

原文地址:https://www.cnblogs.com/AngryZe/p/9284771.html

时间: 2024-10-01 05:14:07

[Django学习] Django基础(9)_阅读计数的相关文章

Django学习之 - 基础部分

学习记录参考: 讲师博客:http://www.cnblogs.com/wupeiqi/articles/5433893.html 老男孩博客:http://oldboy.blog.51cto.com/ 运维平台参考:http://oldboy.blog.51cto.com/2561410/1123127 WEB框架简写与解释解释:Web应用框架有助于减轻网页开发时共通性活动的工作负荷,例如许多框架提供数据库访问接口.标准样板以及会话管理等,可提升代码的可再用性. MVC框架 == Model

[Django学习] Django基础(10)_ContentType学习总结

一. 什么是ContentTypes Django ContentTypes是由Django框架提供的一个核心功能.Django ContentTypes是一个记录了项目中所有model元数据的表,表中一条记录对应着一个存在的model. 当使用django-admin初始化一个django项目的时候,可以看到在默认的INSTALL_APPS已经包含了django.contrib.contenttypes: INSTALLED_APPS = [ 'django.contrib.admin', '

[Django学习]Django基础(15)_ajax的评论提交

一 功能介绍 点击"评论"按钮时,不刷新页面,将评论内容直接插入下方的评论列表中. 二 实现方式 1. 为评论框表单设置id属性 // 为评论框表单设置id属性comment_form <form id="comment_form" action="{% url 'update_comment' %}" method="POST" sytle="overflow:hidden"> {% csrf

Django学习之 - 基础模板语言

模板语言循环 1:如果模板语言遇到列表,直接进行循环取值即可. 2:如果模板语言遇到字典进行循环有以下3种: - for item in dict.keys 只循环获取字典key - for item in dict.value 只循环获取字典value - for k,v in dict.items 循环获取字典的key,value全部.实例url:fordict # 字典for循环的取值方法 1 userlist = { 2 '1': {'name': 'jack', 'age': 36},

Django学习日记05_模板_模板语言

Variables 在模板中,使用两个大括号包含变量的方式来使用变量: {{ name }} 该变量应该作为键值对中的键,在Context中能被查找到. Tags 模板中使用Tags来进行简单的逻辑: {% commet %}? ? #body{% endcommet %} Django内置了大量的Tags: 1. if :使用if标签来实现分支逻辑 {%if option%}? ? #if body{%elif option2%}?? ? #elif body{%else%}?? ? #els

Django学习-----Django开发流程

1. 安装django Django的下载地址:https://www.djangoproject.com/download/ 解压缩后进入这个目录,执行python setup.py install 2. 测试 #python #import python 没有出现错误,证明安装成功 3.创建django项目 #django-admin.py startproject  web_01 4. 修改settings.py 修改TIME_ZON为  Asia/Shanghai 修改LANGUAGE_

django学习之旅 - 基础命令讲解

好久没有写博文了,之前总是写python脚本,一直没有写过python web方面的东西,web方面的作品都用php写的,最近在死命的学习django,打算好好写一个python方面的作品,我一直在想,能不能写一个安卓app来做我平时的工作呢,还是不好高骛远了,先把django学好吧,这个是之前写的笔记,因为赶上节日所以用手机看视频资料学习的就没有过多的整理文档,在后续会慢慢的讲文档都加上. OK,这篇文档就简单的讲讲django的基础命令, 以及一个简单的小实例吧. django 基础命令讲解

Django学习记录_安装(一)

如果有报错先安装setuptools yum install python-setuptools 下载pip wget --no-check-certificate https://github.com/pypa/pip/archive/1.5.5.tar.gz 源码安装pip tar xf 1.5.5.tar.gz cd    pip-1.5.5/ python setup.py install pip安装django1.7 pip install Django==1.7 出现 "Cleani

Django学习系列之基础

Django介绍 Django简介 Django是一个基于MVC构造的框架.但是在Django中,控制器接受用户输入的部分由框架自行处理,所以 Django 里更关注的是模型(Model).模板(Template)和视图(Views),称为 MTV模式,它们各自的职责如下: 模型(Model),即数据存取层 处理与数据相关的所有事务: 如何存取.如何验证有效性.包含哪些行为以及数据之间的关系等 视图(View),即表现层 处理与表现相关的决定: 如何在页面或其他类型文档中进行显示;模型与模板的桥