目录
signals 1
middleware 2
i18n 3
settings 4
django默认的缓存机制: 5
signals
Django的signal可理解为django内部的钩子,当一个事件发生时,其他程序可对其作出相关反应,可通过signal来回调定义好的receivers处理函数,从而更大程度的解耦我们的系统;
使用场景,通知是常用的场景之一(如在论坛中,当帖子得到回复时通知楼主);
Django内置了对数据表|migrate命令|url请求相关|test测试|连接数据库,5大类信号;
Django定义了一系列信号,代码中可监听信号,收到信号后可触发一系列动作;
内置信号:
Model signals:
from django.db.models.signals import
pre_init, post_init # model执行构造方法前后触发
pre_save, post_save保存前(在调用model的save()方法前发送信号)、保存后(在调用model的save()方法后发送信号)
pre_delete, post_delete 删除前(在调用model的delete()方法前发送信号)、删除后(在调用model的delete()方法后发送信号)
m2m_changed #使用多对多字段操作第三张表前后触发
class_prepared # 程序启动时检测已注册的model类,对每个类触发
management signals:
pre_migrate, post_migrate # 执行migrate前后触发
request|response signals:
from django.core.signals import request_started, request_finished请求到来前触发|请求结束后触发
got_request_exception # 请求异常后触发
test signals:
setting_changed # 使用test测试修改配置文件触发
template_rendered # 使用test测试渲染模板时触发
database wrappers:
connection_created # 创建数据库连接时触发
内置信号参数:
django.db.models.signals.pre_save
sender # 模型类
instance # 保存的实际实例(保存后的model数据对象)
raw # 布尔值, True模型完全按提供的方式保存,不应该查询|修改数据库中的其他记录,因为数据库尚未处于一致状态
using # 正在使用的数据库别名
update_fields # 要传递给更新的字段集model.save(),或None如果update_fields未传递给它save()
django.db.models.signals.post_save
sender # 模型类
instance # 保存的实际实例
created # True表示数据创建
raw # 布尔值,True如果模型完全按提供的方式保存,不应该查询|修改数据库中的其它记录,因为数据库尚未处于一致状态
using #
update_fields #
django.db.models.signals.pre_delete
sender #
instance #
using #
django.db.models.signals.post_delete
sender #
instance # 要删除的实际实例,该对象不再存在于数据库中,请谨慎对待此实例
using #
使用方式:
1、手动连接:
from django.db.models.signals import post_delete
def my_callback(sender, **kwargs):
print(sender, '信号已接收')
post_delete.connect(my_callback) # 信号连接接收器,用于收到信号的回调
connect参数:
receiver # 将连接到此信号的回调函数,回调函数名
sender # 指定从中接收信号的特定发送方(如果想要指定某个表对象,直接指定sender)
weak # django默认将信号处理程序存储为弱引用,因此如果您的接收器是本地功能,它可能被垃圾收集,请weak=False在调用信号connect()方法时通过
dispatch_uid # 在可能发送重复信号的情况下信号接收器的唯一标识符
2、receiver装饰器
from django.dispatch import receiver
from django.db.models.signals import post_delete
from app.models import UCenter
@receiver(post_delete, sender=UCenter)
def delete_u2user(sender, instance, **kwargs):
print(sender, instance)
自定义信号使用:
from django.dispatch import Signal
test_signal = Signal(providing_args=['name', 'age']) # 定义信号,声明一个test_signal信号,提供给接收器2个参数
def my_callback(sender, **kwargs):
print(sender, '信号已接收')
test_signal.connect(my_callback) # 注册信号,指定接收器为my_callback
from xxx import test_signal
test_signal.send(sender='test', name='qq', age=18) # 触发信号,Signal.send()不能捕获由接收器提出的任何异常,它只是允许错误传播,因此在面对错误时不是所有接收器都可被通知信号;Signal.send_robust()捕获从python exception类派生的所有错误,并确保所有接收器都收到信号通知,如果发生错误则会在引发错误的接收器的元组对中返回错误实例
例(针对model的signal):
@receiver(post_save, sender=DbManage, dispatch_uid="DbManage_post_save")
def app_create_model_handler(sender, **kwargs):
'''
创建用户的时候创建用户操作日志
kwargs:
{ 'using': 'default', 'update_fields': None, 'instance': < Student: Student object >, 'raw': False,
'created': False, 'signal': < django.db.models.signals.ModelSignal object at0x7f8f48947400 >}
'''
created = kwargs['created']
instance = kwargs['instance']
if created:
# Student_Log.objects.create(action='create', name=instance.name)
# print('create action:%s ' % format(instance.name))
print('!!!create', instance.ip, instance.port)
else:
# Student_Log.objects.create(action='update', name=instance.name)
# print('update action:%s' % format(instance.name))
print('@@@update', instance.ip, instance.port)
@receiver(post_delete, sender=DbManage, dispatch_uid="DbManage_post_delete")
def student_delete_model_handler(sender, **kwargs):
'''
删除用户的时候创建用户操作日志
kwargs:
{'signal': <django.db.models.signals.ModelSignal object at 0x7f5156cf0550>,
'using': 'default', 'instance': <Student: Student object>}
'''
instance = kwargs['instance']
# Student_Log.objects.create(action='delete', name=instance.name)
print('delete action:%s' % format(instance.name))
例:
mysite/books/signals.py
def my_callback(sender, **kwargs):方式1
print('request finished')
request_finished.connect(my_callback)
@receiver(pre_save, sender=Publisher)方式2
def my_handler(sender, **kwargs):
print('do sth action')
mysite/books/apps.py
class BooksConfig(AppConfig):
name = 'books'
def ready(self):
from . import signals
输出:
>>> p = Publisher.objects.create(name='jowin',address='jowin',city='jowin',state_province='jowin',country='cn',website='test')
do sth action
[15/Jan/2019 14:11:27] "GET /favicon.ico HTTP/1.1" 404 2174
request finished
request finished
middleware
中间件是介于request与response处理之间的一道处理过程,用于在全局范围内改变Django的输入和输出。
简单的来说中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作
例如:
1.Django项目中默认启用了csrf保护,每次请求时通过CSRF中间件检查请求中是否有正确的token值;
2.当用户在页面上发送请求时,通过自定义的认证中间件,判断用户是否已经登陆,未登陆就去登陆;
3.当有用户请求过来时,判断用户是否在白名单或者在黑名单里;
https://docs.djangoproject.com/en/2.1/topics/http/middleware/
mysite/mysite/middlewares.py
import os
from django.http import HttpResponse
class DemoMiddleware:
IN_DEMO_MODE = os.environ.get('DEMO_MODE', False)
SAFE_METHOD = ('GET', 'HEAD')
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.method not in self.SAFE_METHOD:
return HttpResponse('in demo mode, only safe method only')
return self.get_response(request)
mysite/mysite/settings.py
MIDDLEWARE = [
'mysite.middlewares.DemoMiddleware',
i18n
mysite/mysite/settings.py
LANGUAGE_CODE = 'zh-CN'
LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale')]建mysite/locale/zh路径,不是py包
mysite/books/views.py
from django.utils.translation import ugettext as _
return HttpResponse(_('add successed'))
(webproject) C:\webproject\mysite>python manage.py makemessages生成翻译文件
mysite/locale/zh/LC_MESSAGES/django.po #编写翻译
#: .\books\views.py:49
msgid "add successed"
msgstr "你妹"
(webproject) C:\webproject\mysite>python manage.py compilemessages编译翻译文件
mysite/books/templates/books_add.html #模板中使用
{% load i18n %}
{% trans "add successed" %}
settings
ALLOWED_HOSTS = [] #在其它主机上部署,通过网络访问;DEBUG = False同时设置ALLOWED_HOSTS = ['*']
APPEND_SLASH = True #在请求的路径上自动加上/
CACHES = #使用的缓存,redis|memcached,默认用内存
DATABASES = [] #默认sqlite
DEBUG = True #默认开启,开发时自动reload,静态文件django提供serve
EMAIL_HOST
FIXTURE_DIRS = [os.path.join(BASE_DIR,’fixture’)] #DB初始化时提供数据
INSTALLED_APPS = [] #
LOGING =
MIDDLEWARE_CLASSES = []
SECRET_KEY = #项目中所有用到的加密都要此字串,如session
TEMPLATES = [] #
LOGIN_URL =
MEDIA_ROOT =
MEDIA_URL = #与用户上传文件有关
AUTH_USER_MODEL = “accounts/login”相关,AUTH_USER_MODEL = 'users.UserProfile'用自定义的模型
LOGIN_REDIRECT_URL = “/”
AUTHENTICATION_BACKENDS = [‘django.contrib.auth.backends.ModelBackend’] #插件,用于扩展,可用其它认证方式
LOGOUT_REDIRECT_URL = None
SESSION_COOKIE_AGE = 1209600
SESSION_COOKIE_DOMAIN = None #session在指定域名下生效
SESSION_COOKIE_PATH = “/”生效的路径,大项目用不同的路径区分
SESSION_COOKIE_NAME = “sessionid”
SESSION_ENGINE = “django.contrib.sessions.backends.db”可设为redis|memcached或文件,默认db
SESSION_EXPIRE_AT_BROWSER_CLOSE = False #用户browser关闭时,session过期
SESSION_FILE_PATH = None
STATIC_ROOT = “/var/www/html/example.com/static”静态文件在nginx的路径
STATIC_URL = “/static/”访问静态文件用到的url前缀
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),] #python manage.py collectstatic将此路径下的静态文件复制一份到STATIC_ROOT下;django仅在开发模式下能对外提供静态文件,DEBUG=False不再对外提供静态文件,需要用collectstatic命令来收集静态文件并交由其它静态文件服务器来提供
# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans'
# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
# USE_TZ = True使用国际时间
USE_TZ = False使用本地时间
django默认的缓存机制:
# 全站缓存
MIDDLEWARE_CLASSES = (
django.middleware.cache.UpdateCacheMiddleware’, #第一
'django.middleware.common.CommonMiddleware',
django.middleware.cache.FetchFromCacheMiddleware’, #最后
)
# 视图缓存
from django.views.decorators.cache import cache_page
import time
@cache_page(15) #超时时间为15秒
def index(request):
获取当前时间
return render(request,"index.html",locals())
# 模板缓存
{% load cache %}
不缓存:-----{{ t }}</h3>
{% cache 2 'name' %} #存的key
缓存:-----:{{ t }}</h3>
{% endcache %}
使用redis:
#1.安装 pip install django-redis
#2.在stting中配置CACHES,可以设置多个缓存,根据名字使用
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
#"CONNECTION_POOL_KWARGS": {"max_connections": 100}
密码",
}
}
},
另添加缓存
"JERD": { }
#3.根据名字去连接池中获取连接
from django_redis import get_redis_connection
conn = get_redis_connection("default")
python manage.py shell
from django.core.cache import cache
cache.set()
cache.has_key()
cache.get()