请教我恋爱的方法Django的User/Group/Permission管理

django中的权限控制
时间: 12:50:34
&&&& 阅读:63
&&&& 评论:
&&&& 收藏:0
标签:  Django默认提供了权限控制,但只能对使用了其自带的登录认证的用户进行权限控制,说白了就是只能对存储在auth_user表中的用户进行权限控制,但不能对未登录过的用户进行权限控制。但如果通过集成LDAP认证后的用户,其用户也会被缓存到该表中,即变相实现了AD用户也能进行权限控制。
  权限是auth 应用中定义的Permission类型;User与Permission是many-to-many的关系。
&  Django对于每个模型类,自动增加add、change、delete三种权限,以便于权限控制。当然你也可以设定自己的权限。比如有一个名为hv的model,则该model就有了add、change和delete三种权限,可以在admin后台查看,如下图所示:
  Django可以在view层面进行权限控制,即是否允许某个用户访问某个view,使用@permission_required修饰符实现。也可以通过request.user.has_perm() 来对add、change、delete三个动作分别进行权限控制。
  一、对某个view进行权限控制,使用@permission_required()修饰符:
  如果当前用户没有aptest.change_hv权限,则无法访问add页面,登录后依然还会继续跳回登录页面。
from django.contrib.auth.decorators import login_required,permission_required #导入权限控制模块
@permission_required(‘aptest.change_hv‘,login_url="/aptest/loginauth") #第一个参数表示所需要的权限(权限名称通过user.get_all_permissions()方法查看),第二个参数定义需要登录到的url,默认为account/login。
def add(request):
  查看某个用户当前权限列表:
from django.contrib.auth.models import User
user = User.objects.get(username=request.user.username)
print user.get_all_permissions() #查看当前用户所具有的权限列表,返回值是permission name的list
#print user.get_group_permissions()方法列出用户所属group的权限
  返回如下,permission name list:
  二、对add、change、delete三个动作分别进行权限控制(比如用户登录一个页面后,可以查看页面内容,但不能进行增、删、改动作):
  实例:用户登录后,判断是否具有add权限,如果没有则不能新增条目,实现如下:
  编辑view视图,内容如下:
@login_required(login_url="/aptest/loginauth") #不需要再使用permission_required()装饰器
def add(request):
hvs = hv.objects.all()
user = User.objects.get(username=request.user.username)
print ‘add page: ‘,user.get_all_permissions()if request.method == ‘POST‘:
form = hvform(request.POST)
if form.is_valid(): #判断输入数据是否合法
#print form.cleaned_data[‘name‘],form.cleaned_data[‘ip‘]
fc = form.cleaned_data
if request.user.has_perm(‘aptest.add_hv‘): #检查用户是否具有add权限,如果没有则不能保存新增内容
form.save()
err.append(str(request.user.username) + ‘doesnot has add permission.‘)
err.append(form.errors) #输出错误信息
form = hvform()
ls = range(10)
context={‘hour_offset‘:hour_offset,‘ls‘:ls,‘err‘:err,‘hvs‘:hvs}
return render(request,‘aptest/form.html‘,context)
&User和Group对象Permission管理:
user.user_permissions = [permission_list]user.user_permissions.add(permission, permission, ...) #增加权限user.user_permissions.remove(permission, permission, ...) #删除权限user.user_permissions.clear() #清空权限
group permission管理逻辑与user permission管理一致,group中使用permissions字段做权限管理:
group.permissions = [permission_list]group.permissions.add(permission, permission, ...)group.permissions.remove(permission, permission, ...)group.permissions.clear()
检查用户权限用has_perm()方法:user.has_perm(‘app.hv‘)has_perm()方法的参数,即permission的codename,但传递参数时需要加上model 所属app的前缀,格式为&app label&.&permission codename&。
无论permission赋予user还是group,has_perm()方法均适用
user.get_all_permissions()方法列出用户的所有权限,返回值是permission name的listuser.get_group_permissions()方法列出用户所属group的权限,返回值是permission name的list
示例:给当前用户添加hv model的change权限
可以在django_content_type和auth_permission表中查看ContentType、permission中的content_type、codename名称
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
#给当前用户添加hv model的change权限
user = User.objects.get(username=request.user.username)
content_type = ContentType.objects.get_for_model(hv)
permission = Permission.objects.get(content_type=content_type, codename=‘change_hv‘)
request.user.user_permissions.add(permission)
#request.user.user_permissions.remove(permission)
#删除当前用户缓存的权限
if hasattr(user, ‘_perm_cache‘):
delattr(user, ‘_perm_cache‘)
print ,request.user,user.get_all_permissions()
&还可以通过如下方法限制用户是否可以访问view(http://www.jb51.net/article/69893.htm):
例如,下面视图确认用户登录并是否有 polls.can_vote权限:
def vote(request):
&if request.user.is_authenticated() and request.user.has_perm(‘polls.can_vote‘)):
&&return HttpResponse("You can‘t vote in this poll.")
并且Django有一个称为 user_passes_test 的简洁方式。它接受参数然后为你指定的情况生成装饰器。
def user_can_vote(user):
&return user.is_authenticated() and user.has_perm("polls.can_vote")
@user_passes_test(user_can_vote, login_url="/login/")
def vote(request):
user_passes_test 使用一个必需的参数: 一个可调用的方法,当存在 User 对象并当此用户允许查看该页面时返回 True 。 注意 user_passes_test 不会自动检查 User是否认证,你应该自己做这件事。标签:
&&国之画&&&& &&&&chrome插件&&
版权所有 京ICP备号-2
迷上了代码!Django中的用户认证_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Django中的用户认证
&&Django自带了一个用户授权认证系统。它可以处理用户帐户、组、权限和基于cookie的用户会话。本篇文档将解释它是如何工作的。
阅读已结束,下载文档到电脑
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩14页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢用户名:战狐
文章数:43
评论数:11
访问量:24620
注册日期:
阅读量:1297
阅读量:3317
阅读量:580741
阅读量:463826
51CTO推荐博文
环境Python 3.5.1django 1.9.1前言今天用django写web平台,第一时间想到django自带的认证,连session都提供好了,既然有轮子了,我们就不需要自己造了。扩展django user的部分方法:一、重写user,将新的user注册到admin,还要重写认证二、继承user,进行扩展(记得在settings中设置AUTH_USER_MODELAUTH_USER_MODEL&=&"myapp.NewUser")2.1 继承AbstractUser类如果你对django自带的User model感到满意, 又希望增加额外的field的话, 你可以扩展AbstractUser类(本文就是这种方法实现)新的django User类支持email,也可以用email作为用户登陆2.2 继承AbstractBaseUser类AbstractBaseUser中只含有3个field: password, last_login和is_active. 这个就是你自己高度定制自己需要的东西model.py#&class&UserManager(BaseUserManager):
#&&&&&#&def&create_user(self,&email,&username,&mobile,&password=None):
#&&&&&def&create_user(self,&email,&username,&mobile,&password=None,&**kwargs):
#&&&&&&&&&"""通过邮箱,密码,手机号创建用户"""
#&&&&&&&&&if&not&email:
#&&&&&&&&&&&&&raise&ValueError(u'用户必须要有邮箱')
#&&&&&&&&&user&=&self.model(
#&&&&&&&&&&&&&email&=&self.normalize_email(email),
#&&&&&&&&&&&&&username&=&username,
#&&&&&&&&&&&&&mobile&=&mobile,
#&&&&&&&&&)
#&&&&&&&&&user.set_password(password)
#&&&&&&&&&if&kwargs:
#&&&&&&&&&&&&&if&kwargs.get('qq',&None):&user.qq&=&kwargs['qq']&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#qq号
#&&&&&&&&&&&&&if&kwargs.get('is_active',&None):&user.is_active&=&kwargs['is_active']&&&&&&&&&&&&&&&&&&#是否激活
#&&&&&&&&&&&&&if&kwargs.get('wechat',&None):&user.wechat&=&kwargs['wechat']&&&&&&&&&&&&&&&&&&&&&&&&&&&&#微信号
#&&&&&&&&&&&&&if&kwargs.get('refuserid',&None):&user.refuserid&=&kwargs['refuserid']&&&&&&&&&&&&&&&&&&#推荐人ID
#&&&&&&&&&&&&&if&kwargs.get('vevideo',&None):&user.vevideo&=&kwargs['vevideo']&&&&&&&&&&&&&&&&&&&&&&&&&#视频认证
#&&&&&&&&&&&&&if&kwargs.get('identicard',&None):&user.identicard&=&kwargs['identicard']&&&&&&&&&&&&&&&#身份证认证
#&&&&&&&&&&&&&if&kwargs.get('type',&None):&user.type&=&kwargs['type']
#&&&&&&&&&user.save(using=self._db)
#&&&&&&&&&return&user
#&&&&&def&create_superuser(self,email,&username,&password,mobile):
#&&&&&&&&&user&=&self.create_user(email,
#&&&&&&&&&&&&&&&&&&&&&&&&&&&&&username=username,
#&&&&&&&&&&&&&&&&&&&&&&&&&&&&&password=password,
#&&&&&&&&&&&&&&&&&&&&&&&&&&&&&mobile&=&mobile,
#&&&&&&&&&)
#&&&&&&&&&user.is_admin&=&True
#&&&&&&&&&user.save(using=self.db)
#&&&&&&&&&return&user
#&class&User(AbstractBaseUser,&PermissionsMixin):
#&&&&&"""扩展User"""
#&&&&&email&=&models.EmailField(verbose_name='Email',&max_length=255,&unique=True,&db_index=True)
#&&&&&username&=&models.CharField(max_length=50)
#&&&&&qq&=&models.CharField(max_length=16)
#&&&&&mobile&=&models.CharField(max_length=11)
#&&&&&wechat&=&models.CharField(max_length=100)
#&&&&&refuserid&=&models.CharField(max_length=20)
#&&&&&vevideo&=&models.BooleanField(default=False)
#&&&&&identicard&=&models.BooleanField(default=False)
#&&&&&created_at&=&models.DateTimeField(auto_now_add=True)
#&&&&&type&=&models.CharField(u'用户类型',&default='0',&max_length=1)
#&&&&&is_active&=&models.BooleanField(default=True)
#&&&&&is_admin&=&models.BooleanField(default=False)
#&&&&&objects&=&UserManager()
#&&&&&USERNAME_FIELD&=&'email'
#&&&&&REQUIRED_FIELDS&=&['mobile']
#&&&&&def&get_full_name(self):
#&&&&&#&The&user&is&identified&by&their&email&address
#&&&&&&&&&return&self.email
#&&&&&def&get_short_name(self):
#&&&&&#&The&user&is&identified&by&their&email&address
#&&&&&&&&&return&self.email
#&&&&&#On&python&2:&def&__unicode__(self):
#&&&&&def&__str__(self):
#&&&&&&&&&return&self.email
#&&&&&def&has_perm(self,&perm,&obj=None):
#&&&&&&&&&"Does&the&user&have&a&specific&permission?"
#&&&&&&&&&#&Simplest&possible&answer:&Yes,&always
#&&&&&&&&&return&True
#&&&&&def&has_module_perms(self,&app_label):
#&&&&&&&&&"Does&the&user&have&permissions&to&view&the&app&`app_label`?"
#&&&&&&&&&#&Simplest&possible&answer:&Yes,&always
#&&&&&&&&&return&True
#&&&&&@property
#&&&&&def&is_staff(self):
#&&&&&&&&&"Is&the&user&a&member&of&staff?"
#&&&&&&&&&#&Simplest&possible&answer:&All&admins&are&staff
#&&&&&&&&&return&self.is_admin
#admin.py#&class&UserCreationForm(forms.ModelForm):
#&&&&&password1&=&forms.CharField(label='Password',&widget=forms.PasswordInput)
#&&&&&password2&=&forms.CharField(label='Password&confirmation',&widget=forms.PasswordInput)
#&&&&&class&Meta:
#&&&&&&&&&model&=&MyUser
#&&&&&&&&&fields&=&('email',&'mobile')
#&&&&&def&clean_password2(self):
#&&&&&&&&&#&Check&that&the&two&password&entries&match
#&&&&&&&&&password1&=&self.cleaned_data.get("password1")
#&&&&&&&&&password2&=&self.cleaned_data.get("password2")
#&&&&&&&&&if&password1&and&password2&and&password1&!=&password2:
#&&&&&&&&&&&&&raise&forms.ValidationError("Passwords&don't&match")
#&&&&&&&&&return&password2
#&&&&&def&save(self,&commit=True):
#&&&&&&&&&#&Save&the&provided&password&in&hashed&format
#&&&&&&&&&user&=&super(UserCreationForm,&self).save(commit=False)
#&&&&&&&&&user.set_password(self.cleaned_data["password1"])
#&&&&&&&&&if&commit:
#&&&&&&&&&&&&&user.save()
#&&&&&&&&&return&user
#&class&UserChangeForm(forms.ModelForm):
#&&&&&password&=&ReadOnlyPasswordHashField()
#&&&&&class&Meta:
#&&&&&&&&&model&=&MyUser
#&&&&&&&&&fields&=&('email',&'password',&'mobile',&'is_active',&'is_admin')
#&&&&&def&clean_password(self):
#&&&&&&&&&return&self.initial['password']
#&class&UserAdmin(BaseUserAdmin):
#&&&&&form&=&UserChangeForm
#&&&&&add_form&=&UserCreationForm
#&&&&&list_display&=&('email',&'mobile','is_admin')
#&&&&&list_filter&=&('is_admin',)
#&&&&&fieldsets&=&(
#&&&&&&&&&(None,&{'fields':&('email',&'password')}),
#&&&&&&&&&('Personal&info',&{'fields':&('mobile',)}),
#&&&&&&&&&('Permissions',&{'fields':&('is_admin',)}),
#&&&&&add_fieldsets&=&(
#&&&&&&&&&(None,&{
#&&&&&&&&&&&&&'classes':&('wide',),
#&&&&&&&&&&&&&'fields'&:('email','mobile',&'password1',&'password2')}
#&&&&&&&&&),
#&&&&&search_fields&=&('email',)
#&&&&&ordering&=&('email',)
#&&&&&filter_horizontal&=&()
#&admin.site.register(MyUser,UserAdmin)
#&admin.site.unregister(Group)三、profile方式扩展,但是从django1.6开始就放弃这种写法四、网上找的方法,不改源码、不加新表,扩展userfrom&django.db&import&models&&from&django.contrib.auth.models&import&User&&from&django.contrib.auth.admin&import&UserAdmin&&import&datetime&&class&ProfileBase(type):&&
&&&&def&__new__(cls,&name,&bases,&attrs):&&#构造器,(名字,基类,类属性)
&&&&&&&&module&=&attrs.pop('__module__')&&
&&&&&&&&parents&=&[b&for&b&in&bases&if&isinstance(b,&ProfileBase)]&&
&&&&&&&&if&parents:&&
&&&&&&&&&&&&fields&=&[]&&
&&&&&&&&&&&&for&obj_name,&obj&in&attrs.items():&&
&&&&&&&&&&&&&&&&if&isinstance(obj,&models.Field):&fields.append(obj_name)&&
&&&&&&&&&&&&&&&&User.add_to_class(obj_name,&obj)&&&&&&&####最重要的步骤
&&&&&&&&&&&&UserAdmin.fieldsets&=&list(UserAdmin.fieldsets)&&
&&&&&&&&&&&&UserAdmin.fieldsets.append((name,&{'fields':&fields}))&&
&&&&&&&&return&super(ProfileBase,&cls).__new__(cls,&name,&bases,&attrs)&&class&ProfileUser(object):&&
&&&&__metaclass__&=&ProfileBase&&class&ExtraInfo(ProfileUser):&&
&&&&phone_number=&models.CharField(max_length&=&20,&verbose_name=u'电话号码')稍微解释一下这段代码: ProfileBase是自定义的一个元类,继承自types.ClassType,其中ProfileUser为一个基类,其元类为ProfileBase,而ExtraInfo才是我们真正自定义字段的类,之所以把基类ProfileUser和ExtraInfo分开,是为了便于在其他地方引用ProfileUser,进行自定义扩展。简单说来,当解释器看到你在定义一个ProfileUser类的子类,而ProfileUser类的元类是ProfileBase,所以ExtraInfo的元类也是ProfileBase,在定义ProfileUser的子类的时候,它就会执行元类ProfileBase中的new中代码,并且将正在定义的类的(名字,基类,类属性)作为参数传递给new,这里的name就是类名ExtraInfo,attrs中则包含你新加的字段,通过User.add_to_class把新的字段加入到User中,为了能在admin中显示出来,把它加入到UserAdmin.fieldsets中,这样就能在后台编辑这个这个字段,当然,你也可以加入到ist_display,使之在列表中显示。如果你有其他app也想往User Model中加field或方法,都只要通过子类ProfileUser类,然后使用声明语法进行定义即可,所有其他工作都有元类帮你完成。这也是所有django的model的内部工作,你可以用此方法扩展任何model。转载出处:需求注册登录都有现成的代码,主要是自带的User字段只有(email,username,password),所以需要扩展User,来增加自己需要的字段代码如下:model.py#coding:utf8
from&django.db&import&models
from&django.contrib.auth.models&import&AbstractUser
from&django.utils.encoding&import&python_2_unicode_compatible
#&Create&your&models&here.
@python_2_unicode_compatible&&&&&&&&
"""是django内置的兼容python2和python3的unicode语法的一个装饰器
只是针对&__str__&方法而用的,__str__方法是为了后台管理(admin)和django&shell的显示,Meta类也是为后台显示服务的
class&MyUser(AbstractUser):
&&&&qq&=&models.CharField(u'qq号',&max_length=16)
&&&&weChat&=models.CharField(u'微信账号',&max_length=100)
&&&&mobile&=models.CharField(u'手机号',&primary_key=True,&max_length=11)
&&&&identicard&=models.BooleanField(u'身份证认证',&default=False)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#默认是0,未认证,&1:身份证认证,&2:视频认证
&&&&refuserid&=&models.CharField(u'推荐人ID',&max_length=20)
&&&&Level&=&models.CharField(u'用户等级',&default='0',&max_length=2)&&&&&&&&&&&&&&&&&&&&&&&&#默认是0,用户等级0-9
&&&&vevideo&=&models.BooleanField(u'视频认证',&default=False)&&&&&&&&&&&&&&&&&&&&&&#默认是0,未认证。&1:已认证
&&&&Type&=models.CharField(u'用户类型',&default='0',&max_length=1)&&&&&&&&&&&&&&&&&&&&&&&&&&#默认是0,未认证,&1:刷手&2:商家
&&&&def&__str__(self):
&&&&&&&&return&self.usernamesettings.pyAUTH_USER_MODEL&=&'appname.MyUser'
AUTHENTICATION_BACKENDS&=&('django.contrib.auth.backends.ModelBackend',)踩过的坑:1、扩展user表后,要在settings.py 添加AUTH_USER_MODEL&=&'appname.扩展user的class&name'2、认证后台要在settings添加,尤其记得加逗号,否则报错认证后台不加的报错Django-AttributeError&'User'&object&has&no&attribute&'backend'没加逗号的报错ImportError:&a&doesn't&look&like&a&module&pathform.py#coding:utf-8
from&django&import&forms
class&RegisterForm(forms.Form):
&&&&username&=&forms.CharField(label='用户名',max_length=100)
&&&&password&=&forms.CharField(label='密码',widget=forms.PasswordInput())
&&&&password2&=&forms.CharField(label='确认密码',widget=forms.PasswordInput())
&&&&mobile&=&forms.CharField(label='手机号',&max_length=11)
&&&&email&=&forms.EmailField()
&&&&qq&=&forms.CharField(label='QQ号',&max_length=16)
&&&&type&=&forms.ChoiceField(label='注册类型',&choices=(('buyer','买家'),('saler','商家')))
&&&&def&clean(self):
&&&&&&&&if&not&self.is_valid():
&&&&&&&&&&&&raise&forms.ValidationError('所有项都为必填项')
&&&&&&&&elif&self.cleaned_data['password2']&!=&self.cleaned_data['password']:
&&&&&&&&&&&&raise&forms.ValidationError('两次输入密码不一致')
&&&&&&&&else:
&&&&&&&&&&&&cleaned_data&=&super(RegisterForm,&self).clean()
&&&&&&&&return&cleaned_data
class&LoginForm(forms.Form):
&&&&username&=&forms.CharField(label='用户名',widget=forms.TextInput(attrs={"placeholder":&"用户名",&"required":&"required",}),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&max_length=50,&error_messages={"required":&"username不能为空",})
&&&&password&=&forms.CharField(label='密码',widget=forms.PasswordInput(attrs={"placeholder":&"密码",&"required":&"required",}),
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&max_length=20,&error_messages={"required":&"password不能为空",})views.pyfrom&django.shortcuts&import&render,render_to_response
from&.models&import&MyUser
from&django.http&import&HttpResponse,HttpResponseRedirect
from&django.template&import&RequestContext
import&time
from&.myclass&import&form
from&django.template&import&RequestContext
from&django.contrib.auth&import&authenticate,login,logout
def&register(request):
&&&&error&=&[]
&&&&#&if&request.method&==&'GET':
&&&&#&&&&&return&render_to_response('register.html',{'uf':uf})
&&&&if&request.method&==&'POST':
&&&&&&&&uf&=&form.RegisterForm(request.POST)
&&&&&&&&if&uf.is_valid():
&&&&&&&&&&&&username&=&uf.cleaned_data['username']
&&&&&&&&&&&&password&=&uf.cleaned_data['password']
&&&&&&&&&&&&password2&=&uf.cleaned_data['password2']
&&&&&&&&&&&&qq&=&uf.cleaned_data['qq']
&&&&&&&&&&&&email&=&uf.cleaned_data['email']
&&&&&&&&&&&&mobile&=&uf.cleaned_data['mobile']
&&&&&&&&&&&&type&=&uf.cleaned_data['type']
&&&&&&&&&&&&if&not&MyUser.objects.all().filter(username=username):
&&&&&&&&&&&&&&&&user&=&MyUser()
&&&&&&&&&&&&&&&&user.username&=&username
&&&&&&&&&&&&&&&&user.set_password(password)
&&&&&&&&&&&&&&&&user.qq&=&qq
&&&&&&&&&&&&&&&&user.email&=&email
&&&&&&&&&&&&&&&&user.mobile&=&mobile
&&&&&&&&&&&&&&&&user.type&=&type
&&&&&&&&&&&&&&&&user.save()
&&&&&&&&&&&&&&&&return&render_to_response('member.html',&{'username':&username})
&&&&&&&&uf&=&form.RegisterForm()
&&&&return&render_to_response('register.html',{'uf':uf,'error':error})
def&do_login(request):
&&&&if&request.method&=='POST':
&&&&&&&&lf&=&form.LoginForm(request.POST)
&&&&&&&&if&lf.is_valid():
&&&&&&&&&&&&username&=&lf.cleaned_data['username']
&&&&&&&&&&&&password&=&lf.cleaned_data['password']
&&&&&&&&&&&&user&=&authenticate(username=username,&password=password)&&&&&&&&&&&&&&&#django自带auth验证用户名密码
&&&&&&&&&&&&if&user&is&not&None:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#判断用户是否存在
&&&&&&&&&&&&&&&&if&user.is_active:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#判断用户是否激活
&&&&&&&&&&&&&&&&&&&&login(request,user)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#用户信息验证成功后把登陆信息写入session
&&&&&&&&&&&&&&&&&&&&return&render_to_response("member.html",&{'username':username})
&&&&&&&&&&&&&&&&else:
&&&&&&&&&&&&&&&&&&&&return&render_to_response('disable.html',{'username':username})
&&&&&&&&&&&&else:
&&&&&&&&&&&&&&&&return&HttpResponse("无效的用户名或者密码!!!")
&&&&&&&&lf&=&form.LoginForm()
&&&&return&render_to_response('index.html',{'lf':lf})
def&do_logout(request):
&&&&logout(request)
&&&&return&HttpResponseRedirect('/')踩过的坑:1、登陆的时候用自带的认证模块总是报noneuser&=&authenticate(username=username,&password=password)查看源码发现是check_password的方法是用hash进行校验,之前注册的password写法是user.password=password这种写法是明文入库,需要更改密码的入库写法user.set_password(password)本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:┆阅读(0)┆评论(0)Django的管理站点 — Django 1.8.2 中文文档
Django 1.8.2 文档
Django Admin 站点
Django 最强大的部分之一是自动生成的Admin 界面。它读取模型中的元数据来提供一个强大的、生产环境就绪的界面,使内容提供者能立即用它向站点中添加内容。在本文中,我们将讨论如何激活,使用和定制Django的管理界面。
通过使用 创建的默认项目模版中,Admin 已启用。
下面的一些要求作为参考:
添加 'django.contrib.admin'到 设置中.
admin有四个依赖 - , ,
和. 如果这些应用没有在
列表中, 那你要把它们添加到该列表中.
把django.contrib.messages.context_processors.messages 添加到 中DjangoTemplates后台的'context_processors'选项中,同样把 和
添加到 . (这些默认都是激活的,所以如果你手工操作过的话就需要按照以上方法进行设置..)
确定应用中的哪些模型应该在Admin 界面中可以编辑。
给每个模型创建一个ModelAdmin 类,封装模型自定义的Admin 功能和选项。
实例化AdminSite 并且告诉它你的每一个模块和ModelAdmin 类.
将AdminSite 实例绑定到URLconf。
做了这些步骤之后, 你将能够通过你已经绑定的URL来访问Django管理站点(默认是/admin/).
如何在产品中使用admin相关的静态文件(图片,JavaScript和CSS)的办法, 请参阅
还有什么问题? 试试 &.
ModelAdmin objects
class ModelAdmin
ModelAdmin 类是模型在Admin 界面中的表示形式。通常,将它们在你的应用中的名为admin.py的文件里。让我们来看一个关于ModelAdmin类非常简单的例子:
from django.contrib import admin
from myproject.myapp.models import Author
class AuthorAdmin(admin.ModelAdmin):
admin.site.register(Author, AuthorAdmin)
你真的需要一个ModelAdmin 对象吗?
在上面的例子中,ModelAdmin并没有定义任何自定义的值。因此, 系统将使用默认的Admin 界面。如果对于默认的Admin 界面足够满意,那你根本不需要自己定义ModelAdmin 对象, 你可以直接注册模型类而无需提供ModelAdmin 的描述。那么上面的例子可以简化成:
from django.contrib import admin
from myproject.myapp.models import Author
admin.site.register(Author)
注册装饰器
register(*models[, site=django.admin.sites.site])
New in Django 1.7.
还可以用一个装饰来注册您的ModelAdmin类(这里有关装饰器的详细信息,请参考python中的相关说明):
from django.contrib import admin
from .models import Author
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
如果不使用默认的AdminSite,可以提供一个或多个模块类来注册ModelAdmin 并且一个可选择的关键参数 site(这里使用装饰器来注册需要注册的类和模块的,请特别留意紧跟装饰器后面关于ModelAdmin的声明,前面是Author,后面是PersonAdmin,我的理解是后一种情况 下注册的类都可以用PersonAdmin来作为接口):
from django.contrib import admin
from .models import Author, Reader, Editor
from myproject.admin_site import custom_admin_site
@admin.register(Author, Reader, Editor, site=custom_admin_site)
class PersonAdmin(admin.ModelAdmin):
发现admin 文件
当你将 'django.contrib.admin'加入到 设置中, Django就会自动搜索每个应用的admin模块并将其导入。
class apps.AdminConfig
New in Django 1.7.
这是 admin的默认 类. 它在 Django 启动时调用 .
class apps.SimpleAdminConfig
New in Django 1.7.
这个类和 的作用一样,除了它不调用.
autodiscover()
这个函数尝试导入每个安装的应用中的admin 模块。这些模块用于注册模型到Admin 中。
Changed in Django 1.7: 以前的Django版本推荐直接在URLconf中调用这个函数. Django 1.7不再需要这样.
能够自动的运行 auto-discovery.
如果你使用自定义的AdminSite, 一般是导入所有的ModelAdmin 子类到你的代码中并将其注册到自定义的AdminSite中. 在这种情况下, 为了禁用auto-discovery,在你的 设置中,应该用 'django.contrib.admin.apps.SimpleAdminConfig'代替'django.contrib.admin' 。
Changed in Django 1.7: 在以前的版本中,admin需要被指示寻找 admin.py 文件通过 . 在Django 1.7, auto-discovery默认可用的,必须明确的使它失效当不需要时.
ModelAdmin options
ModelAdmin 非常灵活。 它有几个选项来处理自定义界面。 所有的选项都在 ModelAdmin 子类中定义:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
date_hierarchy = 'pub_date'
ModelAdmin.actions
在修改列表页面可用的操作列表。详细信息请查看 .
ModelAdmin.actions_on_top
ModelAdmin.actions_on_bottom
控制actions bar 出现在页面的位置。默认情况下,admin的更改列表将操作显示在页面的顶部(actions_on_top = Tactions_on_bottom=False)。
ModelAdmin.actions_selection_counter
控制选择计数器是否紧挨着下拉菜单action默认的admin 更改列表将会显示它 (actions_selection_counter = True).
把 date_hierarchy 设置为在你的model 中的DateField或DateTimeField的字段名,然后更改列表将包含一个依据这个字段基于日期的下拉导航。
date_hierarchy = 'pub_date'
这将根据现有数据智能地填充自己,例如,如果所有的数据都是一个月里的, 它将只显示天级别的数据.
date_hierarchy 在内部使用. 当时区支持启用时,请参考它的一些文档说明。().
ModelAdmin.exclude
如果设置了这个属性,它表示应该从表单中去掉的字段列表。
例如,让我们来考虑下面的模型:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
title = models.CharField(max_length=3)
birth_date = models.DateField(blank=True, null=True)
如果你希望Author 模型的表单只包含name 和title 字段, 你应该显式说明fields 或exclude,像这样:
from django.contrib import admin
class AuthorAdmin(admin.ModelAdmin):
fields = ('name', 'title')
class AuthorAdmin(admin.ModelAdmin):
exclude = ('birth_date',)
由于Author 模型只有三个字段,name、title和 birth_date,上述声明产生的表单将包含完全相同的字段。
ModelAdmin.fields
如果需要实现字段的布局中的“添加” 和 “更改”,“更改”网页形式的简单改变像只显示可用字段的一个子集,你可以使用&fields选项修改他们的顺序或者行内分组(需要复杂布局的请参阅 选项将在下一段讲到). 例如,可以定义一个简单的管理表单的版本使用 模块像下面这样:
class FlatPageAdmin(admin.ModelAdmin):
fields = ('url', 'title', 'content')
在上面的例子中, 只有字段url, title 和 content 将会在表单中顺序的显示. fields能够包含在
中定义的作为只读显示的值
不同于 ,fields 选项 只包含model中的字段名或者通过指定的表单。只有当它们列在中,它才能包含callables
要在同一行显示多个字段, 就把那些字段打包在一个元组里。例子中, url 和 title 字段 会显示在同一行, content 字段将会显示在他们的下一行里:
class FlatPageAdmin(admin.ModelAdmin):
fields = (('url', 'title'), 'content')
此字段选项不应与选项中的 fields 字典键混淆,如下一节所述。
如果fields和 选项都不存在, Django将会默认显示每一个不是 AutoField 并且 editable=True的字段, 在单一的字段集,和在模块中定义的字段有相同的顺序
ModelAdmin.fieldsets
设置fieldsets 控制管理“添加”和 “更改” 页面的布局.
fieldsets 是一个以二元元组为元素的列表, 每一个二元元组代表一个在管理表单的 &fieldset&( &fieldset& 是表单的一部分.)
二元元组的格式是 (name, field_options), 其中 name 是一个字符串相当于 fieldset的标题, field_options 是一个关于 fieldset的字典信息,一个字段列表包含在里面。
一个完整的例子, 来自于 模块:
from django.contrib import admin
class FlatPageAdmin(admin.ModelAdmin):
fieldsets = (
'fields': ('url', 'title', 'content', 'sites')
('Advanced options', {
'classes': ('collapse',),
'fields': ('enable_comments', 'registration_required', 'template_name')
在管理界面的结果看起来像这样:
如果fields和 选项都不存在, Django将会默认显示每一个不是 AutoField 并且 editable=True的字段, 在单一的字段集,和在模块中定义的字段有相同的顺序。
field_options 字典有以下关键字:
字段名元组将显示在该fieldset. 此键必选.
'fields': ('first_name', 'last_name', 'address', 'city', 'state'),
就像 选项, 显示多个字段在同一行, 包裹这些字段在一个元组. 在这个例子中, &first_name 和 last_name 字段将显示在同一行:
'fields': (('first_name', 'last_name'), 'address', 'city', 'state'),
fields 能够包含定义在 中显示的值作为只读.
如果添加可调用的名称到fields中,相同的规则适用于选项: 可调用的必须在 列表中.
一个列表包含额外的CSS classes 应用到 fieldset.
'classes': ('wide', 'extrapretty'),
通过默认的管理站点样式表定义的两个有用的classes 是 collapse 和 wide. Fieldsets 使用 collapse 样式将会在初始化时展开并且替换掉一个 “click to expand” 链接. Fieldsets 使用 wide 样式将会有额外的水平空格.
description
一个可选择额外文本的字符串显示在每一个fieldset的顶部,在fieldset头部的底下. 字符串没有被 渲染由于它的布局.
记住这个值不是 HTML-escaped 当它显示在管理接口中时. 如果你愿意,这允许你包括HTML。另外,你可以使用纯文本和 django.utils.html.escape() 避免任何HTML特殊字符。
ModelAdmin.filter_horizontal
会在管理站点上显示一个&select multiple&.(多选框).但是,当选择多个时多选框非常难用. 添加一个 到该列表将使用一个漂亮的低调的JavaScript中的“过滤器”界面,允许搜索选项。选和不选选项框并排出现。参考 使用垂直界面。
ModelAdmin.filter_vertical
与相同,但使用过滤器界面的垂直显示,其中出现在所选选项框上方的未选定选项框。
ModelAdmin.form
默认情况下, 会根据你的模型动态创建一个ModelForm。 它被用来创建呈现在添加/更改页面上的表单。你可以很容易的提供自己的ModelForm 来重写表单默认的添加/修改行为。或者,你可以使用 方法自定义默认的表单,而不用指定一个全新的表单。
例子见部分。
如果你在中定义 Meta.model属性,那么也必须定义 Meta.fields或Meta.exclude属性。然而,当admin本身定义了fields,则Meta.fields属性将被忽略。
如果ModelForm 仅仅只是给Admin 使用,那么最简单的解决方法就是忽略Meta.model 属性,因为ModelAdmin 将自动选择应该使用的模型。或者,你也可以设置在 Meta 类中的&fields = [] &来满足&ModelForm 的合法性。
如果 ModelForm 和 ModelAdmin 同时定义了一个&exclude 选项,那么 ModelAdmin 具有更高的优先级:
from django import forms
from django.contrib import admin
from myapp.models import Person
class PersonForm(forms.ModelForm):
class Meta:
model = Person
exclude = ['name']
class PersonAdmin(admin.ModelAdmin):
exclude = ['age']
form = PersonForm
在上例中, “age” 字段将被排除而&“name” 字段将被包含在最终产生的表单中。
ModelAdmin.formfield_overrides
这个属性通过一种临时的方案来覆盖现有的模型中 (字段)类型在admin site中的显示类型。formfield_overrides 在类初始化的时候通过一个字典类型的变量来对应模型字段类型与实际重载类型的关系。
因为概念有点抽象,所以让我们来举一个具体的例子。formfield_overrides 常被用于让一个已有的字段显示为自定义控件。所以,试想一下我们写了一个 RichTextEditorWidget(富文本控件) 然后我们想用它来代替&textarea&(文本域控件)用于输入大段文字。下面就是我们如何做到这样的替换。
from django.db import models
from django.contrib import admin
# Import our custom widget and our model from where they're defined
from myapp.widgets import RichTextEditorWidget
from myapp.models import MyModel
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.TextField: {'widget': RichTextEditorWidget},
注意字典的键是一个实际的字段类型,而不是一个具体的字符。 &字典的值是另外一个字典结构的数据;这个参数会传递到表单字段 __init__()(初始化方法) 中。有关详细信息,请参见。
如果你想用一个关系字段的自定义界面 (即
或者 ), 确保你没有在raw_id_fields or radio_fields中included那个字段名。
formfield_overrides不会让您更改raw_id_fields或radio_fields设置的关系字段上的窗口小部件。这是因为raw_id_fields和radio_fields暗示自己的自定义小部件。
ModelAdmin.inlines
请参见下面的对象以及。
ModelAdmin.list_display
使用list_display 去控制哪些字段会显示在Admin 的修改列表页面中。
list_display = ('first_name', 'last_name')
如果你没有设置list_display,Admin 站点将只显示一列表示每个对象的__str__() (Python 2 中是__unicode__())。
在list_display中,你有4种赋值方式可以使用:
模型的字段。
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name')
一个接受对象实例作为参数的可调用对象。例子:
def upper_case_name(obj):
return ("%s %s" % (obj.first_name, obj.last_name)).upper()
upper_case_name.short_description = 'Name'
class PersonAdmin(admin.ModelAdmin):
list_display = (upper_case_name,)
一个表示ModelAdmin 中某个属性的字符串。行为与可调用对象相同。 例如︰
class PersonAdmin(admin.ModelAdmin):
list_display = ('upper_case_name',)
def upper_case_name(self, obj):
return ("%s %s" % (obj.first_name, obj.last_name)).upper()
upper_case_name.short_description = 'Name'
表示模型中某个属性的字符串。它的行为与可调用对象几乎相同,但这时的self 是模型实例。这里是一个完整的模型示例︰
from django.db import models
from django.contrib import admin
class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()
def decade_born_in(self):
return self.birthday.strftime('%Y')[:3] + "0's"
decade_born_in.short_description = 'Birth decade'
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'decade_born_in')
关于list_display 要注意的几个特殊情况︰
如果字段是一个ForeignKey,Django 将展示相关对象的__str__() (Python 2 上是__unicode__())。
不支持ManyToManyField 字段, 因为这将意味着对表中的每一行执行单独的SQL 语句。如果尽管如此你仍然想要这样做,请给你的模型一个自定义的方法,并将该方法名称添加到 list_display。(list_display 的更多自定义方法请参见下文)。
如果该字段为BooleanField 或NullBooleanField,Django 会显示漂亮的"on"或"off"图标而不是True 或False。
如果给出的字符串是模型、ModelAdmin 的一个方法或可调用对象,Django 将默认转义HTML输出。如果你不希望转义方法的输出,可以给方法一个allow_tags 属性,其值为True。然而,为了避免XSS 漏洞,应该使用 转义用户提供的输入。
下面是一个完整的示例模型︰
from django.db import models
from django.contrib import admin
from django.utils.html import format_html
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
def colored_name(self):
return format_html('&span style="color: #{};"&{} {}&/span&',
self.color_code,
self.first_name,
self.last_name)
colored_name.allow_tags = True
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'colored_name')
如果给出的字符串是模型、ModelAdmin 的一个方法或一个返回 True 或False 的可调用的方法,然后赋值给方法的boolean 属性一个True值, Django 将显示漂亮的"on"或"off"图标,。
下面是一个完整的示例模型︰
from django.db import models
from django.contrib import admin
class Person(models.Model):
first_name = models.CharField(max_length=50)
birthday = models.DateField()
def born_in_fifties(self):
return self.birthday.strftime('%Y')[:3] == '195'
born_in_fifties.boolean = True
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'born_in_fifties')
__str__()(Python 2 上是__unicode__())方法在list_display 中同样合法,就和任何其他模型方法一样,所以下面这样写完全OK︰
list_display = ('__str__', 'some_other_field')
通常情况下,list_display 的元素如果不是实际的数据库字段不能用于排序(因为 Django 所有的排序都在数据库级别)。
然而,如果list_display 元素表示数据库的一个特定字段,你可以通过设置 元素的admin_order_field 属性表示这一事实。
from django.db import models
from django.contrib import admin
from django.utils.html import format_html
class Person(models.Model):
first_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6)
def colored_first_name(self):
return format_html('&span style="color: #{};"&{}&/span&',
self.color_code,
self.first_name)
colored_first_name.allow_tags = True
colored_first_name.admin_order_field = 'first_name'
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'colored_first_name')
上面的示例告诉Django 在Admin 中按照按colored_first_name 排序时依据first_name 字段。
New in Django 1.7.
要表示按照admin_order_field 降序排序,你可以在该字段名称前面使用一个连字符前缀。使用上面的示例,这会看起来像︰
colored_first_name.admin_order_field = '-first_name'
list_display 的元素也可以是属性。不过请注意,由于方式属性在Python 中的工作方式,在属性上设置short_description 只能使用 property() 函数,不 能使用@property 装饰器。
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def my_property(self):
return self.first_name + ' ' + self.last_name
my_property.short_description = "Full name of the person"
full_name = property(my_property)
class PersonAdmin(admin.ModelAdmin):
list_display = ('full_name',)
list_display 中的字段名称还将作为HTML 输出的CSS 类, 形式为每个&th& 元素上具有column-&field_name&。例如这可以用于在CSS 文件中设置列的宽度。
Django 会尝试以下面的顺序解释list_display 的每个元素︰
模型的字段。
可调用对象。
表示ModelAdmin 属性的字符串。
表示模型属性的字符串。
例如,如果first_name 既是模型的一个字段又是ModelAdmin 的一个属性,使用的将是模型字段。
ModelAdmin.list_display_links
使用list_display_links可以控制中的字段是否应该链接到对象的“更改”页面。
默认情况下,更改列表页将链接第一列 -
list_display中指定的第一个字段 - 到每个项目的更改页面。但是list_display_links可让您更改此设置:
将其设置为None,根本不会获得任何链接。
将其设置为要将其列转换为链接的字段列表或元组(格式与list_display相同)。
您可以指定一个或多个字段。只要这些字段出现在list_display中,Django不会关心多少(或多少)字段被链接。唯一的要求是,如果要以这种方式使用list_display_links,则必须定义list_display。
在此示例中,first_name和last_name字段将链接到更改列表页面上:
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'birthday')
list_display_links = ('first_name', 'last_name')
在此示例中,更改列表页面网格将没有链接:
class AuditEntryAdmin(admin.ModelAdmin):
list_display = ('timestamp', 'message')
list_display_links = None
Changed in Django 1.7: None作为有效的list_display_links值添加。
ModelAdmin.list_editable
将list_editable设置为模型上的字段名称列表,这将允许在更改列表页面上进行编辑。也就是说,list_editable中列出的字段将在更改列表页面上显示为表单小部件,允许用户一次编辑和保存多行。
list_editable以特定方式与其他几个选项进行交互;您应该注意以下规则:
list_editable中的任何字段也必须位于list_display中。您无法编辑未显示的字段!
同一字段不能在list_editable和list_display_links中列出 - 字段不能同时是表单和链接。
如果这些规则中的任一个损坏,您将收到验证错误。
ModelAdmin.list_filter
list_filter 设置激活激活Admin 修改列表页面右侧栏中的过滤器,如下面的屏幕快照所示︰
list_filter 应该是一个列表或元组,其每个元素应该是下面类型中的一种:
字段名称,其指定的字段应该是BooleanField、CharField、DateField、DateTimeField、IntegerField、ForeignKey 或ManyToManyField,例如︰
class PersonAdmin(admin.ModelAdmin):
list_filter = ('is_staff', 'company')
list_filter 中的字段名称也可以使用__ 查找跨关联关系,例如︰
class PersonAdmin(admin.UserAdmin):
list_filter = ('company__name',)
一个继承自django.contrib.admin.SimpleListFilter 的类,你需要给它提供title 和 parameter_name 属性来重写lookups 和queryset 方法,例如︰
from datetime import date
from django.contrib import admin
from django.utils.translation import ugettext_lazy as _
class DecadeBornListFilter(admin.SimpleListFilter):
# Human-readable title which will be displayed in the
# right admin sidebar just above the filter options.
title = _('decade born')
# Parameter for the filter that will be used in the URL query.
parameter_name = 'decade'
def lookups(self, request, model_admin):
Returns a list of tuples. The first element in each
tuple is the coded value for the option that will
appear in the URL query. The second element is the
human-readable name for the option that will appear
in the right sidebar.
('80s', _('in the eighties')),
('90s', _('in the nineties')),
def queryset(self, request, queryset):
Returns the filtered queryset based on the value
provided in the query string and retrievable via
`self.value()`.
# Compare the requested value (either '80s' or '90s')
# to decide how to filter the queryset.
if self.value() == '80s':
return queryset.filter(birthday__gte=date(1980, 1, 1),
birthday__lte=date(1989, 12, 31))
if self.value() == '90s':
return queryset.filter(birthday__gte=date(1990, 1, 1),
birthday__lte=date(1999, 12, 31))
class PersonAdmin(admin.ModelAdmin):
list_filter = (DecadeBornListFilter,)
作为一种方便,HttpRequest 对象将传递给lookups 和queryset 方法,例如︰
class AuthDecadeBornListFilter(DecadeBornListFilter):
def lookups(self, request, model_admin):
if request.user.is_superuser:
return super(AuthDecadeBornListFilter,
self).lookups(request, model_admin)
def queryset(self, request, queryset):
if request.user.is_superuser:
return super(AuthDecadeBornListFilter,
self).queryset(request, queryset)
也作为一种方便,ModelAdmin 对象将传递给lookups 方法,例如如果你想要基于现有的数据查找︰
class AdvancedDecadeBornListFilter(DecadeBornListFilter):
def lookups(self, request, model_admin):
Only show the lookups if there actually is
anyone born in the corresponding decades.
qs = model_admin.get_queryset(request)
if qs.filter(birthday__gte=date(1980, 1, 1),
birthday__lte=date(1989, 12, 31)).exists():
yield ('80s', _('in the eighties'))
if qs.filter(birthday__gte=date(1990, 1, 1),
birthday__lte=date(1999, 12, 31)).exists():
yield ('90s', _('in the nineties'))
一个元组,第一个元素是字段名称,第二个元素是从继承自django.contrib.admin.FieldListFilter 的一个类,例如︰
class PersonAdmin(admin.ModelAdmin):
list_filter = (
('is_staff', admin.BooleanFieldListFilter),
New in Django 1.8.
你可以使用RelatedOnlyFieldListFilter 限制与该对象关联的模型的选项:
class BookAdmin(admin.ModelAdmin):
list_filter = (
('author', admin.RelatedOnlyFieldListFilter),
假设author 是User 模型的一个ForeignKey,这将限制list_filter 的选项为编写过书籍的用户,而不是所有用户。
FieldListFilter API 被视为内部的,可能会改变。
也可以指定自定义模板用于渲染列表筛选器︰
class FilterWithCustomTemplate(admin.SimpleListFilter):
template = "custom_template.html"
具体的例子请参见Django 提供的默认模板(admin/filter.html)。
ModelAdmin.list_max_show_all
设置list_max_show_all以控制在“显示所有”管理更改列表页面上可以显示的项目数。只有当总结果计数小于或等于此设置时,管理员才会在更改列表上显示“显示全部”链接。默认情况下,设置为200。
ModelAdmin.list_per_page
list_per_page 设置控制Admin 修改列表页面每页中显示多少项。默认设置为100。
ModelAdmin.list_select_related
设置list_select_related以告诉Django在检索管理更改列表页面上的对象列表时使用。这可以节省大量的数据库查询。
该值应该是布尔值,列表或元组。默认值为False。
当值为True时,将始终调用select_related()。When value is set to False, Django will look at list_display and call select_related() if any ForeignKey is present.
如果您需要更细粒度的控制,请使用元组(或列表)作为list_select_related的值。空元组将阻止Django调用select_related。任何其他元组将直接传递到select_related作为参数。例如:
class ArticleAdmin(admin.ModelAdmin):
list_select_related = ('author', 'category')
将会调用select_related('author', 'category').
ModelAdmin.ordering
设置ordering以指定如何在Django管理视图中对对象列表进行排序。这应该是与模型的参数格式相同的列表或元组。
如果没有提供,Django管理员将使用模型的默认排序。
如果您需要指定动态顺序(例如,根据用户或语言),您可以实施方法。
ModelAdmin.paginator
paginator类用于分页。默认情况下,使用。如果自定义paginator类没有与相同的构造函数接口,则还需要为 。
ModelAdmin.prepopulated_fields
将prepopulated_fields设置为将字段名称映射到其应预先填充的字段的字典:
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
设置时,给定字段将使用一些JavaScript来从分配的字段填充。此功能的主要用途是自动从一个或多个其他字段生成SlugField字段的值。生成的值是通过连接源字段的值,然后将该结果转换为有效的字节(例如用空格替换破折号)来生成的。
prepopulated_fields不接受DateTimeField,ForeignKey或ManyToManyField字段。
ModelAdmin.preserve_filters
管理员现在在创建,编辑或删除对象后保留列表视图中的过滤器。您可以将此属性设置为False,以恢复之前清除过滤器的行为。
ModelAdmin.radio_fields
By default, Django’s admin uses a select-box interface (&select&) for fields that are ForeignKey or have choices set. 如果radio_fields中存在字段,Django将使用单选按钮接口。假设group是Person模型上的ForeignKey
class PersonAdmin(admin.ModelAdmin):
radio_fields = {"group": admin.VERTICAL}
您可以选择使用django.contrib.admin模块中的HORIZONTAL或VERTICAL。
除非是ForeignKey或设置了choices,否则不要在radio_fields中包含字段。
ModelAdmin.raw_id_fields
默认情况下,Django 的Admin 对ForeignKey 字段使用选择框表示 (&select&) 。有时候你不想在下拉菜单中显示所有相关实例产生的开销。
raw_id_fields 是一个字段列表,你希望将ForeignKey 或ManyToManyField 转换成Input Widget:
class ArticleAdmin(admin.ModelAdmin):
raw_id_fields = ("newspaper",)
如果该字段是一个ForeignKey,raw_id_fields Input Widget 应该包含一个外键,或者如果字段是一个ManyToManyField 则应该是一个逗号分隔的值的列表。 raw_id_fields Widget 在字段旁边显示一个放大镜按钮,允许用户搜索并选择一个值︰
ModelAdmin.readonly_fields
默认情况下,管理员将所有字段显示为可编辑。此选项中的任何字段(应为list或tuple)将按原样显示其数据,且不可编辑;它们也会从用于创建和编辑的中排除。请注意,指定或时,只读字段必须显示才能显示(否则将被忽略)。
如果在未通过或定义显式排序的情况下使用readonly_fields,则它们将在所有可编辑字段之后添加。
只读字段不仅可以显示模型字段中的数据,还可以显示模型方法的输出或ModelAdmin类本身的方法。这与的行为非常相似。这提供了一种使用管理界面提供对正在编辑的对象的状态的反馈的简单方法,例如:
from django.contrib import admin
from django.utils.html import format_html_join
from django.utils.safestring import mark_safe
class PersonAdmin(admin.ModelAdmin):
readonly_fields = ('address_report',)
def address_report(self, instance):
# assuming get_full_address() returns a list of strings
# for each line of the address and you want to separate each
# line by a linebreak
return format_html_join(
mark_safe('&br/&'),
((line,) for line in instance.get_full_address()),
) or "&span class='errors'&I can't determine this address.&/span&"
# short_description functions like a model field's verbose_name
address_report.short_description = "Address"
# in this example, we have used HTML tags in the output
address_report.allow_tags = True
ModelAdmin.save_as
save_as 设置启用Admin 更改表单上的“save as”功能。
通常情况下,对象有三个保存选项:"保存"、"保存并继续编辑"和"保存并添加另一个"。如果save_as 为True,"保存并添加另一个"将由"另存为"按钮取代。
"另存为"表示对象将被保存为一个新的对象 (带有一个新的 ID),而不是旧的对象。
默认情况下,save_as 设置为False。
ModelAdmin.save_on_top
设置save_on_top可在表单顶部添加保存按钮。
通常,保存按钮仅出现在表单的底部。如果您设置save_on_top,则按钮将同时显示在顶部和底部。
默认情况下,save_on_top设置为False。
search_fields 设置启用Admin 更改列表页面上的搜索框。此属性应设置为每当有人在该文本框中提交搜索查询将搜索的字段名称的列表。
这些字段应该是某种文本字段,如CharField 或TextField。你还可以通过查询API 的"跟随"符号进行ForeignKey 或ManyToManyField 上的关联查找:
search_fields = ['foreign_key__related_fieldname']
例如,如果你有一个具有作者的博客,下面的定义将启用通过作者的电子邮件地址搜索博客条目︰
search_fields = ['user__email']
如果有人在Admin 搜索框中进行搜索,Django 拆分搜索查询为单词并返回包含每个单词的所有对象,不区分大小写,其中每个单词必须在至少一个search_fields。例如,如果search_fields 设置为['first_name', 'last_name'],用户搜索john lennon,Django 的行为将相当于下面的这个WHERE SQL 子句︰
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
若要更快和/或更严格的搜索,请在字典名称前面加上前缀︰
匹配字段的开始。例如,如果search_fields 设置为['^first_name', '^last_name'],用户搜索john lennon 时,Django 的行为将等同于下面这个WHERE SQL 字句:
WHERE (first_name ILIKE 'john%' OR last_name ILIKE 'john%')
AND (first_name ILIKE 'lennon%' OR last_name ILIKE 'lennon%')
此查询比正常'%john%' 查询效率高,因为数据库只需要检查某一列数据的开始,而不用寻找整列数据。另外,如果列上有索引,有些数据库可能能够对于此查询使用索引,即使它是like 查询。
精确匹配,不区分大小写。例如,如果search_fields 设置为['=first_name', '=last_name'],用户搜索john lennon 时,Django 的行为将等同于下面这个WHERE SQL 字句:
WHERE (first_name ILIKE 'john' OR last_name ILIKE 'john')
AND (first_name ILIKE 'lennon' OR last_name ILIKE 'lennon')
注意,该查询输入通过空格分隔,所以根据这个示例,目前不能够搜索first_name 精确匹配'john winston'(包含空格)的所有记录。
Performs a full-text match. This is like the default search method but
uses an index. Currently this is only available for MySQL.
如果你需要自定义搜索,你可以使用 来提供附件的或另外一种搜索行为。
ModelAdmin.show_full_result_count
New in Django 1.8.
设置show_full_result_count以控制是否应在过滤的管理页面上显示对象的完整计数(例如99 结果 103 total))。如果此选项设置为False,则像99 结果 (显示 )。
默认情况下,show_full_result_count=True生成一个查询,对表执行完全计数,如果表包含大量行,这可能很昂贵。
ModelAdmin.view_on_site
New in Django 1.7.
设置view_on_site以控制是否显示“在网站上查看”链接。此链接将带您到一个URL,您可以在其中显示已保存的对象。
此值可以是布尔标志或可调用的。如果True(默认值),对象的方法将用于生成网址。
如果您的模型有方法,但您不想显示“在网站上查看”按钮,则只需将view_on_site设置为False:
from django.contrib import admin
class PersonAdmin(admin.ModelAdmin):
view_on_site = False
如果它是可调用的,它接受模型实例作为参数。例如:
from django.contrib import admin
from django.core.urlresolvers import reverse
class PersonAdmin(admin.ModelAdmin):
def view_on_site(self, obj):
return '' + reverse('person-detail',
kwargs={'slug': obj.slug})
自定义模板的选项
一节描述如何重写或扩展默认Admin 模板。使用以下选项来重写 视图使用的默认模板︰
ModelAdmin.add_form_template
使用的自定义模板的路径。
ModelAdmin.change_form_template
使用的自定义模板的路径。
ModelAdmin.change_list_template
使用的自定义模板的路径。
ModelAdmin.delete_confirmation_template
使用的自定义模板,用于删除一个或多个对象时显示一个确认页。
ModelAdmin.delete_selected_confirmation_template
delete_selected() 使用的自定义模板,用于删除一个或多个对象时显示一个确认页。参见。
ModelAdmin.object_history_template
使用的自定义模板的路径。
ModelAdmin methods
must save/delete the object, they are not for veto purposes, rather they allow you to perform extra operations.
ModelAdmin.save_model(request, obj, form, change)
save_model方法被赋予HttpRequest,模型实例,ModelForm实例和布尔值,基于它是添加还是更改对象。在这里您可以执行任何预保存或后保存操作。
例如,在保存之前将request.user附加到对象:
from django.contrib import admin
class ArticleAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = request.user
obj.save()
ModelAdmin.delete_model(request, obj)
delete_model方法给出了HttpRequest和模型实例。使用此方法执行预删除或后删除操作。
ModelAdmin.save_formset(request, form, formset, change)
save_formset方法是给予HttpRequest,父ModelForm实例和基于是否添加或更改父对象的布尔值。
例如,要将request.user附加到每个已更改的formset模型实例:
class ArticleAdmin(admin.ModelAdmin):
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for obj in formset.deleted_objects:
obj.delete()
for instance in instances:
instance.user = request.user
instance.save()
formset.save_m2m()
另请参见。
ModelAdmin.get_ordering(request)
The get_ordering method takes a``request`` as parameter and is expected to return a list or tuple for ordering similar to the
attribute. 例如:
class PersonAdmin(admin.ModelAdmin):
def get_ordering(self, request):
if request.user.is_superuser:
return ['name', 'rank']
return ['name']
get_search_results方法将显示的对象列表修改为与提供的搜索项匹配的对象。它接受请求,应用当前过滤器的查询集以及用户提供的搜索项。它返回一个包含被修改以实现搜索的查询集的元组,以及一个指示结果是否可能包含重复项的布尔值。
默认实现搜索在中命名的字段。
此方法可以用您自己的自定义搜索方法覆盖。例如,您可能希望通过整数字段搜索,或使用外部工具(如Solr或Haystack)。您必须确定通过搜索方法实现的查询集更改是否可能在结果中引入重复项,并在返回值的第二个元素中返回True。
例如,要启用按整数字段搜索,您可以使用:
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'age')
search_fields = ('name',)
def get_search_results(self, request, queryset, search_term):
queryset, use_distinct = super(PersonAdmin, self).get_search_results(request, queryset, search_term)
search_term_as_int = int(search_term)
except ValueError:
queryset |= self.model.objects.filter(age=search_term_as_int)
return queryset, use_distinct
ModelAdmin.save_related(request, form, formsets, change)
save_related方法给出了HttpRequest,父ModelForm实例,内联表单列表和一个布尔值,添加或更改。在这里,您可以对与父级相关的对象执行任何预保存或后保存操作。请注意,此时父对象及其形式已保存。
ModelAdmin.get_readonly_fields(request, obj=None)
get_readonly_fields方法在添加表单上给予HttpRequest和obj(或None),希望返回将以只读形式显示的字段名称的list或tuple,如上面在部分中所述。
ModelAdmin.get_prepopulated_fields(request, obj=None)
get_prepopulated_fields方法在添加表单上给予HttpRequest和obj(或None),预期返回dictionary,如上面在部分中所述。
ModelAdmin.get_list_display(request)
get_list_display方法被赋予HttpRequest,并且希望返回字段名称的list或tuple显示在如上所述的部分中的changelist视图上。
ModelAdmin.get_list_display_links(request, list_display)
The get_list_display_links method is given the HttpRequest and the list or tuple returned by . 预期将返回更改列表上将链接到更改视图的字段名称的None或list或tuple,如上所述在部分中。
Changed in Django 1.7: None作为有效的get_list_display_links()返回值添加。
ModelAdmin.get_fields(request, obj=None)
New in Django 1.7.
get_fields方法被赋予HttpRequest和obj被编辑(或在添加表单上None),希望返回字段列表,如上面在部分中所述。
ModelAdmin.get_fieldsets(request, obj=None)
get_fieldsets方法是在添加表单上给予HttpRequest和obj(或None),期望返回二元组列表,其中每个二元组在管理表单页面上表示&fieldset&,如上面在部分。
ModelAdmin.get_list_filter(request)
get_list_filter方法被赋予HttpRequest,并且期望返回与属性相同类型的序列类型。
New in Django 1.7.
get_search_fields方法被赋予HttpRequest,并且期望返回与属性相同类型的序列类型。
ModelAdmin.get_inline_instances(request, obj=None)
get_inline_instances方法在添加表单上给予HttpRequest和obj(或None),预期会返回list或tuple的对象,如下面的部分所述。例如,以下内容将返回内联,而不进行基于添加,更改和删除权限的默认过滤:
class MyModelAdmin(admin.ModelAdmin):
inlines = (MyInline,)
def get_inline_instances(self, request, obj=None):
return [inline(self.model, self.admin_site) for inline in self.inlines]
如果覆盖此方法,请确保返回的内联是中定义的类的实例,或者在添加相关对象时可能会遇到“错误请求”错误。
ModelAdmin.get_urls()
ModelAdmin 的get_urls 方法返回ModelAdmin 将要用到的URLs,方式与URLconf 相同。因此,你可以用 中所述的方式扩展它们︰
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = [
url(r'^my_view/$', self.my_view),
return my_urls + urls
def my_view(self, request):
context = dict(
# Include common variables for rendering the admin template.
self.admin_site.each_context(request),
# Anything else you want in the context...
key=value,
return TemplateResponse(request, "sometemplate.html", context)
如果你想要使用Admin 的布局,可以从admin/base_site.html 扩展︰
{% extends "admin/base_site.html" %}
{% block content %}
{% endblock %}
请注意,自定义的模式包含在正常的Admin URLs之前:Admin URL 模式非常宽松,将匹配几乎任何内容,因此你通常要追加自定义的URLs 到内置的URLs 前面。
在此示例中,my_view 的访问点将是/admin/myapp/mymodel/my_view/(假设Admin URLs 包含在/admin/ 下)。
但是, &上述定义的函数self.my_view &将遇到两个问题:
它不 执行任何权限检查,所以会向一般公众开放。
它不提供任何HTTP头的详细信息以防止缓存。这意味着,如果页面从数据库检索数据,而且缓存中间件处于活动状态,页面可能显示过时的信息。
因为这通常不是你想要的,Django 提供一个方便的封装函数来检查权限并标记视图为不可缓存的。这个封装函数就是AdminSite.admin_view()(例如位于ModelAdmin 实例中的self.admin_site.admin_view);就像这样使用它︰
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = [
url(r'^my_view/$', self.admin_site.admin_view(self.my_view))
return my_urls + urls
请注意上述第5行中的被封装的视图︰
url(r'^my_view/$', self.admin_site.admin_view(self.my_view))
这个封装将保护self.my_view 免受未经授权的访问,并将运用django.views.decorators.cache.never_cache 装饰器以确保它不会被缓存,即使缓存中间件是活跃的。
如果该页面是可缓存的,但你仍然想要执行权限检查,你可以传递AdminSite.admin_view() 的cacheable=True 参数︰
url(r'^my_view/$', self.admin_site.admin_view(self.my_view, cacheable=True))
ModelAdmin.get_form(request, obj=None, **kwargs)
返回Admin中添加和更改视图使用的 类,请参阅 和 。
其基本的实现是使用 来子类化,修改如 和属性。所以,举个例子,如果你想要为超级用户提供额外的字段,你可以换成不同的基类表单,就像这样︰
class MyModelAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if request.user.is_superuser:
kwargs['form'] = MySuperuserForm
return super(MyModelAdmin, self).get_form(request, obj, **kwargs)
你也可以简单地直接返回一个自定义的 类。
ModelAdmin.get_formsets(request, obj=None)
自1.7版起已弃用:请改用。
产生用于管理员添加和更改视图。
例如,如果您只想在更改视图中显示特定的内联,则可以覆盖get_formsets,如下所示:
class MyModelAdmin(admin.ModelAdmin):
inlines = [MyInline, SomeOtherInline]
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
if isinstance(inline, MyInline) and obj is None:
yield inline.get_formset(request, obj)
ModelAdmin.get_formsets_with_inlines(request, obj=None)
New in Django 1.7.
产量(FormSet,)对用于管理添加和更改视图。
例如,如果您只想在更改视图中显示特定的内联,则可以覆盖get_formsets_with_inlines,如下所示:
class MyModelAdmin(admin.ModelAdmin):
inlines = [MyInline, SomeOtherInline]
def get_formsets_with_inlines(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# hide MyInline in the add view
if isinstance(inline, MyInline) and obj is None:
yield inline.get_formset(request, obj), inline
ModelAdmin.formfield_for_foreignkey(db_field, request, **kwargs)
ModelAdmin上的formfield_for_foreignkey方法允许覆盖外键字段的默认窗体字段。例如,要根据用户返回此外键字段的对象子集:
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "car":
kwargs["queryset"] = Car.objects.filter(owner=request.user)
return super(MyModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
这使用HttpRequest实例过滤Car外键字段,只显示由User实例拥有的汽车。
ModelAdmin.formfield_for_manytomany(db_field, request, **kwargs)
与formfield_for_foreignkey方法类似,可以覆盖formfield_for_manytomany方法来更改多对多字段的默认窗体字段。例如,如果所有者可以拥有多个汽车,并且汽车可以属于多个所有者 - 多对多关系,则您可以过滤Car外键字段,仅显示由User:
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "cars":
kwargs["queryset"] = Car.objects.filter(owner=request.user)
return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)
ModelAdmin.formfield_for_choice_field(db_field, request, **kwargs)
与formfield_for_foreignkey和formfield_for_manytomany方法类似,可以覆盖formfield_for_choice_field方法更改已声明选择的字段的默认窗体字段。例如,如果超级用户可用的选择应与正式工作人员可用的选项不同,则可按以下步骤操作:
class MyModelAdmin(admin.ModelAdmin):
def formfield_for_choice_field(self, db_field, request, **kwargs):
if db_field.name == "status":
kwargs['choices'] = (
('accepted', 'Accepted'),
('denied', 'Denied'),
if request.user.is_superuser:
kwargs['choices'] += (('ready', 'Ready for deployment'),)
return super(MyModelAdmin, self).formfield_for_choice_field(db_field, request, **kwargs)
在表单字段上设置的任何choices属性将仅限于表单字段。如果模型上的相应字段有选择集,则提供给表单的选项必须是这些选择的有效子集,否则,在保存模型本身之前验证模型本身时,表单提交将失败并显示 。
ModelAdmin.get_changelist(request, **kwargs)
返回要用于列表的Changelist类。默认情况下,使用django.contrib.admin.views.main.ChangeList。通过继承此类,您可以更改列表的行为。
ModelAdmin.get_changelist_form(request, **kwargs)
返回类以用于更改列表页面上的Formset。要使用自定义窗体,例如:
from django import forms
class MyForm(forms.ModelForm):
class MyModelAdmin(admin.ModelAdmin):
def get_changelist_form(self, request, **kwargs):
return MyForm
如果您在上定义Meta.model属性,则还必须定义Meta.fields属性(或Meta.exclude属性)。但是,ModelAdmin会忽略此值,并使用属性覆盖该值。最简单的解决方案是省略Meta.model属性,因为ModelAdmin将提供要使用的正确模型。
ModelAdmin.get_changelist_formset(request, **kwargs)
如果使用,则返回类以在更改列表页上使用。要使用自定义表单集,例如:
from django.forms.models import BaseModelFormSet
class MyAdminFormSet(BaseModelFormSet):
class MyModelAdmin(admin.ModelAdmin):
def get_changelist_formset(self, request, **kwargs):
kwargs['formset'] = MyAdminFormSet
return super(MyModelAdmin, self).get_changelist_formset(request, **kwargs)
ModelAdmin.has_add_permission(request)
如果允许添加对象,则应返回True,否则返回False。
ModelAdmin.has_change_permission(request, obj=None)
如果允许编辑obj,则应返回True,否则返回False。如果obj为None,则应返回True或False以指示是否允许对此类对象进行编辑(例如,False将被解释为意味着当前用户不允许编辑此类型的任何对象)。
ModelAdmin.has_delete_permission(request, obj=None)
如果允许删除obj,则应返回True,否则返回False。If obj is None, should return True or False to indicate whether deleting objects of this type is permitted in general (e.g., False will be interpreted as meaning that the current user is not permitted to delete any object of this type).
ModelAdmin.has_module_permission(request)
New in Django 1.8.
如果在管理索引页上显示模块并允许访问模块的索引页,则应返回True,否则False。默认情况下使用。覆盖它不会限制对添加,更改或删除视图的访问,,和用于那。
ModelAdmin.get_queryset(request)
ModelAdmin上的get_queryset方法会返回管理网站可以编辑的所有模型实例的。覆盖此方法的一个用例是显示由登录用户拥有的对象:
class MyModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(MyModelAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs.filter(author=request.user)
ModelAdmin.message_user(request, message, , extra_tags='', fail_silently=False)
使用 向用户发送消息。参见。
关键字参数运行你修改消息的级别、添加CSS 标签,如果contrib.messages 框架没有安装则默默的失败。关键字参数与 的参数相匹配,更多细节请参见这个函数的文档。有一个不同点是级别除了使用整数/常数传递之外还以使用字符串。
ModelAdmin.get_paginator(queryset, per_page, orphans=0, allow_empty_first_page=True)
返回要用于此视图的分页器的实例。默认情况下,实例化的实例。
ModelAdmin.response_add(request, obj, post_url_continue=None)
为阶段确定。
response_add在管理表单提交后,在对象和所有相关实例已创建并保存之后调用。您可以覆盖它以在对象创建后更改默认行为。
ModelAdmin.response_change(request, obj)
确定 阶段的。
response_change 在Admin 表单提交并保存该对象和所有相关的实例之后调用。您可以重写它来更改对象修改之后的默认行为。
ModelAdmin.response_delete(request, obj_display, obj_id)
New in Django 1.7.
为阶段确定。
在对象已删除后调用response_delete。您可以覆盖它以在对象被删除后更改默认行为。
obj_display是具有已删除对象名称的字符串。
obj_id是用于检索要删除的对象的序列化标识符。
New in Django 1.8: 已添加obj_id参数。
ModelAdmin.get_changeform_initial_data(request)
New in Django 1.7.
用于管理员更改表单上的初始数据的挂钩。默认情况下,字段从GET参数给出初始值。例如,?name=initial_value会将name字段的初始值设置为initial_value。
此方法应返回{'fieldname': 'fieldval'}形式的字典:
def get_changeform_initial_data(self, request):
return {'name': 'custom_initial_value'}
ModelAdmin.add_view(request, form_url='', extra_context=None)
Django视图为模型实例添加页面。见下面的注释。
ModelAdmin.change_view(request, object_id, form_url='', extra_context=None)
Django视图为模型实例版本页。见下面的注释。
ModelAdmin.changelist_view(request, extra_context=None)
Django视图为模型实例更改列表/操作页面。见下面的注释。
ModelAdmin.delete_view(request, object_id, extra_context=None)
模型实例删除确认页面的Django 视图。请参阅下面的注释。
ModelAdmin.history_view(request, object_id, extra_context=None)
显示给定模型实例的修改历史的页面的Django视图。
与上一节中详述的钩型ModelAdmin方法不同,这五个方法实际上被设计为从管理应用程序URL调度处理程序调用为Django视图,以呈现处理模型实例的页面CRUD操作。因此,完全覆盖这些方法将显着改变管理应用程序的行为。
覆盖这些方法的一个常见原因是增加提供给呈现视图的模板的上下文数据。在以下示例中,覆盖更改视图,以便为渲染的模板提供一些额外的映射数据,否则这些数据将不可用:
class MyModelAdmin(admin.ModelAdmin):
# A template for a very customized change view:
change_form_template = 'admin/myapp/extras/openstreetmap_change_form.html'
def get_osm_info(self):
def change_view(self, request, object_id, form_url='', extra_context=None):
extra_context = extra_context or {}
extra_context['osm_data'] = self.get_osm_info()
return super(MyModelAdmin, self).change_view(request, object_id,
form_url, extra_context=extra_context)
这些视图返回实例,允许您在渲染之前轻松自定义响应数据。有关详细信息,请参阅。
ModelAdmin asset definitions
有时候你想添加一些CSS和/或JavaScript到添加/更改视图。这可以通过在ModelAdmin上使用Media内部类来实现:
class ArticleAdmin(admin.ModelAdmin):
class Media:
"all": ("my_styles.css",)
js = ("my_code.js",)
将(或如果为None资产路径。相同的规则适用于表单上的。
Django管理JavaScript使用库。
为了避免与用户提供的脚本或库冲突,Django的jQuery(版本1.11.2)命名为django.jQuery。如果您想在自己的管理JavaScript中使用jQuery而不包含第二个副本,则可以使用更改列表上的django.jQuery对象和添加/编辑视图。
Changed in Django 1.8: 嵌入式jQuery已经从1.9.1升级到1.11.2。
默认情况下,类需要jQuery,因此除非有特定需要,否则不需要向您的ModelAdmin的媒体资源列表添加jQuery。例如,如果您需要将jQuery库放在全局命名空间中(例如使用第三方jQuery插件时)或者如果您需要更新的jQuery版本,则必须包含自己的副本。
Django提供了jQuery的未压缩和“缩小”版本,分别是jquery.js和jquery.min.js。
和具有media属性,可返回存储到JavaScript文件的路径的Media对象列表形式和/或格式。如果是True,它将返回各种JavaScript文件的未压缩版本,包括jquery.js;如果没有,它将返回“minified”版本。
向管理员添加自定义验证
在管理员中添加数据的自定义验证是很容易的。自动管理界面重用,并且ModelAdmin类可以定义您自己的形式:
class ArticleAdmin(admin.ModelAdmin):
form = MyArticleAdminForm
MyArticleAdminForm可以在任何位置定义,只要在需要的地方导入即可。现在,您可以在表单中为任何字段添加自己的自定义验证:
class MyArticleAdminForm(forms.ModelForm):
def clean_name(self):
# do something that validates your data
return self.cleaned_data["name"]
重要的是你在这里使用ModelForm否则会破坏。有关详细信息,请参阅上的文档,更具体地说,。
InlineModelAdmin objects
class InlineModelAdmin
class TabularInline
class StackedInline
此管理界面能够在一个界面编辑多个Model。这些称为内联。假设你有这两个模型:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=100)
The first step in displaying this intermediate model in the admin is to define an inline class for the Membership model:您可以通过在ModelAdmin.inlines中指定模型来为模型添加内联:
from django.contrib import admin
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(adm

我要回帖

更多关于 请教问题的英文邮件 的文章

 

随机推荐