Django Admin 实现外键过滤的方法
说明和Model
环境:
➜python Python3.6.3|Anacondacustom(x86_64)|(default,Oct62017,12:04:38) [GCC4.2.1CompatibleClang4.0.1(tags/RELEASE_401/final)]ondarwin Type"help","copyright","credits"or"license"formoreinformation. >>>importdjango >>>print(django.get_version()) 2.0.1 >>>
2018年05月23日更新:
可以通过get_changeform_initial_data函数来传递initial参数.
#admin.py
@admin.register(Score)
classScoreConfigAdmin(FilterUserAdmin):
#fields=('id','name')
form=ScoreConfigAdminForm
defget_changeform_initial_data(self,request):
initial=super().get_changeform_initial_data(request)
initial.update({'uid':request.user.id})
returninitial
#forms.py
classScoreConfigAdminForm(forms.ModelForm):
def__init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
ifnotkwargs.get('initial'):
return
self.uid=kwargs.get('initial').get('uid')
classMeta:
model=Score
fields='__all__'
有一个支持多用户(使用djangoadmin)的Blog,每一篇Post都需要记录是谁发表的并且属于那个Blog。
user与Blog的关系、Blog与Post有2种定义方式,一种是使用独立关系表,另外一种是直接在Model中定义中使用外键。
后面一种的model定义如下:
fromdjango.contrib.auth.modelsimportUser fromdjango.dbimportmodels classBlog(models.Model): ''' Blog ''' id=models.AutoField(unique=True,primary_key=True,verbose_name="序号") name=models.CharField(max_length=255,blank=True,null=True,verbose_name="名称") user=models.ForeignKey(User,on_delete=models.CASCADE) create_time=models.DateTimeField(verbose_name='添加时间',auto_now_add=True,blank=True) classMeta: verbose_name='Blog' verbose_name_plural='Blog管理' def__str__(self): returnself.name classPost(models.Model): ''' Post内容 ''' id=models.AutoField(unique=True,primary_key=True,verbose_name="序号") title=models.CharField(max_length=255,blank=True,null=True,verbose_name="标题") content=models.TextField(max_length=1024,blank=True,null=True,verbose_name="内容") blog=models.ForeignKey(Blog,on_delete=models.CASCADE,verbose_name="所属Blog") user=models.ForeignKey(User,on_delete=models.CASCADE) create_time=models.DateTimeField(verbose_name='添加时间',auto_now_add=True,blank=True) classMeta: verbose_name='文章' verbose_name_plural='文章管理' def__str__(self): returnself.title
Admin中实现
admin中有2处,一处是Blog和Post列表中按user过滤,另外一处是新增Post时需要按当前user过滤。完整代码如下:
fromdjango.contribimportadmin
fromdjangoimportforms
#Registeryourmodelshere.
fromdjango_summernote.adminimportSummernoteModelAdmin
from.modelsimportTeam,Member,Activity,Score
from.modelsimportBlog,Post
classFilterUserAdmin(admin.ModelAdmin):
'''
按所属用户过滤的base,class
'''
defsave_model(self,request,obj,form,change):
#TODO需要考虑不同用户对同一数据进行修改。
obj.user=request.user
obj.save()
defget_queryset(self,request):
#ForDjango<1.6,overridequerysetinsteadofget_queryset
qs=super(FilterUserAdmin,self).get_queryset(request)
#不能加这个,加了这个会导致superuser更新普通用户的数据。
#ifrequest.user.is_superuser:
#returnqs
returnqs.filter(user=request.user)
defhas_change_permission(self,request,obj=None):
has_class_permission=super(FilterUserAdmin,self).has_change_permission(request,obj)
ifnothas_class_permission:
returnFalse
ifobjisnotNoneandnotrequest.user.is_superuserandrequest.user.id!=obj.user.id:
returnFalse
returnTrue
classBlogConfigAdmin(FilterUserAdmin):
list_display=('id','name','create_time')
exclude=['user']
list_per_page=50
admin.site.register(Blog,BlogConfigAdmin)
classPostConfigAdmin(FilterUserAdmin):
list_display=('id','title','create_time')
exclude=['user']
list_per_page=50
defrender_change_form(self,request,context,add=False,change=False,form_url='',obj=None):
#新增Post时,相关联的Blog需要过滤,关键就在下面这句。
context['adminform'].form.fields['blog'].queryset=Team.objects.filter(user=request.user)
returnsuper(MemberConfigAdmin,self).render_change_form(request,context,add,change,form_url,obj)
admin.site.register(Post,PostConfigAdmin)
说2句
在render_change_form中下断点,直接调试下会发现更多有趣的内容。
以上这篇DjangoAdmin实现外键过滤的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。