今日概要:

  1、form表单进阶

  2、中间件

3、缓存

4、信号

5、admin后台

上节课回顾

    FBV,CBV
序列化
- Django内置
- json.dumps(xxx,cls=)
Form验证
- 类
class LoginForm(Form):
user = fields.CharField(...)
email = fields.EmailField(...)
email = fields.ChoiceField(
choices=[()..]
)
- 添加用户: GET
form = LoginForm() {{form.user}} <input type='text' name='user' /> 等待用户输入内容,提交 - 添加用户: POST
form = LoginForm(data=request.POST)
form.is_valid()
form.cleaned_data
form.errors - 修改用户: GET /edit/9
obj = models.User.objects.get(id=9) form = LoginForm(initial={'user':obj.user}) {{form.user}} <input type='text' name='user' value='数据库中的用户名' /> 等待用户输入内容,提交 - 修改用户: POST /edit/9
form = LoginForm(data=request.POST)
form.is_valid()
form.cleaned_data
models.User.objects.filter(id=9).update(**form.cleaned_data)
form.errors - 补充:可以显示select,但是数据无法实时更新
class LoginForm(Form):
user = fields.CharField(...)
email = fields.EmailField(...)
hobby = fields.ChoiceField(
choices=[()..]
) def __init__(self,*args,**kwargs):
super..
self.fields['hobby'].choices = ....

上节回顾

一、Form表单进阶

  创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

  1、Django内置字段如下:

Field
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成Label标签或显示内容
initial=None, 初始值
help_text='', 帮助信息(在标签旁边显示)
error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'}
show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直)
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None Label内容后缀 CharField(Field)
max_length=None, 最大长度
min_length=None, 最小长度
strip=True 是否移除用户输入空白 IntegerField(Field)
max_value=None, 最大值
min_value=None, 最小值 FloatField(IntegerField)
... DecimalField(IntegerField)
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度 BaseTemporalField(Field)
input_formats=None 时间格式化 DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 DurationField(Field) 时间间隔:%d %H:%M:%S.%f
... RegexField(CharField)
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'} EmailField(CharField)
... FileField(Field)
allow_empty_file=False 是否允许空文件 ImageField(FileField)
...
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
- form表单中 enctype="multipart/form-data"
- view函数中 obj = MyForm(request.POST, request.FILES) URLField(Field)
... BooleanField(Field)
... NullBooleanField(BooleanField)
... ChoiceField(Field)
...
choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),)
required=True, 是否必填
widget=None, 插件,默认select插件
label=None, Label内容
initial=None, 初始值
help_text='', 帮助提示 ModelChoiceField(ChoiceField)
... django.forms.models.ModelChoiceField
queryset, # 查询数据库中的数据
empty_label="---------", # 默认空显示内容
to_field_name=None, # HTML中value的值对应的字段
limit_choices_to=None # ModelForm中对queryset二次筛选 ModelMultipleChoiceField(ModelChoiceField)
... django.forms.models.ModelMultipleChoiceField TypedChoiceField(ChoiceField)
coerce = lambda val: val 对选中的值进行一次转换
empty_value= '' 空值的默认值 MultipleChoiceField(ChoiceField)
... TypedMultipleChoiceField(MultipleChoiceField)
coerce = lambda val: val 对选中的每一个值进行一次转换
empty_value= '' 空值的默认值 ComboField(Field)
fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field)
PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField)
input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
required=True,
widget=None,
label=None,
initial=None,
help_text='' GenericIPAddressField
protocol='both', both,ipv4,ipv6支持的IP格式
unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用 SlugField(CharField) 数字,字母,下划线,减号(连字符)
... UUIDField(CharField) uuid类型
...

内置字段

 

  注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串

>>> import uuid

    # make a UUID based on the host ID and current time
>>> uuid.uuid1() # doctest: +SKIP
UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') # make a UUID using an MD5 hash of a namespace UUID and a name
>>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') # make a random UUID
>>> uuid.uuid4() # doctest: +SKIP
UUID('16fd2706-8baf-433b-82eb-8c7fada847da') # make a UUID using a SHA-1 hash of a namespace UUID and a name
>>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d') # make a UUID from a string of hex digits (braces and hyphens ignored)
>>> x = uuid.UUID('{00010203-0405-0607-0809-0a0b0c0d0e0f}') # convert a UUID to a string of hex digits in standard form
>>> str(x)
'00010203-0405-0607-0809-0a0b0c0d0e0f' # get the raw 16 bytes of the UUID
>>> x.bytes
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f' # make a UUID from a 16-byte string
>>> uuid.UUID(bytes=x.bytes)
UUID('00010203-0405-0607-0809-0a0b0c0d0e0f')

uuid

  2、Django内置插件:

TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget

内置插件

常用选择插件 

# 单radio,值为字符串
# user = fields.CharField(
# initial=2,
# widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),))
# ) # 单radio,值为字符串
# user = fields.ChoiceField(
# choices=((1, '上海'), (2, '北京'),),
# initial=2,
# widget=widgets.RadioSelect
# ) # 单select,值为字符串
# user = fields.CharField(
# initial=2,
# widget=widgets.Select(choices=((1,'上海'),(2,'北京'),))
# ) # 单select,值为字符串
# user = fields.ChoiceField(
# choices=((1, '上海'), (2, '北京'),),
# initial=2,
# widget=widgets.Select
# ) # 多选select,值为列表
# user = fields.MultipleChoiceField(
# choices=((1,'上海'),(2,'北京'),),
# initial=[1,],
# widget=widgets.SelectMultiple
# ) # 单checkbox
# user = fields.CharField(
# widget=widgets.CheckboxInput()
# ) # 多选checkbox,值为列表
# user = fields.MultipleChoiceField(
# initial=[2, ],
# choices=((1, '上海'), (2, '北京'),),
# widget=widgets.CheckboxSelectMultiple
# )

常用选择插件

   注意:写默认值时,多选值对应列表 form = RegisterForm(initial={'city':[1,2],'name':'alex'})

  在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

  1、方式一

from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator class MyForm(Form): user = fields.ChoiceField(
# choices=((1, '上海'), (2, '北京'),),
initial=2,
widget=widgets.Select
) def __init__(self, *args, **kwargs): #数据循环会先存到feilds里以key,value形式
super(MyForm,self).__init__(*args, **kwargs)
# self.fields['user'].widget.choices = ((1, '上海'), (2, '北京'),)
# 或
self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id','caption')

  2、方式二

    使用django提供的ModelChoiceField和ModelMultipleChoiceField字段来实现

from django import forms
from django.forms import fields
from django.forms import widgets
from django.forms import models as form_model
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator class FInfo(forms.Form):
authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())
# authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())

自定义验证规则:

   django的form十分强大,提供了自定义接口

   1、基于对象的方法:      

from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator class MyForm(Form):
user = fields.CharField(
validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
)

  2、基于函数的验证

import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError # 自定义验证规则
def mobile_validate(value):
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
if not mobile_re.match(value):
raise ValidationError('手机号码格式错误') #raise抛出异常form就会捕获 class PublishForm(Form): title = fields.CharField(max_length=20,
min_length=5,
error_messages={'required': '标题不能为空',
'min_length': '标题最少为5个字符',
'max_length': '标题最多为20个字符'},
widget=widgets.TextInput(attrs={'class': "form-control",
'placeholder': '标题5-20个字符'})) # 使用自定义验证规则
phone = fields.CharField(validators=[mobile_validate, ],
error_messages={'required': '手机不能为空'},
widget=widgets.TextInput(attrs={'class': "form-control",
'placeholder': u'手机号码'})) email = fields.EmailField(required=False,
error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))

  注:定义的phone字段,不要在phone函数里去处理其他字段的逻辑,因为有可能到phone的时候,还未添加到字典里,数值为空,会有异常

  3、clean_字段名称 方法   

from django import forms
from django.forms import fields
from django.forms import widgets
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator class FInfo(forms.Form):
username = fields.CharField(max_length=5,
validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], )
email = fields.EmailField() def clean_username(self):
"""
Form中字段中定义的格式匹配完之后,执行此方法进行验证
:return:
"""
value = self.cleaned_data['username']
if "666" in value:
raise ValidationError('666已经被玩烂了...', 'invalid')
return value

  验证手机规则例子: 

    def clean_phone(self):
""" :return: 必须有返回值,
"""
# 去取用户提交的值:可能是错误的,可能是正确
value = self.cleaned_data['phone']
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
if not mobile_re.match(value):
raise ValidationError('手机号码格式错误') if models.UserInfo.objects.filter(phone=value).count():
raise ValidationError('手机号码已经存在') return value

 验证规则执行顺序:

    第一个字段的正则,钩子函数(方法中只能取当前字段的值)

    第二个字段的正则,钩子函数

    整体验证: clean,必须有返回值,   给指定字段添加错误信息

class RegisterForm(Form):
name = fields.CharField()
email = fields.EmailField()
phone = fields.CharField()
pwd = fields.CharField()
pwd_confirm = fields.CharField() def clean(self):
pwd = self.cleaned_data['pwd']
pwd_confirm = self.cleaned_data['pwd_confirm']
if pwd == pwd_confirm:
return self.cleaned_data
else:
from django.core.exceptions import ValidationError
# self.add_error('pwd', ValidationError('密码输入不一致'))
self.add_error('pwd_confirm', ValidationError('密码输入不一致'))
return self.cleaned_data

  4、同时生成多个标签进行验证

from django.forms import Form
from django.forms import widgets
from django.forms import fields from django.core.validators import RegexValidator ############## 自定义字段 ##############
class PhoneField(fields.MultiValueField):
def __init__(self, *args, **kwargs):
# Define one message for all fields.
error_messages = {
'incomplete': 'Enter a country calling code and a phone number.',
}
# Or define a different message for each field.
f = (
fields.CharField(
error_messages={'incomplete': 'Enter a country calling code.'},
validators=[
RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'),
],
),
fields.CharField(
error_messages={'incomplete': 'Enter a phone number.'},
validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')],
),
fields.CharField(
validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')],
required=False,
),
)
super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False, *args,
**kwargs) def compress(self, data_list):
"""
当用户验证都通过后,该值返回给用户
:param data_list:
:return:
"""
return data_list ############## 自定义插件 ##############
class SplitPhoneWidget(widgets.MultiWidget):
def __init__(self):
ws = (
widgets.TextInput(),
widgets.TextInput(),
widgets.TextInput(),
)
super(SplitPhoneWidget, self).__init__(ws) def decompress(self, value):
"""
处理初始值,当初始值initial不是列表时,调用该方法
:param value:
:return:
"""
if value:
return value.split(',')
return [None, None, None]

二、中间件middleware

  Django本身就带middleware功能:

    如下是django的生命周期

  

  如下为中间件的执行顺序

    

  - 中间件执行时机:请求到来,请求返回时
  - 中间件是一个类:
  def process_request(self,request):
    print('m2.process_request')

  def process_response(self,request, response):
    print('m2.prcess_response')
    return response

    - 应用:
    - 请求日志
    - 用户登录认证

#!/usr/bin/python
# -*- coding:utf-8 -*- # from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,redirect
class MiddlewareMixin(object):
def __init__(self, get_response=None):
self.get_response = get_response
super(MiddlewareMixin, self).__init__() def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response class m1(MiddlewareMixin):
'''先执行request,然后到url路由,url之后返回到最上方,在执行view,如果出现错误就直接到response上,执行完,到真正到视图,如果有问题就
执行exception,从下至上查找,如果找到exception就直接执行exception的return在走response返回用户
每个中间件中,4个方法不需要都写.
'''
# def process_request(self,request): #登录验证可以放在中间件里
# if request.path_info == '/userinfo/':
# return None
# if not request.session.get('user_info'):
# return redirect('/userinfo/')
def process_request(self,request):
print('m1.process_request') def process_response(self,request,response):
print('m1.process_response')
return response
def process_view(self,request,callback,callback_args,callback_kwargs):
print('m1.process_view',callback) def process_exception(self,request,exception):
print('m1.exception') class m2(MiddlewareMixin):
def process_request(self,request):
print('m2.process_request') def process_response(self,request,response):
print('m2.process_response')
return response
def process_view(self,request,callback,callback_args,callback_kwargs):
print('m2.process_view',callback) def process_exception(self,request,exception):
print('m2.exception')
return HttpResponse('500 Error')

  注:新的django版本可能不存在MiddlewareMixin,需要手动写一下这个类进行继承

  settings里配置:

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'md.middleware.m1',
'md.middleware.m2',
]

三、缓存 

- 配置
- 开发调试
- 内存中 全局变量
- 文件中
- 数据库
- Memcached
- 使用
- 全局
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
# 其他中间件
'django.middleware.cache.FetchFromCacheMiddleware',
]
- 视图函数 from django.views.decorators.cache import cache_page @cache_page(10)
def test1(request):
import time
ctime = time.time()
return render(request,'test1.html',{'ctime':ctime})
- 局部模板
{% load cache %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>TEST1 -> {{ ctime }}</h1> {% cache 10 "asdfasdfasdf" %}
<h1>TEST1 -> {{ ctime }}</h1>
{% endcache %}
</body>
</html>

  由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

  1、配置

    a、开发调试  

# 此为开始调试用,实际内部不做任何操作
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎
'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
'OPTIONS':{
'MAX_ENTRIES': 300, # 最大缓存个数(默认300)
'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
},
'KEY_PREFIX': '', # 缓存key的前缀(默认空)
'VERSION': 1, # 缓存key的版本(默认1)
'KEY_FUNCTION' 函数名 # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
}
} # 自定义key
def default_key_func(key, key_prefix, version):
"""
Default function to generate keys. Constructs the key used by all other methods. By default it prepends
the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
function with custom key making behavior.
"""
return '%s:%s:%s' % (key_prefix, version, key) def get_key_func(key_func):
"""
Function to decide which key function to use. Defaults to ``default_key_func``.
"""
if key_func is not None:
if callable(key_func):
return key_func
else:
return import_string(key_func)
return default_key_func

开发调试

     b、内存

# 此缓存将内容保存至内存的变量中
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
} # 注:其他配置同开发调试版本

c、文件

# 此缓存将内容保存至文件
# 配置: CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}
# 注:其他配置同开发调试版本

d、数据库

# 此缓存将内容保存至数据库

    # 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table', # 数据库表
}
} # 注:执行创建表命令 python manage.py createcachetable

e、Memcache缓存(python-memcached模块)

# 此缓存使用python-memcached模块连接memcache

    CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'unix:/tmp/memcached.sock',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
}
}

    f、Memcache缓存(pylibmc模块)

# 此缓存使用pylibmc模块连接memcache

    CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '/tmp/memcached.sock',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
}
}

    h、redis的可以去网上找插件,pip install django-redis  

CACHES = {
'default': {
'BACKEND': 'redis_cache.cache.RedisCache',
'LOCATION': '127.0.0.1:6379',
"OPTIONS": {
"CLIENT_CLASS": "redis_cache.client.DefaultClient",
},
},
}
REDIS_TIMEOUT=7*24*60*60
CUBES_REDIS_TIMEOUT=60*60
NEVER_REDIS_TIMEOUT=365*24*60*60

  2、应用

    a、全站使用:   

使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存

    MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
# 其他中间件...
'django.middleware.cache.FetchFromCacheMiddleware',
] CACHE_MIDDLEWARE_ALIAS = ""
CACHE_MIDDLEWARE_SECONDS = ""
CACHE_MIDDLEWARE_KEY_PREFIX = ""

    b、单独视图缓存

方式一:
from django.views.decorators.cache import cache_page @cache_page(60 * 15)
def my_view(request):
... 方式二:
from django.views.decorators.cache import cache_page urlpatterns = [
url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
]

    c、局部视图

a. 引入TemplateTag

        {% load cache %}

    b. 使用缓存

        {% cache 5000 缓存key %}
缓存内容
{% endcache %}

四、信号

  1、应用场景,当遇比如要所有数据库在创建数据的时候,记录一条日志

  Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

Django内置信号  

Model signals
pre_init # django的modal执行其构造方法前,自动触发
post_init # django的modal执行其构造方法后,自动触发
pre_save # django的modal对象保存前,自动触发
post_save # django的modal对象保存后,自动触发
pre_delete # django的modal对象删除前,自动触发
post_delete # django的modal对象删除后,自动触发
m2m_changed # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
pre_migrate # 执行migrate命令前,自动触发
post_migrate # 执行migrate命令后,自动触发
Request/response signals
request_started # 请求到来前,自动触发
request_finished # 请求结束后,自动触发
got_request_exception # 请求异常后,自动触发
Test signals
setting_changed # 使用test测试修改配置文件时,自动触发
template_rendered # 使用test测试渲染模板时,自动触发
Database Wrappers
connection_created # 创建数据库连接时,自动触发

  对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

from django.core.signals import request_finished
from django.core.signals import request_started
from django.core.signals import got_request_exception from django.db.models.signals import class_prepared
from django.db.models.signals import pre_init, post_init
from django.db.models.signals import pre_save, post_save
from django.db.models.signals import pre_delete, post_delete
from django.db.models.signals import m2m_changed
from django.db.models.signals import pre_migrate, post_migrate from django.test.signals import setting_changed
from django.test.signals import template_rendered from django.db.backends.signals import connection_created def callback(sender, **kwargs):
print("xxoo_callback")
print(sender,kwargs) xxoo.connect(callback)
# xxoo指上述导入的内容

  views里写法:

from django.core.signals import request_finished
from django.dispatch import receiver @receiver(request_finished)
def my_callback(sender, **kwargs):
print("Request finished!")

  2、自定义信号

     a、定义信号    

import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

      b、注册信号      

def callback(sender, **kwargs):
print("callback")
print(sender,kwargs) pizza_done.connect(callback)

      c、触发信号:

from 路径 import pizza_done

pizza_done.send(sender='seven',toppings=123, size=456)

五、Admin后台

  http://www.cnblogs.com/liujiliang/p/7580715.html

 

  

    

       

python自动化开发-[第二十一天]-form验证,中间件,缓存,信号,admin后台的更多相关文章

  1. python自动化开发-[第二十天]-form表单,CBV和FBV,序列化

    1.CBV和FBV的用法 2.序列化用法 3.form表单 一.CBV和FBV 1.cbv是 class based view(基于类),fbv是function based view(基于函数) 2 ...

  2. python自动化开发学习 进程, 线程, 协程

    python自动化开发学习 进程, 线程, 协程   前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...

  3. python自动化开发学习 I/O多路复用

    python自动化开发学习 I/O多路复用   一. 简介 socketserver在内部是由I/O多路复用,多线程和多进程,实现了并发通信.IO多路复用的系统消耗很小. IO多路复用底层就是监听so ...

  4. Python Django的分页,Form验证,中间件

    本节内容 Django的分页 Form 中间件 1 Django 分页 1.1 Django自带的分页 1.首先来看下我的测试数据环境 ############ models.py ######### ...

  5. Python自动化开发 - Django【进阶篇】

    Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...

  6. Python自动化开发 - Django【基础篇】

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为: 大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能 ...

  7. Django——12 中间件 上下文处理器 admin后台

    Django 中间件 中间件介绍 中间件的第一个例子 中间件的第二个例子 上下文处理器 admin后台管理   中间件 Django中间件(Middleware)是一个轻量级.底层的“插件”系统,可以 ...

  8. Python自动化开发学习20-Django的form组件

    武沛齐老师的Django的FORM组件:http://www.cnblogs.com/wupeiqi/articles/6144178.html 转自:http://blog.51cto.com/st ...

  9. Python自动化开发-简介

    1.Python简介 Python创始人  Guido Van Rossum,人称"龟叔",1989年圣诞节期间,为了在阿姆斯特丹打发时间,开发的一个新的脚本解释程序 作为ABC语 ...

随机推荐

  1. codeforces559B

    Equivalent Strings CodeForces - 559B Today on a lecture about strings Gerald learned a new definitio ...

  2. HTML5获取地理位置信息

    <!DOCTYPE html> <html> <head> <title>Location</title> <meta charset ...

  3. 最简单的Spring Security配置示例

    代码结构: pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&qu ...

  4. 安卓Android基础第五天

    使用HttpUrlConnection方式提交到服务器2 Get方式:组拼url地址把数据组拼到url上,有大小限制1kb(浏览器)或4kb(http协议) Post方式:post方式提交安全,没有大 ...

  5. git回滚部分文件到某个版本

    reset 命令只能将整个版本的代码一起回滚,需要使用checkout 命令,可以还原部分文件到某一版本 格式为:git checkout [<branch>] [file] 1.首先使用 ...

  6. Hdoj 2454.Degree Sequence of Graph G 题解

    Problem Description Wang Haiyang is a strong and optimistic Chinese youngster. Although born and bro ...

  7. 自学华为IoT物联网_02 常见物联网通信技术

    点击返回自学华为IoT物流网 自学华为IoT物联网_02 常见物联网通信技术 两类技术: 有线通信技术 无线通信技术 一. 有线通信技术 1.1 物联网有线技术介绍及对比 ETH 主要用于支持以太网标 ...

  8. 【BZOJ3561】DZY Loves Math VI (数论)

    [BZOJ3561]DZY Loves Math VI (数论) 题面 BZOJ 题解 \[\begin{aligned} ans&=\sum_{i=1}^n\sum_{j=1}^m\sum_ ...

  9. BUG关闭原因

    已解决:缺陷已经修复. 重复缺陷:是指在系统里相同原因的缺陷已经被其他人报告.在此缺陷被作为重复缺陷返回时,先不要立即取消.必须等到核查修复后,才在系统里取消.这是因为有些缺陷被误认为是重复缺陷,实际 ...

  10. CCCC 喊山

    2016年天梯赛模拟&初赛题集(nwu) 编程题30小题,共计580分 580分 编程题 5-14 喊山   (30分) 喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂…… ...