django请求流程:经过遵循wsgi的组件(例如wsgiref、uwsgi,注意wsgi不属于django的一部分)➡️中间件➡️路由系统➡️视图函数拿到模版和数据库等返回
return render(request, "index.html")
这个时候表明render的时候,已经把request这个对象传递给前端模版了,在前端可以直接调用request这个对象
MTV(数据库、模版、视图函数)就是做模块功能的划分
一、路由系统:
1、可以使用includ进行url分发(include里面加的就是app里面urls 的路径)
from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^app01/', include("APP01.urls")), url(r'^app02/', include("APP02.urls")), ] from django.conf.urls import url, include from django.contrib import admin from APP01 import views urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^index/', views.index), ]
2、例如编辑的时候,以往是通过
<a href="/app01/edit/?id={{ id }}">编辑</a>
这样的方式发送到后端,现在可以使用路由中的正则来匹配,
如:
路由中:
url(r'^edit/(w+)/', views.edit),
视图中:
def edit(request, name):
print(name)
模版中:
<a href="/app01/edit/{{ user }}">编辑</a>
3、路由系统中url正则组还可以自定义命名,视图中根据正则组名字来取
urlpatterns = [
url(r'^edit/(?P<a1>w+)/(?P<a2>w+)', views.edit),
]
上述就是给两个正则组分别命名为p1、p2,需要注意的是,正则组如果采用位置就都采用位置,如果采用名字就都采用名字
路由正则尽量以$结尾,如果以 / 结尾的话 /前面可以无限写东西
4、伪静态(路由系统中url后缀加.html),目的是让用户感觉到是静态文件,加载很快的样子
urlpatterns = [
url(r'^edit/(?P<a1>w+)/(?P<a2>w+).html/$', views.edit),
]
5、路由系统反向生成url(根据名字反向寻找url)
应用场景:比如说不同的用户有不同的权限能访问不同的url,如果把每个人能访问的url都放进数据库占空间,而直接放反向生成的别名就好了。
在python代码中可以应用:
路由中:
urlpatterns = [
url(r'^edit/(?P<a1>w+)/(?P<a2>w+).html/$', views.edit, name="t2"),
]
视图中:
from django.urls import reverse
v = reverse("t2", kwargs={"a1": "alex", "a2": 18})
print(v)
在模版中可以应用:
<form method="post" action="{% url "t2" %}">
<input type="text">
</form>
二、ORM(当数据库的表中有数据又添加新列的时候,可以设置新列null=Treu或者default=“xxx”):
ORM第三张表中这样写默认相当于关联这张表的这个id字段:
class G2B(models.Model):
gid = models.ForeignKey("Girl")
bid = models.ForeignKey("Boy")
class G2B(models.Model):
gid = models.ForeignKey(to="Girl", to_field="id")
bid = models.ForeignKey(to="Boy", to_field="id")
django中使用orm中的准备:
1、手动创建数据库
2、settings配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'Test2',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': '',
}
}
3、与settings同级的init文件中配置:
import pymysql
pymysql.install_as_MySQLdb()
4、在app的models中创建表
class userinfo(models.Model):
nid = models.AutoField(primary_key=True) (这一列可以不写,django会自动生成一列名称为“id”的列为主键,并且自增,并且int)
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
5、在settings 中注册app信息
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'APP01',
]
6、输入生成表的命令
python manage.py makemigrations
python manage.py migrate
一对多关系表:
ug = models.ForeignKey("Userinfo_group", null=True)
创建完成后,自动关联到“Userinfo_group”这张表的主键上
orm基本操作:
# 单表增
# models.Usertype.objects.create(title="运营部")
# 单表删
# models.Usertype.objects.filter(id__gt=4).delete()
# 单表改
# models.Usertype.objects.filter(id=4).update(title="大牛部")
# 单表查
# result = models.Usertype.objects.filter(id=4).first()
# for i in result.userinfo_set.all():
# print(i.name, i.age)
# 一对多表增
# models.Userinfo.objects.create(name="alex", age="18", ut_id=4)
# 一对多表删
# models.Userinfo.objects.filter(id=4).delete()
# 一对多表改
# models.Userinfo.objects.filter(id=1).update(name="alexboy", age="90", ut_id=3)
# 一对多表查
# result = models.Userinfo.objects.filter(id=1).first()
# print(result.name, result.age, result.ut_id, result.ut.title)
# 查表什么也不加 取出的是query_set对象,里面是对象,可以直接 "." 出来属性, 想跨表查询的话for循环出来对象直接"."
result = models.Userinfo.objects.all()
print(result)
# 查表加values 取出的是query_set对象,里面是字典,想跨表查询的话values里面用双下划线
result = models.Userinfo.objects.all().values("id", "name", "ut__title")
print(result)
# 查表加values_list 取出的是query_set对象,里面是元组,想跨表查询的话values_list里面用双下划线
result = models.Userinfo.objects.all().values_list("id", "name", "ut__title")
print(result)
琐碎知识点:
1、
query_set里面是一个个对象,这个时候打印看到的是这样的:
<QuerySet [<Userinfo: Userinfo object>, <Userinfo: Userinfo object>, <Userinfo: Userinfo object>, <Userinfo: Userinfo object>]>
如果想直观的看出来对象是什么,可以在models里面添加:
class Userinfo(models.Model):
name = models.CharField(max_length=32)
age = models.CharField(max_length=32)
ut = models.ForeignKey("Usertype")
def __str__(self):
return "{}-{}".format(self.id, self.name)
2、
倒序排序:
result = models.Userinfo.objects.all().order_by("-id")
print(result)
正序排序:
result = models.Userinfo.objects.all().order_by("id")
print(result)
3、
原生sql语句中聚合函数和分组搭配着进行查询:
select count(id) as count_num, ut_id from APP01_userinfo group by ut_id;
原生sql语句中聚合函数和分组搭配着进行查询(用having进行二次筛选的):
select count(id) as count_num, ut_id from APP01_userinfo group by ut_id having(count_num>1);
django中的orm中聚合函数和分组搭配着进行查询:
from django.db.models import Count
resutl = models.Userinfo.objects.values("ut_id").annotate(xxx=Count("id"))
print(resutl)
django中的orm中聚合函数和分组搭配着进行查询(进行二次筛选的):
from django.db.models import Count
resutl = models.Userinfo.objects.values("ut_id").annotate(xxx=Count("id")).filter(xxx__gt=1) (此时的filter相当于原生sql中的having)
print(resutl)
4、
# 七杂八杂小查询
# id > 2
result = models.Userinfo.objects.filter(id__gt=2)
print(result)
# id < 2
result = models.Userinfo.objects.filter(id__lt=2)
print(result)
# id >= 2
result = models.Userinfo.objects.filter(id__gte=2)
print(result)
# id <= 2
result = models.Userinfo.objects.filter(id__lte=2)
print(result)
# id 在[1, 3 ,5]中的
result = models.Userinfo.objects.filter(id__in=[1, 3, 5])
print(result)
# id在1--5中间的
result = models.Userinfo.objects.filter(id__range=[1, 5])
print(result)
# name以"a"开头的
result = models.Userinfo.objects.filter(name__startswith="a")
print(result)
# name中含有"a"的
result = models.Userinfo.objects.filter(name__contains="a")
print(result)
# id != 1 的
result = models.Userinfo.objects.exclude(id=1)
print(result)
5、
F查询(在更新的时候拿到原来的值):
from django.db.models import F, Q
models.Userinfo.objects.all().update(age=F("age") + 1)
return HttpResponse("ok")
Q查询(用于构造复杂的查询条件):
两种应用:
1⃣️:(推荐使用)
q1 = Q()
q1.connector = "OR"
q1.children.append(("id", 1))
q1.children.append(("id", 2))
q2 = Q()
q1.connector = "OR"
q1.children.append(("id", 3))
q1.children.append(("id", 4))
conn = Q()
conn.add(q1, "AND")
conn.add(q2, "AND")
result = models.Userinfo.objects.filter(conn)
print(result)
2⃣️:
result1 = models.Userinfo.objects.filter(Q(id=1) | Q(id=2))
print(result1)
result2 = models.Userinfo.objects.filter(Q(id=1) & Q(id=2))
print(result2)
extra 查询(orm扩展,自己写一部分原生sql)
# 1、
# result = models.Userinfo.objects.all().extra(select={"n": "select count(1) from APP01_usertype where id<%s"}, select_params=[4, ])
# for i in result:
# print(i.name, i.n)
# 2、
# result = models.Userinfo.objects.all().extra(
# where=["id=%s or id=%s", "name=%s"],
# params=[1, 2, "alexboy"]
# )
# print(result)
# 3、
# result = models.Userinfo.objects.all().extra(order_by=["-id", ])
# print(result)
# 4、
# result =models.Userinfo.objects.all().extra(
# tables=["APP01_usertype"]
# )
# print(result)
orm扩展,自己写全部原生sql
from django.db import connection
curson = connection.cursor()
curson.execute('select * from APP01_userinfo;')
result_list = curson.fetchall()
print(result_list)
django中的reverse() (前面只有加上order_by的话,reverse()才会生效)
result = models.Userinfo.objects.all().order_by("-id").reverse()
print(result)
django中的only("id", "name") (加上only之后效果和values一样,只不过返回的数据还是queryset里面包含一个个对象,这个时候能 “.”出来 “id”和“name” 虽然也能“.”出来其他的属性,例如“age”, 但是不要这样去用,如果这样用的话会向数据库多发请求)
result1 = models.Userinfo.objects.only("id", "name")
print(result1)
result2 = models.Userinfo.objects.values("id", "name")
print(result2)
django中的defer("id", "name") (和only用法一样,只不过only是取出“id”和“name”,defer()恰恰相反)
result1 = models.Userinfo.objects.defer("id", "name")
print(result1)
result2 = models.Userinfo.objects.values("id", "name")
print(result2)
django中的using() (django中可以在settings中配置连接好多个数据库,用using指定去哪个数据库里面拿数据)
result1 = models.Userinfo.objects.all().using("default")
创建数据的时候可以接收返回值
obj = models.Userinfo.objects.create(name="test", age="44", ut_id=1)
print(obj, obj.id)
第二种创建数据的方法
dic = {
"name": "test1",
"age": "18",
"ut_id": 2,
}
obj = models.Userinfo.objects.create(**dic)
print(obj, obj.id)
批量创建数据
objs = [
models.Userinfo(name="test10", age="18", ut_id=1),
models.Userinfo(name="test11", age="18", ut_id=1),
models.Userinfo(name="test12", age="18", ut_id=1),
]
models.Userinfo.objects.bulk_create(objs, 10)
get_or_create()和update_or_create()两个方法:
# obj, created = models.Userinfo.objects.get_or_create(name="alex",defaults={"age": 18, "ut_id": 1})
# print(obj, created)
# obj, created = models.Userinfo.objects.update_or_create(name="alex", defaults={"name": "alex", "age": 18, "ut_id": 1})
# print(obj, created)
exists()方法 (检测是否存在,返回布尔值)
result = models.Userinfo.objects.filter(id="1").exists()
print(result)
关于XSS攻击
慎用前端的:
{{ list | safe }}
和后端的mark_safe:
from django.utils.safestring import mark_safe
select_related()
这样就相当于向数据库查询了十一次
obj_list = models.Userinfo.objects.all() (一次)
for obj in obj_list:
print(obj.name, obj.age, obj.ut.title) (十次,因为涉及到了连标)
此时如果改为以下(相当于向数据库查询了一次,在第一次就直接连表了,提高性能)
obj_list = models.Userinfo.objects.all().select_related("ut") (一次)
for obj in obj_list:
print(obj.name, obj.age, obj.ut.title)
prefetch_related()

orm中的联合唯一(加上 class Meta)
class love(models.Model):
b = models.ForeignKey("boy")
g = models.ForeignKey("girl")
class Meta:
unique_together = [
("b", "g")
]
多对多(三种方法:
一种是ManyToManyField自动创建第三张表,
一种是手动创建第三张表,
class Love(models.Model):
b = models.ForeignKey("Boy")
g = models.ForeignKey("Girl")
一种是手动创建和ManyToManyField相结合,
class Boy(models.Model):
name = models.CharField(max_length=32)
m = models.ManyToManyField("Girl", through="Love", through_fields=("b", "g"))
class Girl(models.Model):
nick = models.CharField(max_length=32)
class Love(models.Model):
b = models.ForeignKey("Boy")
g = models.ForeignKey("Girl")
)
正向查询:
boy_obj = models.Boy.objects.filter(name="方少伟").first()
# boy_obj.m.add(1)
# boy_obj.m.remove(2)
# boy_obj.m.set([3, ])
# obj_list = boy_obj.m.all() # 理论上应该拿到 m 的对象,但是django内部做了功能,直接拿到的就是girl的对象
# obj_list = boy_obj.m.filter(nick="小雨")
# boy_obj.m.clear()
反向查询:
girl_obj = models.Girl.objects.filter(nick="小雨").first()
boy_list = girl_obj.boy_set.all()
for boy_obj in boy_list:
print(boy_obj.name)
---------------------------------------------------------------------------------------------------------------
关于正向查找和反向查找的补充:
1、class Userinfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64) ut = models.ForeignKey("Usertype") class Usertype(models.Model): title = models.CharField(max_length=32) 当这样创建表的时候,反向查找是: models.Usertype.objects.filter(title="营销部").first().Userinfo_set.all() 2、class Userinfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64) ut = models.ForeignKey("Usertype") class Usertype(models.Model): title = models.CharField(max_length=32, related_query_name="users") 当这样创建表的时候,反向查找是: models.Usertype.objects.filter(title="营销部").first().users_set.all() 3、class Userinfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64) ut = models.ForeignKey("Usertype") class Usertype(models.Model): title = models.CharField(max_length=32, related_name="users") 当这样创建表的时候,反向查找是: models.Usertype.objects.filter(title="营销部").first().users.all()
4、(加上带选择项的字段可以这样创建)
class Userinfo(models.Model):
nickname = models.CharField(max_length=32)
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
gender_choices = (
(0, "女"),
(1, "男"),
)
gender = models.IntegerField(gender_choices)
5、在一对多或者多对多表里面还可以这样创建对象:
平常是这样:
models.U2U.objects.create(g_id=1, b_id=2)
还可以这样:
g_obj = models.Userinfo.objects.filter(nickname="马蓉").first()
b_obj = models.Userinfo.objects.filter(nickname="高卓").first()
models.U2U.objects.create(g=g_obj, b=b_obj)
ORM自关联:
多对多自关联:
多对多自关联第一种情况:
models里面:
class Userinfo(models.Model): nickname = models.CharField(max_length=32) username = models.CharField(max_length=32) password = models.CharField(max_length=64) gender_choices = ( (0, "女"), (1, "男"), ) gender = models.IntegerField(gender_choices) class U2U(models.Model): b = models.ForeignKey("Userinfo", related_name="boy") g = models.ForeignKey("Userinfo", related_name="girl")
查找的时候:
# 根据男生找女生
userinfo_obj = models.Userinfo.objects.filter(id=1).first()
u2u_list = userinfo_obj.boy.all()
for u in u2u_list:
print(u.g.nickname)
# 根据女生找男生
userinfo_obj = models.Userinfo.objects.filter(id=5).first()
u2u_list = userinfo_obj.girl.all()
for u in u2u_list:
print(u.g.nickname)
多读多自关联第二种情况
models里面:
class Userinfo(models.Model):
nickname = models.CharField(max_length=32)
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
gender_choices = (
(0, "女"),
(1, "男"),
)
gender = models.IntegerField(gender_choices)
m = models.ManyToManyField("Userinfo")
查找的时候:
# 根据男生查找女生
# userinfo_obj = models.Userinfo.objects.filter(nickname="徐峥").first()
# obj_list = userinfo_obj.m.all()
# for obj in obj_list:
# print(obj.nickname)
# 根据女生查找男生
# userinfo_obj = models.Userinfo.objects.filter(nickname="白百合").first()
# obj_list = userinfo_obj.userinfo_set.all()
# for obj in obj_list:
# print(obj.nickname)
一对多自关联:
---------------------------------------------------------------------------------------------------------------
csrf:跨站请求伪造
form表单中添加{% csrf_token %}
---------------------------------------------------------------------------------------------------------------
三、模板:
1、母版继承(一个子版只能继承一个母版)
母版内填写:
{% block title %}
{% endblock %}
子版内顶部填写:
{% extends 'master.html' %}
{% block title %}
亿忆网到Awehome自动发帖--------请完善发布前的必填信息
{% endblock %}
2、模版内调用函数不用加括号自动执行:
userlist = {"a:": "1", "b": "2", "c": 3}
例如后端 return render(request, "moban.html", {"userlist": userlist})
这时候前端调用 item keys values 等函数都不用加括号
{% for user in userlist.items %}
<h1>{{ user }}</h1>
{% endfor %}
{% for user in userlist.keys %}
<h1>{{ user }}</h1>
{% endfor %}
{% for user in userlist.values %}
<h1>{{ user }}</h1>
{% endfor %}
3、模版内自定义函数filter(filter里面最多支持两个参数,可以作为条件判断放在if语句里面 simple_tag不能作为条件判断放在 if语句里面)
1⃣️、在app中创建一个templatetags文件夹
2⃣️、创建任意py文件,如:xx.py
3⃣️、新创建的py文件里面填写:
from django import template
register = template.Library()
@register.filter
def my_upper(value, arg1):
return value + arg1
4⃣️、模版里面顶部先导入
{% load xx %}
5⃣️、模版里面使用:
{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ name|my_upper:"666" }} (“ : ” 后面传参数,并且冒号后面与参数之间不能留有空格)
</body>
</html>
4、模版内自定义函数simple_tag(simple_tag里面支持多个参数)
1⃣️、在app中创建一个templatetags文件夹
2⃣️、创建任意py文件,如:xx.py
3⃣️、新创建的py文件里面填写:
from django import template
register = template.Library()
@register.simple_tag
def my_upper(value, arg1, arg2, arg3):
return value + arg1 + arg2 + arg3
4⃣️、模版里面顶部先导入
{% load xx %}
5⃣️、模版里面使用:
{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% my_lower "alex" "a" "b" "c" %}
</body>
</html>
5、小组件include(和母版功能类似但又不一样)
把写好的小组件放在一个html里面,然后其他地方想用的话,直接可以直接:
{% include pub.html %}
小组件可以在一个html中导入很多遍
四、session(作用是保持会话,依赖于cookie,好处是隐秘性信息不会让用户端看到):
cookie是保存在客户端的键值对
session是保存在服务器端的数据(可能是键值对,可能是其他任意数据,但是本质上还是键值对)
# session中存放的格式是 ''' { sessionid:{ username:alex, password: alex3714 } } ''' # 将所有Session失效日期小于当前日期的数据删除 (默认过期事件是两周,数据库session表中还默认隐藏存放了一行session过期时间) # request.session.clear_expired() # 查看当前登陆人sessionid # session_key = request.session.session_key # print(session_key) # 删除sessionid对应的value中的username # del request.session["username"] # username = request.session.get("username") # password = request.session.get("password") # print(username) # print(password) # 设置sessionid对应的value中的username # request.session["username"] = "alex" # username = request.session.get("username") # password = request.session.get("password") # print(username) # print(password) # 删除当前用户所对应的所有session数据 # session_key = request.session.session_key # request.session.delete(session_key) # 检测当前登陆用户的sessionid是否在数据库中存在,返回bool值 # session_key = request.session.session_key # ret_bol = request.session.exists(session_key) # print(ret_bol) # 设置session的过期时间 # request.session.set_expiry(value) # *如果value是个整数,session会在些秒数后失效。 # *如果value是个datatime或timedelta,session就会在这个时间后失效。 # *如果value是0, 用户关闭浏览器session就会失效。 # *如果value是None, session会依赖全局session失效策略。
session在settings文件中的配置:
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
SESSION_ENGINE
=
'django.contrib.sessions.backends.db'
# 引擎(session默认放在数据库中)
SESSION_ENGINE
=
'django.contrib.sessions.backends.cache'
# 引擎(session放在缓存中)
SESSION_ENGINE
=
'django.contrib.sessions.backends.file'
# 引擎 (session放在文件中)
SESSION_FILE_PATH
=
None
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,默认修改之后才保存(默认)
五、中间件