一、单例模式:单个实例公用一个对象
1、基于模块的单例模式
s1.py文件:
class Foo(object):
def test(self):
print("123")
v = Foo()
s2.py文件:
from s1 import v as v1
print(v1,id(v1)) #<s1.Foo object at 0x0000000002221710> 35788560
from s1 import v as v2
print(v1,id(v2)) #<s1.Foo object at 0x0000000002221710> 35788560
# 两个的内存地址是一样的
# 文件加载的时候,第一次导入后,再次导入时不会再重新加载。
2、基于new方法的单例模式
class Singleton:
def __new__(cls, *args, **kw):
'''__new__是一个构造方法,self就是他构造的'''
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
one = Singleton()
two = Singleton()
print(one,two) #他们两个的地址一样
# print(id(one),id(two))
one.name = 'alex'
print(two.name)
二、Django-admin使用流程
1、数据库迁移
models.py文件:
from django.db import models
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
age=models.IntegerField()
def __str__(self):
return self.name
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
city=models.CharField( max_length=32)
email=models.EmailField()
def __str__(self):
return self.name
class Book(models.Model):
nid = models.AutoField(primary_key=True,verbose_name="编号")
title = models.CharField( max_length=32,verbose_name="名称")
publishDate=models.DateField()
price=models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
# 与Publish建立一对多的关系,外键字段建立在多的一方
publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
# 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
authors=models.ManyToManyField(to='Author',)
def __str__(self):
return self.title
#执行下面python语句生成相关表(数据迁移)
# python3 manage.py makemigrations
# python3 manage.py migrate
2、创建超级用户
# python3 manage.py createsuperuser
3、admin.py中注册表
from django.contrib import admin
from app01 import models
admin.site.register(models.Book)
admin.site.register(models.Publish)
admin.site.register(models.Author)
4、如果新建应用app02
# python3 manage.py startapp app02
settings.py文件添加内容:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
"app02.apps.App02Config",
]
然后在app02应用的models.py增加表,接着数据库迁移,在app02应用的admin.py中对表进行注册
三、admin源码分析
1、访问url
def get_urls():
temp = [
url(r'^$'.format(app_name, cls_name), change_list),
url(r'^add/$'.format(app_name, cls_name), add_view),
url(r'^del/$'.format(app_name, cls_name), delete_view),
url(r'^change/$'.format(app_name, cls_name), change_view)
]
return temp
url_list = []
for model_class, v in admin.site._registry.items():
cls_name = model_class._meta.model_name # 当前类名称的小写
app_name = model_class._meta.app_label # 当前app的名称
方式一:
# all_urls = url(r'^{0}/{1}/'.format(app_name,cls_name), (get_urls(),None,None,))
方式二:
all_urls = url(r'^{0}/{1}/'.format(app_name, cls_name), include(get_urls()))
url_list.append(all_urls)
urlpatterns = [
url(r'^admin/', admin.site.urls),
# admin.site这个对象里面有一个属性_registry = {}
# 点击urls查看源码返回的是一个元组,元组的第一个元素是一个列表
url(r'^index/', (
[
url(r'^app01/userinfo/', ([
url(r'^$', change_list, name="login"),
url(r'^add/$', add_view, name="login"),
url(r'^(\d+)/del/$', delete_view, name="login"),
url(r'^(\d+)/change/$', change_view, name="login"),
], None, None), name="login"),
url(r'^app01/usertype/', ([
url(r'^$', change_list, name="login"),
url(r'^add/$', add_view, name="login"),
url(r'^(\d+)/del/$', delete_view, name="login"),
url(r'^(\d+)/change/$', change_view, name="login"),
], None, None), name="login"), ], None, None)),
url(r'^app02/article/', ([
url(r'^$', change_list, name="login"),
url(r'^add/$', add_view, name="login"),
url(r'^(\d+)/del/$', delete_view, name="login"),
url(r'^(\d+)/change/$', change_view, name="login"),
], None, None), name="login"),
# index和index2的两个是一样的,我们可以用index2的方式替代index
url(r'^index2/', (url_list, None, None,)),
]
2、admin源码流程
a. 运行程序,找到每一个app中的 admin.py 文件,并加载
- app01.admin.py
- 创建admin.site中的对象
- 执行对象的 register方法,目的:将注册类添加到 _registry中
_registry = {
key是传进来的model value:是ModelAdmin的对象,传了两个参数
models.Role: ModelAdmin(models.Role,admin.site),
models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
models.UserType: ModelAdmin(models.UserType,admin.site)
}
- app02.admin.py
- 用app01.admin中创建那个admin.site对象
- 执行对象的 register方法,目的:讲注册类添加到 _registry中
_registry = {
models.Role: ModelAdmin(models.Role,admin.site),
models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
models.UserType: ModelAdmin(models.UserType,admin.site)
models.Article: ModelAdmin(models.Article,admin.site)
}
admin.site是一个对象(单例模式创建),其中封装了:
_registry = {
models.Role: ModelAdmin(models.Role,admin.site),
models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
models.UserType: ModelAdmin(models.UserType,admin.site)
models.Article: ModelAdmin(models.Article,admin.site)
}
b. urls.py
再次调用 admin.site 对象的 urls属性:
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
class ModelAdmin(object):
def __init__(self,model_class,site):
self.model_class = model_class
self.site = site
def changelist_view(self,request):
data_list = self.model_class.objects.all() #是动态的
return HttpResponse('列表页面')
def add_view(self,request):
return HttpResponse('添加页面')
def delete_view(self,request,nid):
return HttpResponse('删除页面')
def change_view(self,request,nid):
return HttpResponse('修改页面')
def get_urls(self):
urlpatterns = [
url(r'^$', self.changelist_view),
url(r'^add/$', self.add_view),
url(r'^(.+)/delete/$', self.delete_view),
url(r'^(.+)/change/$', self.change_view),
]
return urlpatterns
@property
def urls(self):
return self.get_urls()
class AdminSite(object):
def __init__(self):
self._registry = {}
def register(self,model_class,model_admin):
self._registry[model_class] = model_admin(model_class,self)
def get_urls(self):
"""
models.Role: ModelAdmin(models.Role,admin.site),
models.UserInfo: ModelAdmin(models.UserInfo,admin.site)
models.UserType: ModelAdmin(models.UserType,admin.site)
models.Article: ModelAdmin(models.Article,admin.site)
"""
url_list = []
for model_class,model_admin in self._registry.items():
model_class是一个类
app_name = model_class._meta.app_label
model_name = model_class._meta.model_name
url_list += [
url('%s/%s' %(app_name,model_name,), include(model_admin.urls))
]
return url_list
@property
def urls(self):
return (self.get_urls(), None,None )
四、Django-admin(web页面显示)
models.py文件:
from django.db import models
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
age=models.IntegerField()
# 与AuthorDetail建立一对一的关系
authorDetail=models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)
def __str__(self):
return self.name
class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
birthday=models.DateField()
telephone=models.BigIntegerField()
addr=models.CharField( max_length=64)
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name=models.CharField( max_length=32)
city=models.CharField( max_length=32)
email=models.EmailField()
def __str__(self):
return self.name
class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField( max_length=32)
publishDate=models.DateField()
price=models.DecimalField(max_digits=5,decimal_places=2)
# 与Publish建立一对多的关系,外键字段建立在多的一方
publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
# 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
authors=models.ManyToManyField(to='Author',)
admin.py文件:
from django.contrib import admin
# Register your models here.
from .models import *
#定制功能
class BookConfig(admin.ModelAdmin):
list_display = ["nid","title","price","publishDate","publish"] #显示的列
list_display_links=["title","price"] #字段可以点击跳转
list_filter=["title","publish"] #定制右侧快速筛选
search_fields=["title"] #列表时,模糊搜索的功能
def patch_init(self,request,queryset): #批量操作执行的函数
queryset.update(price=100)
patch_init.short_description = "批量初始化" #批量操作显示的描述
actions = [patch_init]
#对所选择的选项执行批量操作函数
#change_list_template="list.html" #定制HTML模板
ordering=("price","nid",) #数据排序规则
admin.site.register(Book,BookConfig) #第一个参数是对哪个表进行注册,第二个参数是新增的自定义的功能类,这样book页面就会显示新的功能了
admin.site.register(Publish)
admin.site.register(Author)
admin.site.register(AuthorDetail)
其他的一些定制功能:
1、分页
# 分页,每页显示条数
list_per_page = 100
# 分页,显示全部(真实数据<该值时,才会有显示全部)
list_max_show_all = 200
# 分页插件
paginator = Paginator
2、list_editable,列表时,可以编辑的列
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
list_display = ('user', 'pwd','ug',)
list_editable = ('ug',)
3、date_hierarchy,列表时,对Date和DateTime类型进行搜索
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
date_hierarchy = 'ctime'
4、preserve_filters,详细页面,删除、修改,更新后跳转回列表后,是否保留原搜索条件
5、save_as = False,详细页面,按钮为“Sava as new” 或 “Sava and add another”
save_as_continue = True
# 如果 save_as=True,save_as_continue = True, 点击Sava as new 按钮后继续编辑。
# 如果 save_as=True,save_as_continue = False,点击Sava as new 按钮后返回列表。
6、save_on_top = False,详细页面,在页面上方是否也显示保存删除等按钮
7、inlines,详细页面,如果有其他表和当前表做FK,那么详细页面可以进行动态增加和删除
class UserInfoInline(admin.StackedInline): # TabularInline
extra = 0
model = models.UserInfo
class GroupAdminMode(admin.ModelAdmin):
list_display = ('id', 'title',)
inlines = [UserInfoInline, ]
8、raw_id_fields,详细页面,针对FK和M2M字段变成以Input框形式
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
raw_id_fields = ('FK字段', 'M2M字段',)
9、fields,详细页面时,显示字段的字段
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
fields = ('user',)
10、exclude,详细页面时,排除的字段
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
exclude = ('user',)
11、readonly_fields,详细页面时,只读字段
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
readonly_fields = ('user',)
12、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'),
}),
)
13、详细页面时,M2M显示时,数据移动选择(方向:上下和左右)
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
filter_vertical = ("m2m字段",) # 或filter_horizontal = ("m2m字段",)
14、view_on_site,编辑时,是否在页面上显示view on set
view_on_site = False
或
def view_on_site(self, obj):
return 'https://www.baidu.com'
15、radio_fields,详细页面时,使用radio显示选项(FK默认使用select)
radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL
16、show_full_result_count = True,列表时,模糊搜索后面显示的数据个数样式
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
# show_full_result_count = True # 1 result (12 total)
# show_full_result_count = False # 1 result (Show all)
search_fields = ('user',)
17、formfield_overrides = {},详细页面时,指定现实插件
from django.forms import widgets
from django.utils.html import format_html
class MyTextarea(widgets.Widget):
def __init__(self, attrs=None):
# Use slightly better defaults than HTML's 20x2 box
default_attrs = {'cols': '40', 'rows': '10'}
if attrs:
default_attrs.update(attrs)
super(MyTextarea, self).__init__(default_attrs)
def render(self, name, value, attrs=None):
if value is None:
value = ''
final_attrs = self.build_attrs(attrs, name=name)
return format_html('<textarea {}>\r\n{}</textarea>',final_attrs, value)
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
formfield_overrides = {
models.models.CharField: {'widget': MyTextarea},
}
18、prepopulated_fields = {},添加页面,当在某字段填入值后,自动会将值填充到指定字段。
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
prepopulated_fields = {"email": ("user","pwd",)}
PS: DjangoAdmin中使用js实现功能,页面email字段的值会在输入:user、pwd时自动填充
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
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 = "指定列数据为空时,默认显示"
转载于:https://blog.51cto.com/qidian510/2128520