若是知道每篇文章的瀏覽量,管理員就能夠了解到訪問者對文章的喜愛程度,方便後續推出相關內容文章,同時對熱門博客的統計和閱讀趨勢圖打好基礎。針對閱讀統計功能,前先後後我一共想到了三種方法,各類方法都有利有弊。python
採用該模型字段計數django
1.修改Post模型read_numcookie
2.優化:設置cookie判斷是否用戶屢次點擊response.set_cookie()
優勢:簡單
缺點:1.後臺編輯博客可能影響數據
2.功能單一,沒法統計某一天的閱讀數量工具
3.具體實現:post
在Post模型類中直接定義一個read_num的字段名優化
read_num = models.IntegerField(default=0)
而後能夠經過對Post屬性read_num的操做來實現閱讀計數+1的邏輯處理設計
post.read_num += 1 post.save()
設計功能獨立的ReadNum模型數據表code
1.添加read_num字段對象
2.增長post外鍵blog
3.利用ReadNum.objects.filter(post=post)來過濾當前的文章計數對象
4.優化:設置cookie判斷是否用戶屢次點擊response.set_cookie()
具體實現:
在blog/models.py文件中,與定義Post相似,定義一個ReadNum的模型類
class ReadNum(models.Model): read_num = models.IntegerField(u'閱讀次數', default=0) post = models.OneToOneField(Post, on_delete=models.CASCADE) def __str__(self): return self.read_num class Meta: verbose_name = '閱讀' verbose_name_plural = '閱讀'
經過objects的filter方法來過濾當前博客是否有閱讀的記錄,如不存在記錄,則建立新的readnum計數對象
if ReadNum.objects.filter(post=post).count(): # 存在記錄 readnum = ReadNum.objects.get(post=post) else: # 不存在記錄 readnum = ReadNum(post=post) readnum.read_num += 1 readnum.save()
閱讀計數表就算是建好了,還須要將閱讀數量加到後臺的每篇文章中,在Post模型類中添加該方法
def get_read_num(self): try: return self.readnum.read_num except exceptions.ObjectDoesNotExist: return 0
將get_read_num方法添加到admin.py的list_display中
list_display = ('id', 'title', 'created_time', 'modified_time', 'category', 'author', 'get_read_num')
設計功能獨立的計數應用read_statistics
1.導入兩個模塊GenericForeignKey和ContentType(很是重要)
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType
2.新增ReadNum模型表,建立read_num這個字段名
from django.db import models from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType class ReadNum(models.Model): """ 單篇博客計數的模型類 繼承model.Model模型類 """ read_num = models.IntegerField(u'閱讀計數', default=0) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() # 使用contenttypes模型類來找出關聯blog content_object = GenericForeignKey('content_type', 'object_id') class Meta: verbose_name = '閱讀計數' verbose_name_plural = '閱讀計數' ordering = ['-read_num']
3.新增utils.py做爲工具包,加入閱讀計數+1的邏輯處理
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, created = ReadNum.objects.get_or_create(content_type=ct, object_id=obj.pk) # 計數+1 readnum.read_num += 1 readnum.save()
4.解決後臺計數對象沒建立時的解決辦法,新增一個ReadNumExpandMethod類
class ReadNumExpandMethod(object): """ 計數擴展類,此方法放在admin的list_display中 繼承object模型類 """ def get_read_num(self): ct = ContentType.objects.get_for_model(self) # 此處的一個異常處理,用來捕獲沒有計數對象的狀況 # 例如在admin後臺中,沒有計數值會顯示爲‘-’ try: readnum = ReadNum.objects.get(content_type=ct, object_id=self.pk) return readnum.read_num # 對象不存在就返回0 except exceptions.ObjectDoesNotExist: return 0
而後讓blog/models中的Post模型類繼承ReadNumExpandMethod類中的方法
class Post(models.Model, ReadNumExpandMethod): ...
5.將方法加入到blog/amdin.py中的list_display中
list_display = ('id', 'title', 'created_time', 'modified_time', 'category', 'author', 'get_read_num')
以上就是文章閱讀計數的簡單方法,這三種方法的共同缺點就是功能單一,沒法統計某一天的閱讀數量,下一篇內容將對閱讀計數內容進行優化,增長日期的閱讀量查詢