Django文章浏览量设计

linxiaoyun 2017.5.6 21:52 1083 0
Django技术 Django

文章被浏览的数量,简单的方式处理是通过Post里设置read_num进行记录,在views中对应详情页处理函数detail(request,pk)里处理,引入cookie优化阅读量概念的——关闭浏览器表示一次阅读。

models.py:Post
#read_num = models.PositiveIntegerField('阅读量',default=0)
views.py:detail(request,pk)

post = get_object_or_404(Post,pk=pk)

strs = 'post_%s_readed'% pk

obj_type = ContentType.objects.get_for_model(Post)
v = ViewNum.objects.get_or_create(content_type=obj_type,object_id=post.id)
if strs not in request.COOKIES:
    post.read_num+=1
    post.save()
    
    ……
#设置临时cookie,该cookie有效期知道浏览器关闭
response.set_cookie( strs,True)

然而,每次打开详情页调用一次detail就保存了一次post,使得Post中设置了auto_now的modified_time概念上从“最后修改”变成了“最后浏览”。

modified_time = models.DateTimeField('更新时间',auto_now=True,null=True)

所以一个解决办法是把read_num放到另一个模型表中保持更新,而不影响Post,通过设置一般外键关系建立两模型表的关系。

新的模型表ViewNum利用ContentObject——这是一个模型总表实例的概念,通过ContentType和Object_id可以访问关联的ViewNum记录。

class ViewNum(models.Model):
    content_type=models.ForeignKey(ContentType)
    object_id=models.PositiveIntegerField()
    content_object=GenericForeignKey()

    view_nums = models.PositiveIntegerField(default=0)

此处,我们只需用Post和post便可以访问view_nums

views.py:detail(request,pk)

obj_type = ContentType.objects.get_for_model(Post)
v = ViewNum.objects.get_or_create(content_type=obj_type,object_id=post.id)
if strs not in request.COOKIES:
    v[0].view_nums+=1
    v[0].save()

在模板文件中,通过自定义标签访问view_nums,自定义模板标签get_view_num

@register.simple_tag
def get_view_num(post_id):
    obj_type = ContentType.objects.get_for_model(Post)
    v = ViewNum.objects.get_or_create(content_type=obj_type, object_id=post_id)
    return v[0].view_nums

在这里与杨仕航的做法不一样,自定义模板标签传入参数Object_id,概念更加清晰,即已知一个post实例,获取该实例对应的view_nums。v[0]因为get_or_create返回一个元组,其第一个元素为ViewNum实例。

自定义标签使用如下:

{% load blog_tags %}
……
{% get_view_num  post.id  %}

其中自定义标签get_view_num位于blog_tags中,在templatetags文件夹下。

在admin中Post管理注册时,也不能通过字段read_num了,需要通过函数访问对应的ViewNum。

admin.py:PostAdmin

def view_num_count(self,obj):
    return sum(map(lambda x:x.view_nums,obj.view_num.all()))
view_num_count.short_description = '阅读量'

lambda取实例对应的字段,同时需要设置逆向关联,才能使用view_num.all()。

models.py:Post
view_num = GenericRelation(ViewNum)

当设置了逆向关联时,即可通过post.view_num.all()取得关联对象。自定义模板标签也可以修改如下,给自定义标签传递的是Post实例post

@register.simple_tag
def get_view_n(post):
    return sum(map(lambda x:x.view_nums,post.view_num.all()))


总结:MVC中,M中通过GenericForeignKey,GenericRelation设置一般外键关系和逆向关联;C中通过ContentType和Object_id获取关联的对象进行操作,V中通过自定标签进行呈现。

Last Modified·2017年5月6日 22:14

暂无评论

您尚未登录,请先才能评论。