19 Jul 18
一、计划
1 CRM
stark组件(一周)
权限,CRM (3天)
2 路飞
restframework (2-3天)
vue-cli
luffy之支付系统,redis (一周)
3 爬虫
4 flask
5 linux
二、Django回顾
1 url控制器+MTV
2 Ajax
a. ContentType(详见item 7)
3 forms组件
4 cookie,session
def foo(request):
request.session["name"]="egon"
return balabala
5 用户认证组件
6 中间件
a. cookie/session 和url的中间件很重要,要看源码
7 ContentType (请求体的编码类型)(*******)
https://www.cnblogs.com/yuanchenqi/articles/9070966.html
a. application/x-www-form-urlencoded
1)在form和ajax提交POST请求时,如果不特意指定enctype(form)或contentType(ajax),默认使用的编码类型
2)请求体:user=yuan&age=22;浏览器在解析请求头时,查看到编码类型,然后在用该编码类型对应的请求体数据样式,将数据进行相应提取展示
3) 请求格式
"
POST /index HTTP/1.1
contentType:application/x-www-form-urlencoded
name=yuan&pwd=123
"
b. multipart/form-data
1) 使用表单上传文件时,必须让<form> 表单的enctype 等于multipart/form-data
c. text/plan
1) form表单只支持以上三种contentType(application/x-www-form-urlencoded,multipart/form-data,ext/plan),不支持application/json等
2) text/pam基本上不被使用
d. application/json
1) request.POST只解析application/x-www-form-urlencoded;即如果用application/json编码格式提交数据,print(request.POST)为空。
2)处理该情况,可以从request.body(为经处理的原始数据,bytes类型)中提取数据
e. 用ajax发送json数据时,两种处理数据的方式
1) 在html中用application/json这种contentType发送json格式数据,在views中从request.body中提取数据(解码,loads)
d=json.loads(request.body.decode("utf8"))
2)在html中依据用默认的contentType(application/x-www-form-urlencoded)发送数据,但做如下处理
data:{xxx:JSON.stringify({a:1,b:2})},
8 如果有传来多个数据(checkbox,select multiple),用getlist取出相应数据
a. checkbox
<input type="text" name="user" value="yuan">
<input type="checkbox" name="hobby" value="1"> 篮球
<input type="checkbox" name="hobby" value="2"> 足球
<input type="checkbox" name="hobby" value="3"> 彩色球
b. select multiple
<select multiple name="xxx">
<option value="1">111</option>
<option value="2">222</option>
<option value="3">333</option>
</select>
c. 请求体格式
user=yuan&hobby=[1,2,3]&xxx=[1,2,3]
d. 在Django的views中取出相应数据
request.POST.get("user")
request.POST.getlist("hobby")
9 Others
a. Django中response的一定是HttpResponse中的一类(HttpResponse,JsonResponse,render,redirect)
b. Django一般比较适合大项目,而flask一般比较适合小精型项目
c. request.meta :封装了请求头信息的字典
d. wsgiref, 收发消息;将字符串封装成request对象,将response对象转换成字符串
e. 浏览器只能识别HTML, CSS, JS
三、admin的使用
https://www.cnblogs.com/yuanchenqi/articles/8323452.html
1 Admin:Django下的后台数据管理的web页面
# 每个注册过的表对应四个url
http://127.0.0.1:8000/admin/app01/publish/
http://127.0.0.1:8000/admin/app01/publish/add/
http://127.0.0.1:8000/admin/app01/publish/1/change/
http://127.0.0.1:8000/admin/app01/publish/1/delete/
2 admin的定制
a 方法
1) 方法一
class UserAdmin(admin.ModelAdmin):
list_display = ('user', 'pwd',)
admin.site.register(models.UserInfo, UserAdmin) # 第一个参数可以是列表
2)方法二
@admin.register(models.UserInfo) # 第一个参数可以是列表
class UserAdmin(admin.ModelAdmin):
list_display = ('user', 'pwd',)
b 可定制的功能
1)list_display: 列表时,定制显示的列。
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
list_display = ('user', 'pwd', 'xxxxx')
def xxxxx(self, obj):
return "xxxxx"
2)list_display_links:列表时,定制列可以点击跳转。
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
list_display = ('user', 'pwd', 'xxxxx')
list_display_links = ('pwd',)
3)list_filter:列表时,定制右侧快速筛选。
# 一般用于一对多或多对多关系中
4)list_select_related:列表时,连表查询是否自动select_related
5)list_editable:列表时,可以编辑的列
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
list_display = ('user', 'pwd','ug',)
list_editable = ('ug',)
6)search_fields:列表时,模糊搜索的功能
#列表中可以排多个值,是一种或的关系
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
search_fields = ('user', 'pwd')
7)date_hierarchy:列表时,对Date和DateTime类型进行搜索
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
date_hierarchy = 'ctime'
8)inlines:详细页面,如果有其他表和当前表做FK,那么详细页面可以进行动态增加和删除
class UserInfoInline(admin.StackedInline): # TabularInline
extra = 0
model = models.UserInfo
class GroupAdminMode(admin.ModelAdmin):
list_display = ('id', 'title',)
inlines = [UserInfoInline, ]
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
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
11)raw_id_fields:详细页面,针对FK和M2M字段变成以Input框形式
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
raw_id_fields = ('FK字段', 'M2M字段',)
12)fields:详细页面时,显示字段的字段
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
fields = ('user',)
13)exclude:详细页面时,排除的字段
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
exclude = ('user',)
14)readonly_fields:详细页面时,只读字段
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
readonly_fields = ('user',)
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'),
}),
)
16)详细页面时,M2M显示时,数据移动选择(方向:上下和左右)
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
filter_vertical = ("m2m字段",) # 或filter_horizontal = ("m2m字段",)
17)ordering:列表时,数据排序规则
@admin.register(models.UserInfo)
class UserAdmin(admin.ModelAdmin):
ordering = ('-id',)
或
def get_ordering(self, request):
return ['-id', ]
18)radio_fields:详细页面时,使用radio显示选项(FK默认使用select)
radio_fields = {"ug": admin.VERTICAL} # 或admin.HORIZONTAL
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 = "指定列数据为空时,默认显示"
四、admin的源码
https://www.cnblogs.com/yuanchenqi/articles/8323452.html
1 复习单例
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。
比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个AppConfig 的类来读取配置文件的信息。如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建AppConfig 对象的实例,这就导致系统中存在多个AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。事实上,类似AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
在Python 中,我们可以用多种方法来实现单例模式:
a 使用__new__
class Singleton(object):
_instance = None
def __new__(cls, *args, **kw):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
return cls._instance
class MyClass(Singleton):
a = 1
b 使用装饰器(decorator)
import settings
def singleton(cls): #cls=Mysql
_instance=cls(settings.HOST,settings.PORT)
def wrapper(*args,**kwargs):
if args or kwargs:
obj=cls(*args,**kwargs)
return obj
return _instance
return wrapper
@singleton # Mysql=singleton(Mysql)
class Mysql:
def __init__(self,host,port):
self.host=host
self.port=port
obj1=Mysql()
obj2=Mysql()
obj3=Mysql()
print(obj1 is obj2 is obj3) #True
obj4=Mysql('1.1.1.3',3307)
obj5=Mysql('1.1.1.4',3308)
print(obj3 is obj4) #False
c 使用元类(metaclass)
import settings
class Mymeta(type):
def __init__(self,name,bases,dic): #定义类Mysql时就触发
# 事先先从配置文件中取配置来造一个Mysql的实例出来
self.__instance = object.__new__(self) # 产生对象
self.__init__(self.__instance, settings.HOST, settings.PORT) # 初始化对象
# 上述两步可以合成下面一步
# self.__instance=super().__call__(*args,**kwargs)
super().__init__(name,bases,dic)
def __call__(self, *args, **kwargs): #Mysql(...)时触发
if args or kwargs: # args或kwargs内有值
obj=object.__new__(self)
self.__init__(obj,*args,**kwargs)
return obj
return self.__instance
class Mysql(metaclass=Mymeta):
def __init__(self,host,port):
self.host=host
self.port=port
obj1=Mysql() # 没有传值则默认从配置文件中读配置来实例化,所有的实例应该指向一个内存地址
obj2=Mysql()
obj3=Mysql()
print(obj1 is obj2 is obj3)
obj4=Mysql('1.1.1.4',3307)
d 定义一个类方法实现单例模式
import settings
class Mysql:
__instance=None
def __init__(self,host,port):
self.host=host
self.port=port
@classmethod
def singleton(cls):
if not cls.__instance:
cls.__instance=cls(settings.HOST,settings.PORT)
return cls.__instance
obj1=Mysql('1.1.1.2',3306)
obj2=Mysql('1.1.1.3',3307)
print(obj1 is obj2) #False
obj3=Mysql.singleton()
obj4=Mysql.singleton()
print(obj3 is obj4) #True
e 使用模块
Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成.pyc 文件,当第二次导入时,就会直接加载.pyc 文件,而不会再次执行模块代码。
因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做:
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton()
# 使用
from mysingleton import my_singleton
my_singleton.foo()
注意:
1)在同一django中的不同py文件中导入变量my_singleton为同一单例
2)在同一django中的不同py文件中导入类My_singleton为同一个类,但调用其产生的对象为不同的对象
2 复习类/对象中属性的查找
3 启动
循环加载执行所有已经注册的app中的admin.py文件
def autodiscover():
autodiscover_modules('admin', register_to=site)
4 注册(*******)
class AdminSite(object):
def __init__(self, name='admin'):
self._registry = {}
def register(self, model_or_iterable, admin_class=None, **options):
if not admin_class:
admin_class = ModelAdmin # 配置类
self._registry[model] = admin_class(model, self)
# {Book:BookConfig(Book),Publish:ModelAdmin(Publish)}
site=AdminSite() # 对于AdminSite类的一个单例模式,执行的每一个app中的每一个admin.site都是一个对象
-----------------------------------------
class BookConfig(ModelAdmin):
list_display=["",]
admin.site.register(Book,BookConfig) # Book在app01中
admin.site.register(Publish) # Publish在app02中;按照注册顺序,先执行app01中的admin,再执行app02中的admin
-----------------------------------------
print(admin.site._registry)
{
<class 'django.contrib.auth.models.Group'>: <django.contrib.auth.admin.GroupAdmin object at 0x00000256B97EF9E8>,
<class 'django.contrib.auth.models.User'>: <django.contrib.auth.admin.UserAdmin object at 0x00000256B9825438>,
<class 'app01.models.Book'>: <app01.admin.BookConfig object at 0x00000256B983C080>,
<class 'app01.models.Publish'>: <app01.admin.PublishConfig object at 0x00000256B983C128>
}
# 两个django自带的键值对,外加两个app中各自注册的键值对(model:对应配置类的对象)