Django-CRM项目学习(一)-admin组件
开始今日份整理
1.admin组件使用
1.1 创建django项目以及开启APP01
略
1.2 创建类
使用django自带的sqlite3的小型文件型的数据库
注:使用sqlite3类型的数据库需要下载驱动
在app01.models创建类
from django.db import models # Create your models here. class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) pub_date = models.DateField() publish = models.ForeignKey('Publish', on_delete=models.CASCADE, null=True) # modeles.CASCADE设置串行,由于和出版社关联,在删除出版社的只会删除外键,不会删除对象,只有在null # 为True才可以删除。 staes = models.IntegerField(choices=[(1,'已出版'),(2,'未出版')],default=1) author = models.ManyToManyField('Author') # 一对多关系 def __str__(self): return self.title class Publish(models.Model): # 出版社类 name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField() def __str__(self): return self.name class Author(models.Model): # 作者类 name = models.CharField(max_length=32) age = models.IntegerField() au_detail = models.OneToOneField('Author_detail',on_delete=models.CASCADE,null=True) def __str__(self): return self.name class Author_detail(models.Model): # 作者详情类 tel = models.CharField(max_length=32) address = models.CharField(max_length=64)
使用manage.py文件创建数据表并写入到数据库中,同时创建超级用户
makemigrations:将库写入到内存中
migrate:将内存中的数据写入到数据库中
createsuperuser:创建超级用户,用于登陆admin页面
1.3 admin.py文件编辑
从app01.models中引入项目各个类
在下面输入要创建的页面
admin.site.register(Book,BookConfig)
admin.site.register(Publish,PublishConfig)
admin.site.register(Author,AuthorConfig)
admin.site.register(Author_detail)
启动项目,在网页中打开,展示如下
输入用户名密码,进入到展示页面
1.4 默认显示
对于admin注册的默认显示内容如下,读取querset,如果有__str__属性,则显示__str__属性。
1.5 自定义列表
根据上图,对数据页面上分别添加出版社,作者以及书籍
1.5.1 自定义展示列表
#创建一个自定义类 class BookConfig(admin.ModelAdmin): #用于展示多对多关系,展示书籍作者 # 用于展示 list_display = ['title','price','pub_date','publish','show_authors','staes'] #在book相关admin中添加自定义类,BookConfig为新增 admin.site.register(Book,BookConfig)
上面的list_display为内置用法,用于显示,最后展示如下
1.5.2 自定义展示多对多关系
书籍与作者的关系是多对多关系,需要自定义函数,用于展示!
#用于展示多对多关系,自定义函数show_authors,完整代码如下 class BookConfig(admin.ModelAdmin): def show_authors(self,obj): print("obj",obj) return '|'.join([obj.name for obj in obj.author.all()]) # 用于展示 list_display = ['title','price','pub_date','publish','show_authors',]
多个作者用‘|’分隔。
1.5.3 反射字段
对于表中使用choices的属相,反射对应的字段
在models中如下设置
注:
- django现在默认会将choice的对应的值转换对应的值,默认会显示为对应的出版社或者未出版社
- obj.get_states_display()用于反射choiice对应的值
1.6 批量操作
批量操作为action操作
在上面的BookConfig中写入
#action操作 # 价格初始化 def patch_init(self,request,queryset): print('queryset',queryset) queryset.update(price=0) patch_init.short_description = '价格初始化'#设置多选服务 # 出版状态初始化 def states_status(self,request,queryset): queryset.update(staes=2) states_status.short_description ='出版状态初始化' # 多选服务 actions = [patch_init,states_status] #其中.short_description以及actions为内置应用
展示如下
1.7 多重过滤
在上面的BookConfig类中写入
#多重过滤 list_filter = ['publish','author'] #对出版社以及作者做过滤
展示如下
1.8 排序
在上面的BookConfig类中写入
# 排序 ordering = ['price','-id'] #可以用俩个参数进行排序,默认是升序,加-号变为逆反
1.9 模糊查询
# 模糊查询 search_fields = ['title','price'] #如果title以及价格中都有特定的参数那么都显示
展示如下
admin整体代码
from django.contrib import admin # Register your models here. from app01.models import Book,Publish,Author,Author_detail class BookConfig(admin.ModelAdmin): def show_authors(self,obj): print("obj",obj) return '|'.join([obj.name for obj in obj.author.all()]) # 用于展示 list_display = ['title','price','pub_date','publish','show_authors','staes'] # 用于设置连接的内容 list_display_links = ['title','price'] #action操作 # 价格初始化 def patch_init(self,request,queryset): print('queryset',queryset) queryset.update(price=0) patch_init.short_description = '价格初始化'#设置多选服务 # 出版状态初始化 def states_status(self,request,queryset): queryset.update(staes=2) states_status.short_description ='出版状态初始化' # 多选服务 actions = [patch_init,states_status] #多重过滤 list_filter = ['publish','author'] # 排序 ordering = ['price','-id'] # 模糊查询 search_fields = ['title','price'] class PublishConfig(admin.ModelAdmin): list_display = ['name','city','email'] class AuthorConfig(admin.ModelAdmin): def show_tel(self,obj): print('obj',obj) return obj.au_detail.tel def show_address(self,obj): print('obj',obj) return obj.au_detail.address list_display = ['name','age','show_tel','show_address'] admin.site.register(Book,BookConfig) admin.site.register(Publish,PublishConfig) admin.site.register(Author,AuthorConfig) admin.site.register(Author_detail)
1.10 其他操作
1.10.1 list_display,列表时,定制显示的列。
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): list_display = ('user', 'pwd', 'xxxxx') def xxxxx(self, obj): return "xxxxx"
1.10.2 list_display_links,列表时,定制列可以点击跳转。
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): list_display = ('user', 'pwd', 'xxxxx') list_display_links = ('pwd',)
1.10.3 list_filter,列表时,定制右侧快速筛选。
1.10.4 list_select_related,列表时,连表查询是否自动select_related
1.10.5 list_editable,列表时,可以编辑的列
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): list_display = ('user', 'pwd','ug',) list_editable = ('ug',)
1.10.6 search_fields,列表时,模糊搜索的功能
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): search_fields = ('user', 'pwd')
1.10.7 date_hierarchy,列表时,对Date和DateTime类型进行搜索
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): date_hierarchy = 'ctime'
1.10.8 inlines,详细页面,如果有其他表和当前表做FK,那么详细页面可以进行动态增加和删除
class UserInfoInline(admin.StackedInline): # TabularInline extra = 0 model = models.UserInfo class GroupAdminMode(admin.ModelAdmin): list_display = ('id', 'title',) inlines = [UserInfoInline, ]
1.10.9 action,列表时,定制action中的操作
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): # 定制Action行为具体方法 def func(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
1.10.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
1.10.11 raw_id_fields,详细页面,针对FK和M2M字段变成以Input框形式
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): raw_id_fields = ('FK字段', 'M2M字段',)
1.10.12 fields,详细页面时,显示字段的字段
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): fields = ('user',)
1.10.13 exclude,详细页面时,排除的字段
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): exclude = ('user',)
1.10.14 readonly_fields,详细页面时,只读字段
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): readonly_fields = ('user',)
1.10.15 fieldsets,详细页面时,使用fieldsets标签对数据进行分割显示
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): fieldsets = ( ('基本数据', { 'fields': ('user', 'pwd', 'ctime',) }), ('其他', { 'classes': ('collapse', 'wide', 'extrapretty'), # 'collapse','wide', 'extrapretty' 'fields': ('user', 'pwd'), }), )
1.10.16 详细页面时,M2M显示时,数据移动选择(方向:上下和左右)
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): filter_vertical = ("m2m字段",) # 或filter_horizontal = ("m2m字段",)
1.10.17 ordering,列表时,数据排序规则
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): ordering = ('-id',) 或 def get_ordering(self, request): return ['-id', ]
1.10.18 radio_fields,详细页面时,使用radio显示选项(FK默认使用select)
radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL
1.10.19 form = ModelForm,用于定制用户请求时候表单验证
from app01 import models from django.forms import ModelForm from django.forms import fields class MyForm(ModelForm): others = fields.CharField() class Meta: model = models = models.UserInfo fields = "__all__" @admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): form = MyForm
1.10.20 empty_value_display = "列数据为空时,显示默认值"
@admin.register(models.UserInfo) class UserAdmin(admin.ModelAdmin): empty_value_display = "列数据为空时,默认显示" list_display = ('user','pwd','up') def up(self,obj): return obj.user up.empty_value_display = "指定列数据为空时,默认显示"
2. admin 源码解析
对于admin组件的使用,在初期主要是有四大关键点,按照这几个点开解析源码
- admin组件的启动
- 模块的注册
- URLS的设计
- URLS的增删改查
2.1 admin的启动
(1)django在启动项目的时候,首先会读取settings文件,读取配置文件,执行settings中的INSTALLED_APPS
,我们可以看到第一个就是django.contrib.admin
(2)查看admin文件
from django.contrib import admin
注:
- 引入一个模块,除了函数,其他都会被执行一遍
- __all__,导入就会执行里面的函数
(3)admin.py文件的执行顺序
执行顺序是按照app的注册顺序来执行
2.2 admin的注册
2.2.1 面向对象的补充
单例模式,常用方式主要有__new__方式以及基于模块的单例模式
#1.基于__new__方式的单例模式 class Animal(object): __instance =None def __new__(cls, *args, **kwargs): if not cls.__instance: cls.__instance = object.__new__(cls) return cls.__instance #2.基于模块的单例模式 class Dog(): def __init__(self): pass def run(self): print('is running......') dog1 = Dog() # 其他人引用这个模块中dog1就是一个永远单独的例子
补充:
- 单例的好处:减少实例化对象占用的空间,加快整个程序的运行速度
- 实例化的对象,只是保留类的类指针,并不保留类方法
- 变量的查询顺序:实例对象的名称空间~类名称空间~父类的名称空间
- 一个项目只会有一个程序,实例化对象都在一个名称空间,对于基于模块的单例模式,不管怎么引用,都是指向的一个。
2.2.2 admin的site
查看site源码
from django.contrib import admin from django.contrib.admin.sites import AdminSite, site #最后进入site源码
2.2.3 site的register方法
查看site的AdminSite类,查看里面的register方法
对于register方法来说最重要的就是上面红框内的俩句话,分别解析
2.2.3.1 第一句
下面在看下admin的默认样式
2.2.3.2 第二句
第二句的前提
site在实例化开始的时候就定义了一个空的字典,用于存放每个app注册的表以及他的样式。
在app01中stark中注册book以及publish,展示如下
{<class 'app01.models.Publish'>: <stark.services.sites.ModelStark object at 0x03B86BF0>, <class 'app01.models.Book'>: <app01.stark.BookConfig object at 0x03B86B90>} ####展示字典中的内容####
2.3 URLS的设计以及URLS的增删改查(超重点)
其实就是解析path('admin/', admin.site.urls),这句话
2.3.1 补充知识点
APPEND_SLASH = True #默认为True
这个参数的主要作用为补全网络的’/’这个符号,如果没有django会补全,并让浏览器重新发送请求
2.3.2 URL分发
之前在使用django的时候,是使用include方法做内容分发到不同的app中
#普通的二级分发 path("test",([ path("abc",test01), path("bcd",test02), ],None,None)) #普通的三级分发 path("test",([ path("abc",([ path('123',test03), path('456',test04), ],None,None)), path("bcd",test02) ],None,None))
2.3.3 自定义admin的url分发
解析自定义admin的url分发功能
def get_urls2(): # 用于生成三级分发目录,增删改查 temp=[ path("",list_view), path("add/",add_view), path("(\d+)/change/",change_view), path("(\d+)/delete/",delete_view), ] return (temp,None,None) def get_url(): #动态的为注册的模型类创建增删改查的URL temp=[] #admin.site._registry为注册模型类时生成的那个字典 for model,config_obj in admin.site._registry.items(): # 获取数据库中每张数据表的表名字段 model_name = model._meta.model_name #获取对应项目的项目名称,例如app01 app_label = model._meta.app_label temp.append( path("%s/%s/" % (app_label, model_name), get_urls2()) ) return (temp, None, None) urlpatterns = [ path('admin/', admin.site.urls), path("stark/",get_urls())#后面用于获取urls ]
这样就创建好了一个admin的增删改查的分发功能,其中有几个侧重点
admin.site._registry为注册模型类时生成的那个字典 # 获取数据库中每张数据表的表名字段 model_name = model._meta.model_name #获取对应项目的项目名称,例如app01 app_label = model._meta.app_label
a