Django后台自动填充当前登录用户为文章发布作者
2020-11-19     loonlog     3996     2
本文目录
1、建立Entry模型的博客
import datetime from django.contrib.auth.models import User from django.db import models class Entry(models.Model): title = models.CharField(max_length=250) slug = models.SlugField() pub_date = models.DateTimeField(default=datetime.datetime.now) author = models.ForeignKey(User, related_name='entries') summary = models.TextField(blank=True) body = models.TextField() class Meta: get_latest_by = 'pub_date' ordering = ('-pub_date',) verbose_name_plural = 'entries' def __unicode__(self): return self.title def get_absolute_url(self): return "/weblog/%s/%s/" % (self.pub_date.strftime("%Y/%b/%d"),self.slug)
2、一步一步设计admin.py文件
我们在admin.py文件里面为Entry模型编写一个ModelAdmin类,用来在后台管理这个数据模型;除了常规项目,另外在保存每个新建Entry时,自动将当前创建Entry的登录用户写入“author”字段。
我们从博客应用程序的admin.py文件中填写ModelAdmin的常规选项开始:
from django.contrib import admin from blog.models import Entry class EntryAdmin(admin.ModelAdmin): list_display = ('title', 'pub_date', 'author') prepopulated_fields = { 'slug': ['title'] } admin.site.register(Entry, EntryAdmin)
因为我们将自动填写author字段,所以需要在后台编辑页面里面使用exclude = ('author',)语句隐藏这个字段:
class EntryAdmin(admin.ModelAdmin): exclude = ('author',) list_display = ('title', 'pub_date', 'author') prepopulated_fields = { 'slug': ['title'] }
接下来就是覆盖EntryAdmin上的一种数据保存方法。 此方法称为save_model:
它接收当前HttpRequest,将要保存的对象(obj),用于验证其数据的表单(form),以及指示该对象是否将被第一次保存或者已经存在并正在编辑的布尔标志作为参数(change)。
由于我们只需要在创建时填写作者字段,我们就可以查看该标志。 代码最终看起来像这样:
def save_model(self, request, obj, form, change): if not change: obj.author = request.user obj.save()
就是这样:该方法所要做的就是保存对象,并且可以在保存之前做任何想做的事情。 并且由于它接收HttpRequest作为参数,因此它可以访问request.user并可以在保存之前将其填写在Entry上。 参阅官方文档:https://docs.djangoproject.com/en/dev/ref/contrib/admin/#save-model-self-request-obj-form-change,文档是好东西。
3、扩展功能
以上即可实现自动填充author字段,但还是需要其他功能加以配合才完美,比如超级管理员可以修改其他用户的文章:
对于大多数人来说,难题的另一半是将管理员中可查看/可编辑对象的列表限制为仅由当前用户“拥有”的对象。 在我们的示例博客应用程序中,这意味着将管理员更改列表中的条目列表限制为仅由当前用户发布的条目。 为此,我们需要对EntryAdmin类进行两项更改:一项处理对象的主要列表,另一项确保恶意用户无法绕开它并通过知道其ID并直接跳转来编辑对象 到其编辑页面。
首先,我们在EntryAdmin上覆盖方法queryset; 这将生成用于Entry对象主列表的QuerySet,并且可以访问HttpRequest对象,因此我们可以根据request.user过滤条目:
def queryset(self, request): return Entry.objects.filter(author=request.user)
当然,这有一个问题:它会完全隐藏除您自己编写的条目以外的所有条目,我们可能希望有一些极受信任的人能够查看和编辑其他人的条目。 这些人最有可能在其用户帐户上将is_superuser标志设置为True,因此我们可以向他们显示完整列表,仅过滤其他人:
def queryset(self, request): if request.user.is_superuser: return Entry.objects.all() return Entry.objects.filter(author=request.user)
但是,这只会影响列表视图中显示的条目。 从单个对象编辑页面调用另一个方法has_change_permission,以确保允许用户编辑该对象。 而且,如果用户对所讨论的模型类具有“更改”权限,则该方法默认情况下返回True,因此我们需要对其进行更改以检查类级别的权限,然后检查用户是否为 条目的超级用户或作者。 这是代码(此方法同时接收HttpRequest和对象作为参数):
def has_change_permission(self, request, obj=None): has_class_permission = super(EntryAdmin, self).has_change_permission(request, obj) if not has_class_permission: return False if obj is not None and not request.user.is_superuser and request.user.id != obj.author.id: return False return True
4、完整admin.py文件
最后,这是包含完整类的完整admin.py文件:
from django.contrib import admin from blog.models import Entry class EntryAdmin(admin.ModelAdmin): exclude = ('author',) list_display = ('title', 'pub_date', 'author') prepopulated_fields = { 'slug': ['title'] } def has_change_permission(self, request, obj=None): has_class_permission = super(EntryAdmin, self).has_change_permission(request, obj) if not has_class_permission: return False if obj is not None and not request.user.is_superuser and request.user.id != obj.author.id: return False return True def queryset(self, request): if request.user.is_superuser: return Entry.objects.all() return Entry.objects.filter(author=request.user) def save_model(self, request, obj, form, change): if not change: obj.author = request.user obj.save() admin.site.register(Entry, EntryAdmin)
参考:https://www.b-list.org/weblog/2008/dec/24/admin/
http://loonlog.com/2020/11/19/django-user-admin-author/
评论列表,共 2 条评论
回复
OωO博主你好,申请互换友情链接! 站点名:宠物知道网 站点地址:***.com.cn/ 宠物知道网是非常受宠物欢迎的宠物知识宠物教程网站,站内拥有宠物健康,宠物饲养,宠物训练,猫咪饲养,猫咪健康,猫咪训练,狗狗饲养,狗狗训练,狗狗健康……等优秀栏目。
回复
不好意思,非博客类,暂不加友联