Django 温故
HTTP Objects
- HttpRequest
- 自身属性
- request.path ->
/foo/bar/
- request.method ->
POST
,GET
- 类字典属性(QueryDict)
- request.GET
- request.POST
- request.COOKIES
- request.FILES ->
{name1: file1, name2: file2, ...}
- request.META[‘REMOTE_ADDR’]
- request.META[‘HTTP_USER_AGENT’]
- request.path ->
- 中间件添加的属性
- request.session
- request.user
- 方法
- request.get_full_path() ->
/foo/bar/?a=123
- request.get_signed_cookie(key)
- request.get_full_path() ->
- 自身属性
- HttpResponse
- 属性
- response.status_code
- response.content
- 方法
- response.set_cookie(key, value, max_age=None)
- 属性
- JsonResponse
response = JsonResponse({'a': 12, 'b': 'xyz'})
Django 中间件
-
面向切片编程
-
最简单的中间件
def simple_middleware(get_response): # do_something_for_init() def middleware(request): # do_something_before_views() response = get_response(request) # views 函数在这里执行 # do_something_after_views() return response return middleware
-
中间件类
class MyMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response def process_view(self, request, view_func, view_args, view_kwargs): pass
-
Django-1.10 以前的中间件
from django.utils.deprecation import MiddlewareMixin class MyMiddleware(MiddlewareMixin): def process_request(self, request): pass def process_view(self, request, view_func, view_args, view_kwargs): pass def process_response(self, request, response): return response
-
执行顺序
- process_request, process_view 从上往下执行
- process_response 从下往上执行
Form 表单
-
核心功能:数据验证
-
form 的 method 只能是 POST 或 GET
-
method=GET 时, 表单提交的参数会出现在 URL 里
-
属性和方法
form.is_valid()
form.has_changed()
form.clean_<field>()
form.cleaned_data['fieldname']
-
Form 的定义和使用
from django.forms import Form from django.forms import IntegerField, CharField, DateField, ChoiceField class TestForm(Form): TAGS = ( ('py', 'python'), ('ln', 'linux'), ('dj', 'django'), ) fid = IntegerField() name = CharField(max_length=10) tag = ChoiceField(choices=TAGS) date = DateField() data = {'fid': 'abc123', 'name': '1234567890', 'tag': 'dj', 'date': '2017-12-17'} form = TestForm(data) print(form.is_valid()) print(form.cleaned_data) # cleaned_data 属性是 is_valid 函数执行时动态添加的 print(form.errors)
-
ModelForm
class UserForm(ModelForm): class Meta: model = User fields = ['name', 'birth']
模板
-
base.html 模板推荐布局
[外链图片转存失败(img-KRSXUYsE-1564220387292)(…/…/…/…/…/%E5%8D%83%E9%94%8Bpython/%E7%AC%AC%E5%9B%9B%E5%A4%A7%E9%98%B6%E6%AE%B5/python%E9%A1%B9%E7%9B%AE%E5%91%A8/%E8%AF%BE%E4%BB%B6/00-swiper-doc/img/layout.jpg)]
<!DOCTYPE html> <html> <head> <title>{{title}}</title> <link rel="stylesheet" type="text/css" href="/static/css/style.css"> {% block "ext_css" %}{% endblock %} </head> <body> <!-- {% block "navbar" %}{% endblock %} --> {% block "sidebar" %}{% endblock %} {% block "content" %}{% endblock %} <!-- {% block "foot" %}{% endblock %} --> {% block "ext_js" %}{% endblock %} </body> </html>
-
-
csrf_token
<form> {% csrf_token %} <input type="text" name="x" value="123"> </form>
-
for...endfor
中的变量forloop.counter
从 1 开始计数forloop.counter0
从 0 开始计数forloop.revcounter
逆序计数到 1forloop.revcounter0
逆序计数到 0forloop.first
是否是循环中的第一个forloop.last
是否是循环中的最后一个forloop.parentloop
用于引用上级循环中的变量, 如{{ forloop.parentloop.counter }}
-
empty 子句
{% for x in lst %} <div>...</div> {% empty %} <div>Sorry</div> {% endfor %}
-
load: 加载自定义 Tag
{% load foo.bar %}
-
url: 根据 url name 替换
{% url 'your-url-name' v1 v2 %}
-
static
{% load static %} <img src="{% static "img/smile.jpg" %}">
或
{% load static %} <img src="{% get_static_prefix %}img/smile.jpg">
-
-
safe 和 escape:
{{ var|safe|escape }}
ORM
-
什么是 ORM
-
CURD (Create/Update/Retrieve/Delete)
-
Field 选项
null
针对数据库, 允许数据库该字段为 Nullblank
针对 Model 本身, 允许传入字段为空. blank 为 True 时, 对数据库来说, 该字段依然为必填项default
尽量使用 default, 少用 null 和 blankchoices
primary_key
非必要时不要设置, 用默认 id, 保持条目自增、有序unique
db_index
(True | False)max_length
auto_now
每次 save 时,更新为当前时间。update 批量更新时,不生效auto_now_add
只记录创建时的时间, 保存时不更新
-
-
方法
- 创建:
create() / get_or_create() / update_or_create() / bulk_create()
- 条件过滤和排除:
filter() / exclude()
- 只加载需要的字段:
only() / defer()
order_by() / count() / exists()
latest() / earliest()
first() / last()
- 创建:
-
查找条件
filter(id__in=[123, 555, 231])
- SELECT * FROM users WHERE id IN (123, 555, 321)
filter(id__range=[123, 456])
- SELECT * FROM users WHERE id BETWEEN 123 AND 456
filter(name__contains='123')
- SELECT * FROM users WHERE name LIKE ‘%1234%’
filter(name__startswith='123')
- SELECT * FROM users WHERE name LIKE ‘1234%’
filter(id__lte=123)
gt / gte / lt / lte
-
Q 对象
-
F 对象
-
-
其他 ORM
- sqlalchemy
- peewee
-
主键和外键约束
- 内部系统、传统企业级应用可以使用 (需要数据量可控,数据库服务器数量可控)
- 互联网行业不建议使用
- 性能缺陷
- 不能用于分布式环境
- 不容易做到数据解耦
Cache
-
默认缓存:
from django.core.cache import cache
-
BACKEND:
DatabaseCache / MemcachedCache / LocMemCache
-
LOCATION: IP:Port 绑定, 只有一个时配制成字符串链接, 有多台时配制为列表
-
使用 Redis 做缓存
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "PICKLE_VERSION": -1, } } }
-
基本方法
cache.set(key, value, timeout=None)
cache.get(key, default=None)
cache.delete(key)
cache.incr('num')
cache.decr('num')
cache.get_or_set(key, default, timeout=None)
cache.set_many({'a': 1, 'b': 2, 'c': 3})
cache.get_many(['a', 'b', 'c'])
-
全站缓存中间件:
django.middleware.cache.UpdateCacheMiddleware
- 前置中间件
- 缓存期限: CACHE_MIDDLEWARE_SECONDS
-
页面缓存装饰器:
from django.views.decorators.cache import cache_page
-
属性缓存装饰器:
from django.utils.functional import cached_property
-
pickle
data = dumps(obj, -1)
obj = loads(data)
Cookie 和 Session
- 产生过程
- 浏览器 发起请求访问服务器
- 服务器 为 浏览器 创建 Session 对象, 其中包含一个全局唯一的 ID ——
session_id
- 服务器 将 session_id 写入 response 的 Cookie 中, 传回 浏览器
- 浏览器 取出 session_id, 并将其存入 Cookie
- 后续每次请求 session_id 会随 Cookie 一同传到 服务器
- 服务器 取出 session_id 并找出用户之前存储的状态信息
- Cookie:
response.set_cookie(key, value, max_age=None)
- Session 配置
- 开启 Session 中间件:
django.contrib.sessions.middleware.SessionMiddleware
- 配置缓存
- 配置 Session 引擎:
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
- 开启 Session 中间件:
- 可选项
SESSION_COOKIE_AGE
缓存时间, 默认 2 周SESSION_COOKIE_NAME
Session 名, 默认 ‘sessionid’SESSION_EXPIRE_AT_BROWSER_CLOSE
浏览器关闭页面时, Session 是否设为过期SESSION_SAVE_EVERY_REQUEST
每次请求时, 是否强制保存一次 Session
- 用法
request.session.session_key
查看 session_idrequest.session.modified
session 是否发生过修改request.session['uid'] = 1234
当 session 发生更改时会自动保存request.session.get('uid')
取值request.session.save()
手动保存
Logging
-
日志级别
- DEBUG
- INFO
- WARNING
- ERROR
- FATAL
-
使用
- logger.debug(‘xxxxxxxx’)
- logger.info(‘xxxxxxxx’)
- logger.warning(‘xxxxxxxx’)
- logger.error(‘xxxxxxxx’)
- logger.fatal(‘xxxxxxxx’)
-
查找、分析
- tail
- head
- less
- awk
- grep
-
LOGGING = { 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'simple': { 'format': '%(asctime)s %(module)s.%(funcName)s: %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S', }, 'verbose': { 'format': '%(asctime)s %(levelname)s [%(process)d-%(threadName)s] ' '%(module)s.%(funcName)s line %(lineno)d: %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S', } }, 'handlers': { 'inf': { 'class': 'logging.handlers.TimedRotatingFileHandler', 'filename': '/data/web/info.log', 'when': 'W0', # 每周一切割日志 'backupCount': 5, 'formatter': 'simple', 'level': 'DEBUG' if DEBUG else 'INFO', }, 'err': { 'class': 'logging.handlers.TimedRotatingFileHandler', 'filename': '/data/web/error.log', 'when': 'D', # 每天切割日志 'backupCount': 5, 'formatter': 'verbose', 'level': 'WARNING', } }, 'loggers': { 'inf': { 'handlers': ['inf'], 'level': 'DEBUG', 'propagate': True, }, 'err': { 'handlers': ['err'], 'level': 'DEBUG', 'propagate': True, } } }