如何在Django中统计单资源总下载次数并在后台展示
功能实现步骤
1. 调整模型层,增加总下载次数字段
现有ManyToMany关联User的逻辑只能统计登录用户的下载行为,无法覆盖游客下载场景,先在Item模型中新增独立计数字段:
# 原有字段保留 upload = models.FileField(upload_to ='uploads/') downloads = models.ManyToManyField(User, related_name='post_download', blank=True) # 新增总下载次数字段 download_count = models.IntegerField(default=0, verbose_name="总下载次数")
修改完成后执行数据库迁移:python manage.py makemigrationspython manage.py migrate
2. 修正下载视图逻辑,同步更新统计
现有视图存在两个问题:一是参数获取逻辑错误,已经通过路由拿到pk参数仍尝试从POST请求读item_id;二是缺少文件下载逻辑,加完关联直接跳转详情页不会触发下载,修正后代码如下:
from django.http import FileResponse import os from django.conf import settings def DownloadView(request, pk): # 直接用路由传递的pk获取资源 post = get_object_or_404(Item, id=pk) # 下载次数+1 post.download_count += 1 # 登录用户去重逻辑:同一用户多次下载只记录一次关联(可根据需求决定是否保留) if request.user.is_authenticated and not post.downloads.filter(id=request.user.id).exists(): post.downloads.add(request.user) post.save(update_fields=['download_count']) # 返回文件下载响应 file_path = os.path.join(settings.MEDIA_ROOT, post.upload.name) response = FileResponse(open(file_path, 'rb')) response['Content-Disposition'] = f'attachment; filename="{os.path.basename(file_path)}"' return response
可选优化:如果需要避免短时间内重复请求刷高计数,可以增加IP校验逻辑,把用户IP和资源ID存到缓存中设定过期时间,过期前重复请求不计数
3. 修改模板下载链接,触发统计逻辑
原有模板的下载链接直接指向静态资源URL,不会触发统计逻辑,改成指向下载视图的路由即可:
<div class="flex items-center justify-center"> <a href="{% url 'download_post' item.pk %}" class="text-white w-full text-center bg-black p-4 rounded-lg mt-8 hover:bg-gray-800"> <button>Download this file | <span class="text-xs text-green-400">{{object.upload.size|filesizeformat}}</span></button> </a> </div>
如果需要前台展示下载次数,直接在模板中调用{{ item.download_count }}即可。
4. 后台展示下载次数
在项目的admin.py中注册Item模型时,把下载次数字段加入展示列表:
from django.contrib import admin from .models import Item class ItemAdmin(admin.ModelAdmin): # 后台列表页展示的字段,可根据你的需求补充其他字段 list_display = ['id', 'upload', 'download_count'] # 设计数字段为只读,防止后台手动修改统计值 readonly_fields = ['download_count', 'downloads'] admin.site.register(Item, ItemAdmin)
内容的提问来源于stack exchange,提问作者Waqart
相关产品推荐
相关产品推荐

