一、必会的13条html
返回对象列表的python
allajax
filter数据库
excludedjango
order_byjson
reverse数组
distinct浏览器
特殊的对象列表缓存
values安全
values_list
返回对象的
get
first
last
返回布尔值
exist
返回数字的
count
二、单表中双下滑线
__gt
__lt
__in
__range
__countains
__icountains
__startswith
__istartswith
__endswith
__iendswith
__isnull
正向查询
按照对象查询,这个时候只要屡清楚外键设置在哪一个方向,按照对象一步一步的
往过屡就ok。
反向查询
反向查询的时候经过表名(小写的类名)_set,拿到这个管理对象,对这个对象
能够进行表的一些操做。
按字段查询
按字段查询的时候就没有必要屡主外键在哪方面,只须要看着要查的结果和条件
而后按双下划线方法去查找就ok
例子:
# 查找书名是“1”的书的出版社出版的其余书籍的名字和价格
ret = models.Publisher.objects.filter(book__title='1').first().books.exclude(title='1').values('title','price')
print(ret)
ret = models.Book.objects.filter(publisher=models.Publisher.objects.filter(book__title='1').first()).exclude(
title='1')
print(ret)
# 查找书名是“1”的书的做者们的姓名以及出版的全部书籍名称和价钱
ret = models.Author.objects.values('book__title', 'book__price').filter(book__title='1').distinct()
for i in ret:
print(i)
# ret = models.Book.objects.get(title='1').author.values('name', 'book__title', 'book__price').distinct()
# print(ret)查出的数据确定是一条一条的,若是是一对多条,会一行一行的列出来吗,而后 再筛选
正向查询
Obj.多对多关系 -》 管理对象
add()
remove()
clear()
set() []
create()
反向查询
Obj.表名(小写的类名)_set -》 管理对象
聚合是一个终止语句 aggregate
分组的目的是为了进行聚合操做
分组的结果放到了字段中(values中)
正着来
若是不指定分组对象,那么按照表名(表名id)分
反着来
这样是指定values(字段)(也就是分组名称)来分组
拿到的是对象
from django.db.model import F
两个字段之间的比较
子段__gt=F("字段")
字段=F(“字段”) * 2
字段=Concat(F("title"), Value("("), Value("初版"), Value(")"))
from django.db.model import Q
两个条件之间的或关系
Q(筛选条件) | Q(筛选条件)
二者条件之间的与关系
Q(筛选条件) & Q(筛选条件)
条件取反
~Q(筛选条件)
把一些列的操做(步骤)看成一个事务
所有的步骤都成功才成功
经典例子:银行转帐
代码实现:
import os
if name == 'main': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup()
import datetime
from app01 import models
try:
from django.db import transaction # 事务
with transaction.atomic(): # 里面是执行的全部步骤
new_publisher = models.Publisher.objects.create(name="火星出版社")
models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10) # 指定一个不存在的出版社id
except Exception as e:
print(str(e))
是一个保存在浏览器本地的一组组键值对
为何用cookie?http协议是无状态的,每次请求都是无关联的,没有办法保存状态
Network中,请求头中(随着request传到服务器)
禁用以后登录不了,登录是配合cookie作的
特性
服务器让浏览器进行保存的cookie
浏览器有权利是否进行保存
再次访问服务器的时候会携带相应的cookie
Django使用
获取
request.COOKIES
设置
ret = HttpRequest("XXX")
ret.set_cookie(key, max-age=5)
删除
ret = HttpResponse("XX")
ret.delete_cookie(key)
用途
登陆
投票
记录浏览习惯
保存着服务器上的键值对
为何要用session?
cookie保存在浏览器上,不安全、
cookie的长度受限制 4096字节
Django中操做session
设置session
request.session[key] = value
request.session.setdefault(key, valuue)
获取session
request.session[key]
request.session.get(key)
删除session
del request.session[key] 删除某一个
request.session.delete() 删除该用户的全部数据,不删除cookie
request.session.flush() 删除该用户的全部数据,删除cookie
设置超时时间
request.session.set_expiry(value)
清除全部过时的session
request.session.clear_expired()
from django.conf import global_settings
SEESSION配置
458行
SESSION_COOKIE_NAME 名字
SESSION_COOKIE_AGE 过时时间
SESSION_SAVE_EVERY_REQUEST = False 每次保存一次session
SESSION_EXPIRE_AT_BROWSER_CLOSE = False 关闭浏览器就清除cookie
SESSION_ENGINE = '' 设置引擎
Django中默认支持session,其内部提供了5种类型的session供开发者使用
1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也能够是memcache),此处别名依赖缓存的设置
3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,若是为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
其余公用设置项:
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过时(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改以后才保存(默认)
发请求:a标签,location,form表单,地址栏
钩子:在某个位置预留了位置,没有挂钩子函数的话继续执行,若是写了钩子函数就执行完后继续执行。
中间件全部的动做都会走,会影响全局,谨慎使用
settings中的MIDDLEWARE
Django中的中间件?是什么?
是一个python类用来在全局范围内处理请求和响应的一个钩子。
自定义中间件
五个方法
参数,执行时间,执行顺序
一、process_request(self, request)
执行时间:在路由匹配以前,在视图函数执行以前,
参数:
request:视图函数用到中用到的request
执行顺序:按照注册顺序执行
返回值:
None:正常流程
HttpResponse对象:当前中间件后面的中间件的process_request方法
process_Response方法和视图的Http_Response对象不执行,执行当前
中间件的process_response方法以及以前的process_reques方法
二、process_response(self, request, response)
执行时间:在视图函数执行以后
参数:
request:视图函数用到中用到的request
response:视图函数中返回的response对象,若是中间件返回response对象,就不走
视图函数了
执行顺序:按照注册顺序倒序执行
返回值:
不能为None,不然会报错
必须是response对象
三、process_view(self, request, view_func, view_args, view_kwargs)
执行时间:在视图函数以前,在process_reques方法以后,以及路由匹配以后
参数:
request:视图函数用到中用到的request
view_func:要执行的视图函数
view_args:视图函数的位置参数
view_kwargs:视图函数的关键字参数
返回值:
None:正常流程
HttpResponse对象:他以后的中间件process_view方法、视图都不执行,执行全部中
间件的process_response方法
执行属性:按照注册顺序执行
四、process_exception(self, request, exception)
执行时间:
触发条件:有异常才执行
在视图函数以后,在process_response以前
参数:
request:视图函数用到中用到的request
exception:错误信息对象
返回值:HttpResponse对象:
None:正常执行
HttpResponse对象:
注册顺序以前的全部中间件的process_exception方法不走了
执行全部中间件的的process_response
执行顺序:按照注册顺序倒序执行
五、process_template_response(self, request, response)
执行时间:
触发条件:返回的response对象要有一个render方法
在视图函数以后,在process_response方法以前
参数“
request:视图函数用到中用到的request
response:视图函数中返回的response对象
返回值:
不能为None,不然会报错
必须是response对象
执行顺序:按照注册顺序倒序执行(不会截断,可以重写)
CSRF中间件
CSRF跨站请求伪造
在form表单中加{%csrf_token%}干了两件事
隐藏一个input标签
生成一个cookie
两个装饰器
from django.views.decorators.csrf import csrf_exempt, csrf_protect
csrf_exempt:给单个视图排除校验
csrf_protect:给单个视图必须校验
源码分析
process_request
从请求的cookie中获取csrftoken的值 ——》csrf_token ——》
request.META['CSRF_COOKIE']
preocess_view
若是视图函数加上了csrf_exempt的装饰器 不作校验
若是请求方式是'GET', 'HEAD', 'OPTIONS', 'TRACE' 也不作校验
其余的请求方式作校验
request.META.get('CSRF_COOKIE') —— 》 csrf_token
request_csrf_token = ""
从request.POST中获取csrfmiddlewaretoken对应的值
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
从请求头中获取X-csrftoken 的值
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')
request_csrf_token 和 csrf_token 作对比
若是校验成功 正常走
若是校验不成功 拒绝
浏览器向服务器发送请求的形式
地址栏输入地址 回车 GET
form表单 点击 submit
a标签
ajax
json是一种数据结构,跨平台
python中的json数据结构转换
数据类型
字符串、数字、bool、列表、字典、None
序列化
dumps(python数据类型)
dump(python的数据类型, f)
反序列化
loads
load
js中json数据的转换
数据类型
字符串、数字、布尔、数组、对象、null
序列化
stringify
反序列化
parse
django中json
JsonResponse
JsonResponse({})
JsonResponse([], safe=False)
是一个与服务器进行交互的技术。(js技术)
特色:
异步
不刷新页面 数据量小
浏览器向服务器发送请求
地址栏输入地址 回车
form表单
a标签
ajax
ajax
参数
$('#b1').click(function () {
$.ajax({
url: '/calc/', # url地址
type: 'post', # 请求方式
data: { # 发送的数据
i1: $('[name="i1"]').val(),
i2: $('[name="i2"]').val()
hobby:JSON.stringify(['抽烟','喝酒','烫头']) # 传个列表 进行序列化
},
success: function (res) { # 回调函数 成功时调用 res 返回的内容 响应的响应体
console.log(res);
$('[name="i3"]').val(res)
}, error: function (res) { # 回调函数 失败时调用
console.log('这是错误的')
console.log(res)
}
})
});ajax发post请求 经过CSRF验证的方法
页面中使用{% csrf_token %}
$('#b1').click(function () {
$.ajax({
url: '/csrf_test/',
type: 'post',
data: {
csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val(), # **********
name: 'ward',
age: '18',
},
success: function (res) {
console.log(res);
}
})
});设置请求头
$('#b1').click(function () {
$.ajax({
url: '/csrf_test/',
type: 'post',
headers: {"X-CSRFToken": $('[name="csrfmiddlewaretoken"]').val()},
data: {
name: 'ward',
age: '18',
},
success: function (res) {
console.log(res);
}
})
});全局设置(本身写的js代码)
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
# 从cookie中取值 必要有cookie
有cookie的方式
1. 使用{% csrf_token %}
2. 不使用{% csrf_token %}
from django.views.decorators.csrf import ensure_csrf_cookie
将ensure_csrf_cookie加在视图上 保证返回的响应有cookie
建立超级用户
python3 manager.py createsuperuser
认证 校验 用户的用户名与密码
obj = auth.authenticate(request, username=username, password=password)
认证成功:对象
认真失败:None
保存登陆状态 记录到session
login(request, user)
注销 删除session
logout(request)
判断登陆状态
requset.user.is_authenticated()
建立用户
from django.cotrib.auth.models import User
密码是明文的
User.objects.create(username=username,password=password)
密码是密文的普通用户
User.objects.create_user(**form_obj.cleaned_data)
建立超级用户
User.objects.create_superuser(email='',**form_obj.cleaned_data)
密码相关
校验密码
request.user.check_password('root1234')
设置密码
request.user.set_password('admin1234')
request.user.save()扩展默认的auth_user表
这内置的认证系统这么好用,可是auth_user表字段都是固定的那几个,我在项目中无法拿来直接使用啊!
好比,我想要加一个存储用户手机号的字段,怎么办?
可能会想到新建另一张表而后经过一对一和内置的auth_user表关联,这样虽然能知足要求可是有没有更好的实现方式呢?
答案是固然有了。
咱们能够经过继承内置的 AbstractUser 类,来定义一个本身的Model类。
这样既能根据项目需求灵活的设计用户表,又能使用Django强大的认证系统了。
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
"""
用户信息表
"""
nid = models.AutoField(primary_key=True)
phone = models.CharField(max_length=11, null=True, unique=True)
def __str__(self):
return self.username注意:
按上面的方式扩展了内置的auth_user表以后,必定要在settings.py中告诉Django,我如今使用我新定义的UserInfo表来作用户认证。写法以下:
# 引用Django自带的User表,继承使用时须要设置
AUTH_USER_MODEL = "app名.UserInfo"再次注意:
一旦咱们指定了新的认证系统所使用的表,咱们就须要从新在数据库中建立该表,而不能继续使用原来默认的auth_user表了。
form
完成的事情
有input标签,让用户能够填数据
校验form表单提交数据
提示错误信息
Django的form
定义
from django import forms
# 定义form
class RegForm(forms.Form):
user = forms.CharField(label='用户名')
pwd = forms.CharField(label='密码')使用
视图中
def register2(request):
form_obj = RegForm()
return render(request, 'register2.html', {'form_obj': form_obj})模板中
<form action="" method="post">
{% csrf_token %}
{{ form_obj.as_p }}
<p>
<input type="submit" value="注册">
</p>
</form><form action="" method="post">
<p>
{{ form_obj.user.lable }}
{{ form_obj.user }}
</p>
<p>
{{ form_obj.pwd.lable }}
{{ form_obj.pwd }}
</p>
<p>
<input type="submit" value="注册">
</p>
</form>总结:
form_obj.as_p ——> 自动生成多个p标签 包含lable input框
form_obj.user/form_obj.pwd ——> 自动生成某个字段的input框
form_obj.user.errors ——> 某个字段的全部错误信息
form_obj.user.errors.0 ——> 摸个字段的错误信息的第一个
form_obj.use.id_for_lable
参数
label='用户名', # 标签的名字 min_length=6, # 校验的规则 最小长度 initial='alexdsb', # 初始值 error_messages={ # 自定义错误提示 'min_length': '你的长度过短了,还不到6', 'required': '不能为空'
} widget=widgets.PasswordInput() # 插件 指定字段的类型
校验
每一个字段有默认的校验方法
min_length=6
max_length=6
required=False
disabled 是否不可修改
自定义校验规则
validators = [ 校验器1,校验器2 ]
from django.core.validators import RegexValidator
RegexValidator(r'^1[3-9]\d{9}$', '手机号不正经')
自定义函数 from django.core.exceptions import ValidationError
def check_name(value): if 'sb' in value: raise ValidationError('不符合社会主义核心价值观')
validators = [ check_name, ]. # 校验函数
钩子函数
局部钩子
def clean_phone(self):
value = self.cleaned_data.get('phone')
if re.match(r'^1[3-9]\d{9}$',value):
return value
raise ValidationError('手机号不正经')全局钩子
def clean(self):
pwd = self.cleaned_data.get('pwd')
re_pwd = self.cleaned_data.get('re_pwd')
if pwd == re_pwd:
return self.cleaned_data
self.add_error('re_pwd','两次密码不一致')
raise ValidationError('两次密码不一致')