django几大部分

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,默认修改之后才保存(默认)


五、中间件

posted @ 2019-04-21 17:48  Qimisun  阅读(444)  评论(0编辑  收藏  举报