欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
  知识预览
 
  admin组件使用
 
  admin源码解析
 
  回到顶部
 
  admin组件使用
 
  Django提供了基于web的管理工具。
 
  Django自动管理工具是django.contrib的一部分。你可以在项目的settings.py中的INSTALLED_APPS看到它:
 
  复制代码
 
  #Applicationdefinition
 
  INSTALLED_APPS=[
 
  'django.contrib.admin',
 
  'django.contrib.auth',
 
  'django.contrib.contenttypes',
 
  'django.contrib.sessions',
 
  'django.contrib.messages',
 
  'django.contrib.staticfiles',
 
  "app01"
 
  ]
 
  复制代码
 
  django.contrib是一套庞大的功能集,它是Django基本代码的组成部分。
 
  激活管理工具
 
  通常我们在生成项目时会在urls.py中自动设置好,
 
  复制代码
 
  fromdjango.conf.urlsimporturl
 
  fromdjango.contribimportadmin
 
  urlpatterns=[
 
  url(r'^admin/',admin.site.urls),
 
  ]
 
  复制代码
 
  当这一切都配置好后,Django管理工具就可以运行了。
 
  使用管理工具
 
  启动开发服务器,然后在浏览器中访问http://127.0.0.1:8000/admin/,得到登陆界面,你可以通过命令pythonmanage.pycreatesuperuser来创建超级用户。
 
  为了让admin界面管理某个数据模型,我们需要先注册该数据模型到admin
 
  ViewCode
 
  admin的定制
 
  在admin.py中只需要讲Mode中的某个类注册,即可在Admin中实现增删改查的功能,如:
 
  admin.site.register(models.UserInfo)
 
  但是,这种方式比较简单,如果想要进行更多的定制操作,需要利用ModelAdmin进行操作,如:
 
  复制代码
 
  方式一:
 
  classUserAdmin(admin.ModelAdmin):
 
  list_display=('user','pwd',)
 
  admin.site.register(models.UserInfo,UserAdmin)#第一个参数可以是列表
 
  方式二:
 
  @admin.register(models.UserInfo)#第一个参数可以是列表
 
  classUserAdmin(admin.ModelAdmin):
 
  list_display=('user','pwd',)
 
  复制代码
 
  ModelAdmin中提供了大量的可定制功能,如
 
  1.list_display,列表时,定制显示的列。
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  list_display=('user','pwd','xxxxx')
 
  defxxxxx(self,obj):
 
  return"xxxxx"
 
  2.list_display_links,列表时,定制列可以点击跳转。
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  list_display=('user','pwd','xxxxx')
 
  list_display_links=('pwd',)
 
  3.list_filter,列表时,定制右侧分类筛选。字段至少有两个以上
 
  list_filter=["title"]#注意外键关联
 
  list_filter=["title","user","tags"]
 
  4.list_select_related,列表时,连表查询是否自动select_related
 
  5.list_editable,列表时,列表内设定的列以输入框形式展示,注意要和list_display_links=('pwd',)搭配使用,且links内不能够有edict内的字段
 
  classArticleConfig(admin.ModelAdmin):
 
  defdeletes_article(self):#用函数表示新增字段
 
  returnmark_safe("<ahref="">删除</a>")
 
  list_display=["title","create_time","comment_count","up_count",deletes_article]#展示那些字段
 
  list_display_links=["create_time"]
 
  list_filter=["title","user","tags"]
 
  list_editable=["title"]
 
  6.search_fields,对列表内的字段进行搜索,字段之间是或关系
 
  classArticleConfig(admin.ModelAdmin):
 
  defdeletes_article(self):#用函数表示新增字段
 
  returnmark_safe("<ahref="">删除</a>")
 
  list_display=["title","create_time","comment_count","up_count",deletes_article]#展示那些字段
 
  list_display_links=["title"]
 
  search_fields=["title"]
 
  7.date_hierarchy,列表时,对Date和DateTime类型进行搜索
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  date_hierarchy='ctime'
 
  8inlines,详细页面,如果有其他表和当前表做FK,那么详细页面可以进行动态增加和删除
 
  复制代码
 
  classUserInfoInline(admin.StackedInline):#TabularInline
 
  extra=0
 
  model=models.UserInfo
 
  classGroupAdminMode(admin.ModelAdmin):
 
  list_display=('id','title',)
 
  inlines=[UserInfoInline,]
 
  复制代码
 
  9action,对列表内数据进行批量增删改查,自定义删除等功能
 
  复制代码
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  #定制Action行为具体方法
 
  deffunc(self,request,queryset):
 
  queryset.update(create_time="2017-10-18")
 
  func.short_description="更新时间"
 
  actions=[func,]
 
  #Action选项都是在页面上方显示
 
  actions_on_top=True
 
  #Action选项都是在页面下方显示
 
  actions_on_bottom=False
 
  #是否显示选择个数
 
  actions_selection_counter=True
 
  复制代码
 
  10定制HTML模板
 
  add_form_template=None
 
  change_form_template=None
 
  change_list_template=None//更新页面
 
  delete_confirmation_template=None
 
  delete_selected_confirmation_template=None
 
  object_history_template=None
 
  11raw_id_fields,详细页面,针对FK和M2M字段变成以Input框形式
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  raw_id_fields=('FK字段','M2M字段',)
 
  12fields,编辑表时,可选择性显示页面,把可以为空的字段隐藏起来
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  fields=('user',)
 
  13exclude,详细页面时,排除的字段
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  exclude=('user',)
 
  14readonly_fields,详细页面时,只读字段
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  readonly_fields=('user',)
 
  15fieldsets,详细页面时,使用fieldsets标签对数据进行分割显示
 
  复制代码
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  fieldsets=(
 
  ('基本数据',{
 
  'fields':('user','pwd','ctime',)
 
  }),
 
  ('其他',{
 
  'classes':('collapse','wide','extrapretty'),#'collapse','wide','extrapretty'
 
  'fields':('user','pwd'),
 
  }),
 
  )
 
  复制代码
 
  16详细页面时,M2M显示时,数据移动选择(方向:上下和左右)
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  filter_vertical=("m2m字段",)#或filter_horizontal=("m2m字段",)
 
  17ordering,列表时,数据排序规则
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  ordering=('-id',)
 
  或
 
  defget_ordering(self,request):
 
  return['-id',]
 
  18.radio_fields,详细页面时,使用radio显示选项(FK默认使用select)
 
  radio_fields={"ug":admin.VERTICAL}#或admin.HORIZONTAL
 
  19form=ModelForm,用于定制用户请求时候表单验证
 
  复制代码
 
  fromapp01importmodels
 
  fromdjango.formsimportModelForm
 
  fromdjango.formsimportfields
 
  classMyForm(ModelForm):
 
  others=fields.CharField()
 
  classMeta:
 
  model=models=models.UserInfo
 
  fields="__all__"
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  form=MyForm
 
  复制代码
 
  20empty_value_display="列数据为空时,显示默认值"
 
  复制代码
 
  @admin.register(models.UserInfo)
 
  classUserAdmin(admin.ModelAdmin):
 
  empty_value_display="列数据为空时,默认显示"
 
  list_display=('user','pwd','up')
 
  defup(self,obj):
 
  returnobj.user
 
  up.empty_value_display="指定列数据为空时,默认显示"
 
  复制代码
 
  fromdjango.contribimportadmin
 
  #Registeryourmodelshere.
 
  from.modelsimport*
 
  classBookInline(admin.StackedInline):#TabularInline
 
  extra=0
 
  model=Book
 
  classBookAdmin(admin.ModelAdmin):
 
  list_display=("title",'publishDate','price',"foo","publisher")
 
  list_display_links=('publishDate',"price")
 
  list_filter=('price',)
 
  list_editable=("title","publisher")
 
  search_fields=('title',)
 
  date_hierarchy='publishDate'
 
  preserve_filters=False
 
  deffoo(self,obj):
 
  returnobj.title+str(obj.price)
 
  #定制Action行为具体方法
 
  deffunc(self,request,queryset):
 
  print(self,request,queryset)
 
  print(request.POST.getlist('_selected_action'))
 
  func.short_description="中文显示自定义Actions"
 
  actions=[func,]
 
  #Action选项都是在页面上方显示
 
  actions_on_top=True
 
  #Action选项都是在页面下方显示
 
  actions_on_bottom=False
 
  #是否显示选择个数
 
  actions_selection_counter=True
 
  change_list_template="my_change_list_template.html"
 
  classPublishAdmin(admin.ModelAdmin):
 
  list_display=('name','email',)
 
  inlines=[BookInline,]
 
  admin.site.register(Book,BookAdmin)#第一个参数可以是列表
 
  admin.site.register(Publish,PublishAdmin)
 
  admin.site.register(Author)
 
  ViewCode
 
  回到顶部
 
  admin源码解析
 
  单例模式
 
  单例模式(SingletonPattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
 
  就像系统的某个类模块,每一个项目实例化的对象都指向一个地方,因为它们需要的功能和数据是一样的,因此修改一个,会影响到其他项目的执行,但是这样可以节省空间.就像AppConfig,在很多app内都需要用到,如果内一个app都实例化一个对象,浪费空间的同时,也降低了效率
 
  在配置信息中是很常见的
 
  在Python中,我们可以用多种方法来实现单例模式:
 
  使用模块
 
  使用__new__
 
  使用装饰器(decorator)
 
  使用元类(metaclass)
 
  (1)使用__new__
 
  为了使类只能出现一个实例,我们可以使用__new__来控制实例的创建过程,代码如下:
 
  复制代码
 
  classSingleton(object):
 
  _instance=None
 
  def__new__(cls,*args,**kw):#cls表示当前类
 
  ifnotcls._instance:
 
  cls._instance=super(Singleton,cls).__new__(cls,*args,**kw)#用__new__实例化一个对象,第一次进来的时候_instance,已经变成一个实例化对象了
 
  returncls._instance
 
  classMyClass(Singleton):
 
  a=1
 
  复制代码
 
  复制代码
 
  >>>one=MyClass()
 
  >>>two=MyClass()
 
  >>>one==two
 
  True
 
  >>>oneistwo
 
  True
 
  >>>id(one),id(two)
 
  (4303862608,4303862608)
 
  复制代码
 
  (2)使用模块
 
  其实,Python的模块就是天然的单例模式,因为模块在第一次导入时,会生成.pyc文件,当第二次导入时,就会直接加载.pyc文件,即在python整个项目中模块只导入一次,在别的py文件导入时,就直接使用第一次导入生成的.pyc文件,而不会再次导入模块。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:
 
  #mysingleton.py需要导入的模块
 
  classMy_Singleton(object):
 
  deffoo(self):
 
  pass
 
  my_singleton=My_Singleton()
 
  当我们导入一个其他模块中的实例化对象,或者类,在各个py文件中都指向一个id地址,但是由类生成的对象就是不同的在admin中导入site使用的就是该方法,这里包括导入模块后使用模块.已经实例化的对象都是指向同一个id:
 
  frommysingletonimportmy_singleton#导入一个实例化对象,当在项目其他py文件导入时,就直接指向该空间,共享该方法
 
  my_singleton.foo()
 
  admin执行流程
 
  <1>按着App注册顺序加载执App内所有admin.py文件,即在脚本中导入或者使用admin内的方法都会先执行
 
  defautodiscover():
 
  autodiscover_modules('admin',register_to=site)
 
  <2>执行代码
 
  复制代码
 
  #admin.py
 
  classBookAdmin(admin.ModelAdmin):
 
  list_display=("title",'publishDate','price')
 
  admin.site.register(Book,BookAdmin)
 
  admin.site.register(Publish)
 
  复制代码
 
  <3>admin.site
 
  这里应用的是一个单例模式,对于AdminSite类的一个单例模式,在所有app中执行的admin.site都是同一个对象,指向同一个内存地址
 
  <4>执行register方法
 
  admin.site.register(Book,BookAdmin)
 
  admin.site.register(Publish)
 
  复制代码
 
  classModelAdmin(BaseModelAdmin):pass
 
  defregister(self,model_or_iterable,admin_class=None,**options):
 
  _registry={}
 
  ifnotadmin_class:
 
  admin_class=ModelAdmin
 
  #Instantiatetheadminclasstosaveintheregistry
 
  self._registry[model]=admin_class(model,self)
 
  复制代码
 
  思考:在每一个app的admin.py中加上
 
  print(admin.site._registry)#可以拿到所有已经注册的类名和实例化的对象
 
  <5>admin的URL配置源码
 
  urlpatterns=[
 
  url(r'^admin/',admin.site.urls),
 
  ]
 
  复制代码
 
  classAdminSite(object):
 
  defget_urls(self):
 
  fromdjango.conf.urlsimporturl,include
 
  urlpatterns=[]
 
  #Addineachmodel'sviews,andcreatealistofvalidURLSforthe
 
  #app_index
 
  valid_app_labels=[]
 
  formodel,model_admininself._registry.items():
 
  urlpatterns+=[
 
  url(r'^%s/%s/'%(model._meta.app_label,model._meta.model_name),include(model_admin.urls)),
 
  ]
 
  ifmodel._meta.app_labelnotinvalid_app_labels:
 
  valid_app_labels.append(model._meta.app_label)
 
  returnurlpatterns
 
  @property
 
  defurls(self):
 
  returnself.get_urls(),'admin',self.name
 
  复制代码
 
  <6>url()方法的扩展应用,即把url中视图函数改成列表[],第一个参数是url路径匹配,第2和第3个参数是None,可以是多层次分发,列表内路径可有函数执行后返回数据
 
  简单版路由分发
 
  复制代码
 
  fromdjango.shortcutsimportHttpResponse
 
  deftest01(request):
 
  returnHttpResponse("test01")
 
  deftest02(request):
 
  returnHttpResponse("test02")
 
  urlpatterns=[
 
  url(r'^admin/',admin.site.urls),
 
  url(r'^yuan/',([
 
  url(r'^test01/',test01),
 
  url(r'^test02/',test02),
 
  ],None,None)),
 
  ]
 
  复制代码
 
  老师版扩展优化
 
  复制代码
 
  fromdjango.conf.urlsimporturl,include
 
  fromdjango.contribimportadmin
 
  fromdjango.shortcutsimportHttpResponse
 
  defchange_list_view(request):
 
  returnHttpResponse("change_list_view")
 
  defadd_view(request):
 
  returnHttpResponse("add_view")
 
  defdelete_view(request):
 
  returnHttpResponse("delete_view")
 
  defchange_view(request):
 
  returnHttpResponse("change_view")
 
  defget_urls():
 
  temp=[
 
  url(r"^$".format(app_name,model_name),change_list_view),
 
  url(r"^add/$".format(app_name,model_name),add_view),
 
  url(r"^\d+/del/$".format(app_name,model_name),delete_view),
 
  url(r"^\d+/change/$".format(app_name,model_name),change_view),
 
  ]
 
  returntemp
 
  url_list=[]
 
  formodel_class,objinadmin.site._registry.items():#切记一定要调用.items方法才能够实行for循环
 
  model_name=model_class._meta.model_name
 
  app_name=model_class._meta.app_label
 
  #temp=url(r"{0}/{1}/".format(app_name,model_name),(get_urls(),None,None))
 
  temp=url(r"{0}/{1}/".format(app_name,model_name),include(get_urls()))
 
  url_list.append(temp)
 
  urlpatterns=[
 
  url(r'^admin/',admin.site.urls),
 
  url(r'^yuan/',(url_list,None,None)),
 
  ]
 
  复制代码
 
  注意:在这里调用了models模型内的meta方法,如果在表中没有设置,meta会自定义一些参数
 
  meta有以下的方法
 
  unique_together#查看联合唯一字段属性
 
  permissions#查看权限
 
  db_tablespace#数据库中表名
 
  db_table#查看数据库表名,一般自定义为App名+表名
 
  db_table#表名所在的app
 
  url分发详情
 
  defget_url():#一级分发表
 
  #admin.site._registry拿到当前注册的表和实例化的对象,通过单例模型
 
  url=[]
 
  forkey,valueinadmin.site._registry.items():
 
  #注意这里的key和value都是一个类变量,对其打印或显示,只会显示内存地址,
 
  #因此关键在于拿到对象的名字和相应的上一层路径
 
  app_name=key._meta.app_label
 
  table_name=key._meta.model_name
 
  url_base=re_path('^{}/{}/'.format(app_name,table_name),[get_url2(),None,None])
 
  url.append(url_base)
 
  returnurl
 
  defget_url2():
 
  url=[]
 
  url.append(re_path('^add/$',test))
 
  url.append(re_path('^delete/(\d+)',test))
 
  url.append(re_path('^update/(\d+)',test))
 
  url.append(re_path('^check/(\d+)',test))
 
  returnurl
 
  urlpatterns=[
 
  path('admin/',admin.site.urls),
 
  re_path('^ad/',(get_url(),None,None)),
 
  ]
 
  注册问题
 
  register()函数源码,函数注册时,当没有自定义模块时,用自定的类,实例化传进来的参数,如果有自定义的类,就用传进来的类实例化传进来的参数,注意这里把表名做键,实例化的对象做值放在字典中,注意的键是表名,不需要用""
 
  classAdminSite(object):
 
  def__init__(self,name='admin'):
 
  self._registry={}
 
  defregister(self,models,admin_class=None,**option):
 
  ifnotadmin_class:
 
  admin_class=ModelAdmin#默认一个类方法
 
  #对传进来的模型进行实例化,因此传进来一个对象,都会封装在_registry字典中
 
  self._registry[ArticleDetail]=admin_class(models,self)
 
  site=AdminSite()
 
  效果如下图
 
  admin.site.register(models.ArticleDetail)
 
  self._registry[ArticleDetail]=ModelAdmin(ArticleDetail,self)
 
  #self._registry={ArticleDetail:ModelAdmin(ArticleDetail),}
 
  admin.site.register(models.Article,ArticleConfig)
 
  self._registry[Article]=ArticleConfig(Article,self)
 
  #self._registry={ArticleDetail:ModelAdmin(ArticleDetail),Article:ArticleConfig(Article,slef)}
 
  类的补充
 
  类中表示调用他的对象或者,如实例化对象调用类中的方法,此时self就是,字典的键是不可变类型,因此他可以是实例化的对象

如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h54742.shtml