Django 笔记整理

自写框架

HTTP协议

http协议:
   即超文本传输协议(Hypertext transfer protocol)。是一种详细规定了浏览器和万维网(WWW = World Wide Web)服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:
  请求行、请求头部、空行和请求数据四个部分组成
特性:
   基于TCP/IP协议;无状态;短链接;被动响应

 

wsgiref模块

WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app(应用程序)与web server(socket服务端)之间接口格式,实现web app与web server间的解耦。通俗的说:当规范建立后,程序就不再重复编写web server(socket服务端),而是直接使用现成的实现WSGI的模块(例如:wsgiref、uwsgi、werkzeug),从而让程序员更加专注与业务代码与其重复造轮子,不如直接用现成的。

Python的wsgiref是基于WSGI规范封装的模块,我们可以在这个模块基础上开发我们的web server


from wsgiref.simple_server import make_server

def login():
pass

def error():
return "404 error"

urls = [
("/login",login)
]

def run(environ,response):
# environ:请求数据封装成格式为字典
path = environ.get('PATH_INFO')   # 获取请求的url
# 返回数据的格式(响应行,请求头)
response("200 OK",[('Content-Type','text/html; charset=utf-8')])

func = 0
for i in urls:
if path == i[0]:
func = i[1]
break
if func:
res = func()
else:
res = error()

# 返回给客户端的消息
return [res.encode("utf-8")]

# 绑定host,port 自动执行 run函数
s = make_server("0.0.0.0",9000,run)

# 启动服务端,循环监听
s.serve_forever()

动态网页

import time
from wsgiref.simple_server import make_server

def gen():
with open(r"..\1.html","r",encoding='utf-8') as f:
data = f.read()
t = time.ctime()
data = data.replace("time",t)
return data


def error():
return "404 error"

urls = [
("/",gen)
]

def run(environ,response):
# environ:请求数据封装成格式为字典
path = environ.get('PATH_INFO')   # 获取请求的url
# 返回数据的格式(响应行,请求头)
response("200 OK",[('Content-Type','text/html; charset=utf-8')])

func = 0
for i in urls:
if path == i[0]:
func = i[1]
break
if func:
res = func()
else:
res = error()

# 返回给客户端的消息
return [res.encode("utf-8")]

# 绑定host,port 自动执行 run函数
s = make_server("127.0.0.1",9000,run)

# 启动服务端,循环监听
s.serve_forever()

模板语法jinja2

from jinja2 import Temlate

# html部分
{{user}}

# 后端部分
from wsgiref.simple_server import make_server
from jinja2 import Template

def gen():
dic = {"name":"bajie","age":18}
with open(r"..\1.html","r",encoding='utf-8') as f:
data = f.read()
t = Template(data)
data = t.render(user=dic)
return data

def error():
return "404 error"
urls = [
("/",gen)
]

def run(environ,response):
# environ:请求数据封装成格式为字典
path = environ.get('PATH_INFO')   # 获取请求的url
# 返回数据的格式(响应行,请求头)
response("200 OK",[('Content-Type','text/html; charset=utf-8')])

func = 0
for i in urls:
if path == i[0]:
func = i[1]
break
if func:
res = func()
else:
res = error()

# 返回给客户端的消息
return [res.encode("utf-8")]
# 绑定host,port 自动执行 run函数
s = make_server("127.0.0.1",9000,run)
# 启动服务端,循环监听
s.serve_forever()

Django

# 创建项目(先进入到要创建项目的文件夹)
django-admin startproject 项目名

# 创建应用(app)
python manage.py startapp 应用名称

# 启动应用
python manage.py runserver IP/port

项目目录结构

项目
应用
  migrants
      __init__.py
       __init__.py
       admin.py               # 数据库后台
       apps.py                # django 把项目和app 关联文件
       models.py              # 数据库操作
       tests.py               # 单元测试
       views.py               # 视图函数,业务逻辑
      HttpResponse(字符串)
           render(request,xxx.html)
   项目文件
  __init__.py
       setting.py             # 程序的配置文件
       urls.py                # 程序的路由系统(url与视图函数的对应关系)
       swgi.py                # 指定框架的wsgi
   
   templates                  # html模板文件自己创建
   db.sqlite3
   manage.py                  # 管理程序文件,启动与结束等

MVC&MTV架构

# MVC 是一种使用MVC (Model View Controller 模型-视图逻辑-控制器) 设计创建的Web的模式

 

# MTV
(Model templates Controller 模型-视图逻辑-控制器) 设计创建的Web的模式

 

1, url 路由层

1,正则匹配
APPEND_SLASH = False    取消自动加/
   url(r'login',view.login)
   url(r'longing',view.longing)    
2,匹配首页
url(r"^$",view.home)
3,尾页匹配
url(r"",view.error)

 

1.1 静态路由

url('login/(^2020$)/', views.login)

2.0
url('login/2020/', views.login)

视图函数(位置传参)

1.2 动态路由

re_path('login/(?P<year>[0-9]{4})', views.login)  # 视图函数(关键字传参year)

re_path('login/(?P<slug>[\w-]+)', views.login)    # 匹配任意字符


2.0
path('login/(<int:year>)', views.login)  # 视图函数(关键字传参year)

path('login/<slug:slug>', views.login)    # 匹配任意字符

1.3路由分发(include)与名称空间(了解)

# 不同应用相同url的分发
'''
如果view方法相同时,反向解析不能识别前缀url,这时需要使用namespace命名空间,
解析时:reverse(app01:home)  
'''
### 主文件下的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',namespace='app01')),
   url(r'^app02/', include('app01.urls',namespace='app02')),
]

### 应用app01的urls文件
from django.conf.urls import url
from app01 import views

urlpatterns = [
   url(r'^home/', views.home),
]

### 应用app02的urls文件
from django.conf.urls import url
from app02 import views

urlpatterns = [
   url(r'^home/', views.home),
]

# 注意事项:总路由不能加$

# 访问路径
http://127.0.0.1:8000/app01/home/
http://127.0.0.1:8000/app02/home/

1.4 url 反向解析

from django.shortcuts import reverse

1,先给路由起一个别名
url(r'^func/',view.func,name='别名')
2,后端view反向解析
print(reverse('别名'))
3,前端html反向解析
<a href = "{% url 别名 %}">ooo</a>

# 无名分组反向解析(数据的主键值来替代1)
url(r'^func/(\ d+)',view.func,name='别名')
1,后端view反向解析
print(reverse('别名',args=(1,)))
2,前端html反向解析
<a href = "{% url 别名 1 %}">ooo</a>

# 有名分组反向解析
url(r'^func/(?P<year>\ d+)',view.func,name='别名')
1,后端view反向解析
print(reverse('别名',args=(1,)))      简写!
print(reverse('别名',kwargs={'year':1}))
2,前端html反向解析
<a href = "{% url 别名 1 %}">ooo</a>  简写!
<a href = "{% url 别名 year = 1 %}">ooo</a>

2, views(视图层)

# request对象方法





 

2.1 FBV模式

url(r'^longin/(/d+)', views.longin)

def longin(request,参数1(/d+)):
   return  render(request,"longin.html")

返回页面:
   HttpResquest("hellow word")                                 # 返回字符串
   render(request,"xx.html",{jinjia2传值})                      # 返回页面
   redirect("网址")                                             # 重定向
   JsonResponse(数据,json_dumps_params={"ensure_ascii":False})  # 返回json格式数据
  默认只能序列化字典,序列化其他加参数  JsonResponse(数据,json_dumps_params={"ensure_ascii":False},safe=False)    # 返回前端是对象

2.2 CBV模式

url(r'^longin/', views.Select.as_view())

from django.views import View

class Select(View,):
   def dispatch(self, request, *args, **kwargs):
       print('第一次执行位置')
       res = super().dispatch(request, *args, **kwargs)
       print('第三次执行位置')
       return res   # 按照不同的方法,执行后的返回值返回到页面

   def get(self, request):
       print('第二次执行位置')
       return HttpResponse("get请求方法")

   def post(self, request):
       pass

3,templates渲染层

3.1 万能点

# (索引,key,属性,方法(不加括号,只能进行无参数方法),类,对象)

3.2 过滤器

# html,语法:{{ value|filter_name:参数}}
{{ value|default:"默认值"}}                    # 当value没有传值时,拿默认值填充
{{ value|length}}                             # value的长度
{{ value|filesizeformat}}                     # 数字可转换为MB单位
{{ value|slice:"0:4"}}                        # value切片
{{ value|date:"Y-m-d H:i:s" }}                # value时间格式化
{{ value|safe }}                              # 若果是标签格式,具有标签效果
{{ value|truncatechars:4 }}                   # 从第四个字符截断...
{{ value|truncatewords:4 }}                   # 从第四个单词截断...
{{ value|cut:' ' }}                           # 移除(字符)空格  
{{ value|join:'-' }}                          # 字符串拼接

3.3 模板标签

3.3.1 for 标签

{for i in lst}
<h1>i</h1>
如果lst为空,或者后台没有给lst数据,那么就展示empty下面的内容
{% empty %}  
<span>哥,啥也木有啊</span>
{% endfor %}

### forloop

forloop.counter            当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
forloop.counter0           当前循环的索引值(从0开始)
forloop.revcounter         当前循环的倒序索引值(从1开始)
forloop.revcounter0        当前循环的倒序索引值(从0开始)
forloop.first              当前循环是不是第一次循环(布尔值)
forloop.last               当前循环是不是最后一次循环(布尔值)
forloop.parentloop         本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等

3.3.2 if 标签(可以配合过滤器使用)

{% if 条件 %}

{% elif 条件 %}

{% else %}
{% endif %}

3.4 模板导入(组件)

导入组件
{% include '组件.html' %}

3.5 静态文件配置

# 静态文件:拿来就可以使用的(img,css,js...)
将html文件放到templates文件夹下
1,在项目根目录下创建statics文件夹(img,css,js,other)

2,在settings.py文件中设置如下内容

STATIC_URL = '/static/'        # 路径别名
STATICFILES_DIRS = [os.path.join(BASE_DIR,'statics'),]    # 找到static_file 路径这里

引入方式一:
   1,<link rel="stylesheet" href="/static/img/static_file.img">
   2,{% load static %}
     <link rel="stylesheet" href="{% static /static_file.img %}">
   
3,<img src="/static/img/1.png" alt="">    # img标签路径设置

3.6 模板继承

# 模板(母版.html页面)

划分子板可能要添加内容的区域
{% block content%}
要添加内容的区域
{% endblock %}

# 继承模板
{% extends '母版.html页面'%}

{% block content%}
子板要修改的内容
{% endblock %}

# 总结:
{% block css%}  等同样适用

4,ORM(Object Relational Mapping)

# 链接数据库
1,创建库
create databases dbtext01;
2,修改配置(settings.py)
DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.mysql',
       'NAME': 'dbtext01',
       'HOST': '127.0.0.1',
       'PORT': 3306,
       'USER': 'root',
       'PASSWORD': "123456"}}
3,配置pycharm数据库显示
4,项目同名文件夹下的__init__配置
import pymysql
pymysql.install_as_MySQLdb()
   
# orm语句特点

1,惰性查询  res = models.Book.object.all()   # 不会去查
print(res)                              # 用的时候才查
   
2,查询优化
   # only
   res = models.Book.object.only(title)    # 获取所有对象,显示title字段,for循环时,查看title不走数据库
   # defer
   res = models.Book.object.defer(title)   # 与only刚好相反
   
   # 跨表查询相关
   select_related("联表")    # 联表join查询出来的数据,再次查询时,不会走数据库(只能放外键字段,一对一,一对多)
   prefetch_related("联表")  # 子查询in

4.1 单表操作

# 常用字段属性
1,null
如果为True,Django 将用NULL来在数据库中存储空值。 默认值是 False.
blank
如果为True,该字段允许不填。默认为False。要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。

2,default
字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值

3,primary_key
如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key=True

4,unique
如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的

5,choices
由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
6,db_index
  如果db_index=True 则代表着为此字段设置数据库索引。

# DatetimeField、DateField、TimeField这个三个时间字段,都可以设置如下属性。
7,auto_now_add
   配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

8,auto_now
   配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。

### choices属性
sex = models.IntegerField(choices=((1, '男性'), (2, '女性')))

数据库里面存的是1或者2
通过model模型类对象.get_属性名称_display()可以获取到数字对应的文本内容


# 创建字段
class Book(models.Model):
   title = models.CharField(max_length=32)    # varchar(32)
   price = models.DecimalField(max_digits=5,decimal_places=2)   # decimal(5,2)
   pub_date = models.DateField()      # date
   publish = models.CharField(max_length=32)

# 添加字段
       age = models.IntegerField()
       1,命令行添加默认值
       2,可以为空   null = True
       3,自己添加默认值  default = "18"
       
# 修改字段
  直接修改,再执行迁移命令
       
# 删除字段
  注释掉,再执行迁移命令(数据即消失)
   
# 数据库迁移
python manage.py makemigraitons (将操作记录记录到migrations文件下)
python manage.py migrate         (将操作记录记录同步到数据库)

4.1.1 单表增

1,配置路由
2,views写逻辑
3,访问网页

def home(request):

   ### 方法一
   obj = models.Book(
       title='西游记后传',
       price=2.8,
       # pub_date='2000-08-12', #这样的格式字符串
       pub_date=datetime.datetime.now(),  #时间日期类型
       publish='31期红浪漫出版社',
  )
   obj.save()
   
   ### 方法二
   models.Book.objects.create(
       title='西游记前传',
       price=3,
       pub_date=datetime.datetime.now(),
       publish='夕阳红出版社',
  )
   
   ### 批量增加
   bj_lst = []
   for i in range(10):
       obj = models.Book(
           title=f'西游记前传{i}',
           price=4,
           pub_date=datetime.datetime.now(),
           publish='夕阳红出版社',
      )
       obj_lst.append(obj)
   models.Book.objects.bulk_create(obj_lst)
   
   
   return HttpResponse("ok")

4.1.2 单表改

def home(request):
### 方法一
   models.Book.objects.filter(id = 2).update(price = "5.88")
   models.Book.objects.filter(id = 2).update(**kwargs)
### 方法二
   obj = models.Book.objects.get(id = 3)
   obj.price = 9.99
   obj.save()
   return HttpResponse("ok")

4.1.3 单表删除

def home(request):

   models.Book.objects.filter(id = 1).delete()

   return HttpResponse("ok")

4.1.4 单表查询

# QuerySet 对象(类似于列表对象)
models.Book.objects.filter()                         # 所有记录
models.Book.objects.all()                            # 所有记录
models.Book.objects.filter(id = 5)                   # 筛选记录
### 双下划线模糊匹配语法(字段__方法=“val”)
   startswith           # 开头
   endswith             # 结尾
   contains             # 包含
   in                   # 内
   range                # 区间
   year                 # 年
   mouth                # 月
   gt/gte               # 大于
   lt/ite               # 小于
   i                    # 不区分大小写
models.Book.objects.exclude(id=5)                    # 排除记录
models.Book.objects.order_by("id")                   # 记录排序
models.Book.objects.order_by("id").reverse()         # 排序后反转
models.Book.objects.filter(id=5).count()             # 筛选后计数
models.Book.objects.filter(id=5).values()            # 筛选后查看值(每一条数据为字典)
models.Book.objects.filter(id=5).values_list()       # 筛选后查看值(每一条数据为元组)
models.Book.objects.all().values("price").distinct() # 记录去重

# models.Book 实例对象
models.Book.objects.get(id=5)                   # 只查一条(多少都报错)
models.Book.objects.filter(id=5).first()        # 第一条
models.Book.objects.all()[0]                    # 第一条
models.Book.objects.filter(id=5).last()         # 最后一条

# 记录
models.Book.objects.filter(id=5).exists()       # 有无这条记录

4.2 多表操作

注意事项:ForeignKey(db_constraint = False)   取消强制约束效果(级联删除)


# 创建表
from django.db import models

# 作者表
class Author(models.Model): #比较常用的信息放到这个表里面
   name=models.CharField( max_length=32)
   age=models.IntegerField()  #int
   # 与AuthorDetail建立一对一的关系,一对一的这个关系字段写在两个表的任意一个表里面都可以
   ad = models.OneToOneField(to="AuthorDetail", to_field='id', on_delete=models.CASCADE)     # 自动加_id

# 作者详细信息表
class AuthorDetail(models.Model):#不常用的放到这个表里面
   birthday=models.DateField()
   telephone=models.CharField(max_length=11)
   addr=models.CharField(max_length=64)


# 出版社表
class Publish(models.Model):
   name=models.CharField( max_length=32)
   city=models.CharField( max_length=32)


# 书籍表
class Book(models.Model):
   title = models.CharField( max_length=32)
   publishDate=models.DateField()
   price=models.DecimalField(max_digits=5,decimal_places=2)
   publish=models.ForeignKey(to="Publish") # 自动加_id 默认级联删除,默认关联的是另外一张表的主键字段
   authors=models.ManyToManyField(to='Author',) # 多对多外键建议放到查询频率多的一方,自动创建第三张表,id author_id book_id,不会作为本表的字段出现

 

4.2.1 多表增加

# 一对多 (书与出版社)  外键字段在书籍表
1,直接写实际字段
models.Book.objects.create(
       title=data["title"],
       price=data["price"],
       publishDate=data["publishDate"],
       publish_id = 1,)
2,先获取外键对象,再指定外键值(自动获取主键值)
obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.create(
       title=data["title"],
       price=data["price"],
       publishDate=data["publishDate"],
       publish_id = obj,)
   
# 多对多 (作者与书) 操作第三张关系表
1,拿到book对象
book_obj = models.Book.objects.get(id=1) # 拿到书籍id为1的对象,给他添加做作者
2,添加另一张表的id字段
book_obj.authors.add(1,2) # 拿到了第三张表的字段authors,实际上拿到了第三张表,添加id为1,2的俩位作者,同样支持放对象

4.2.2 多表更新

# 一对一和一对多
models.Author.objects.get(id=1).update(name = 'bajie')

# 多对多修改
ret = models.Book.objects.get(id=2)
ret.authors.set([1,])         # 只有一个值,先删除再添加,如果有就不动,必须是可迭代对象

4.2.3 多表删除

# 一对一和一对多 ,基本和单表一样(级联删除)
models.Author.objects.get(id=1).delete()
models.AuthorDetail.objects.get(id=2).delete()
models.Book.objects.get(id=1).delete()

# 多对多删除
ret = models.Book.objects.get(id=2)
ret.authors.clear()                 # 清空该书籍对应的第三张表中的记录
ret.authors.remove(3,4)             # 指定删除该书和哪些作者的关系

4.2.4 多表查询

# 查询方向 :
正向:外键字段在Book,用Book查出版社为正向;否则为反向
   '''
  正向查询按字段
  反向查询按表名小写
  '''
       
# 子查询(基于对象的跨表查询)
# 正向
   book_obj = models.Book.objects.filter(pk=1).first()
   book_obj.publish.name     # 拿到了出版社对象(book与publish联表),用字段查
   """
  当结果可能有多个时,需要加 .all()
  如果为空,需要加all()
  """
   
   # 反向
   publish_obj = models.Publish.objects.filter(name = "山西出版社").first()
   res = publish_obj.book_set.all()
   """
  当查询结果有多个时需要加 _set.all()
  """
   
# 联表查询(基于双下划线的跨表查询)
"""
如果跨表,查到外键字段,那么直接跨到了外键字段关联的那张表;无限跨表
"""
# 正向(先筛选再关联)
   res = models.Book.objects.filter(pk=1).values("publish__name","addr")  # 可多值查询
   print(res)
   
   # 反向(先关联再筛选)
res = models.Publish.objects.filter("book__id" = 1).values("name","book__name")
   
   
# 聚合查询(aggregate)
   from django.db.models import Max,Min,Sum,Count,Avg
   # 通常情况配合分组使用
   models.Book.objects.aggregate(Avg("price"))
   
# 分组查询(annotate----group by)
'''分组之后,除了分组字段,其他字段都无法看到'''
   
'''
严格模式:
'''
   
# models 后面是什么,就按什么分组 ,只要是queryset对象就可以无限.
res = models.Book.objects.annotate()    # 按书分组
   
   # 方式一                         # 别名   个数 联表     继续过滤   获取值    
   res = models.Book.objects.annotate(n = Count("author")).filter().values(n)    # 按书分组
# 方式二
   res = models.Book.objects.values("price").annotate()   # 按照字段分组,先values,如果报错考虑严格模式
   
# F 查询
from django.db.models import F
# 同一张表俩列比较
   models.Book.objects.filter(点赞字段__gt=F("评论字段"))
   # 统一处理
   models.Book.objects.update(price=F('price') + 50)    # 价格统一加50元
   
# Q 查询
from django.db.models import Q
   # 处理filter参数有多个 and(,) , or(|) , not (~) 用Q包裹
   models.Book.objects.filter(~Q(price__gt=3)|Q(id = 1))
   # 高阶用法:
   q = Q()
   q.children.append("点赞字段__gt",100)
   q.children.append("评论字段__lt",60)
   models.Book.objects.filter(q)   # 默认是and关系
  修改关系:q.connector = "or"

4.3 锁与事务

# 原生SQL加锁 for update;
begin;                        # 开启事务
select * from t1 for update   # 加锁
commit;                       # 解锁

# ORM 加锁
from django.db import transaction     # 引入事务

@transaction.atomic       # (被装饰函数中的sql捆绑为事务)
def insert(requset):
       with @transaction.atomic()    # (被装饰函数中的sql捆绑为事务,小范围)
      models.Book.objects.filter(id=1).select_for_update()   # 加锁

4.4 ajax ( 异步提交,局部刷新 )

使用jquery封装之后的版本(需要导入jquery)
# 将提交按钮变为普通按钮取消刷新效果
   用户名:<input type="text" id="name"></input>
   密码:<input type="password" id="pwd"></input>
   <input type="button" id="btn">提交</input>
   
# 给提交按钮绑定事件
$("#btn").click(function(){
    # 获取数据
       var name = $("#name").val()
       var pwd = $("#pwd").val()
       $.ajax({
           url:"/longin/"                     # 不指定默认当前地址
           type:"post"                        # 请求方法
           data:{username:name,password:pwd}  # 提交数据
           dataType:true                      # 自动反序列化
           # 根据状态码判断请求报错与否
           success:function(res){  
               if (res === "ok"){
                   location.href= "跳转页面url"
              }
               elif (res === "error"){
                   做一些提示
              }
          }         # res 接受post请求返回的数据
           error:function(res){
               做一些效果展示啥的逻辑
          }
      })
})

4.4.1 ajax发送json格式数据

$(标签).click(function(){ 
   $.ajax({
       url:""
       type:"post"
       data:JSON.stringify({"name":"八戒"}), # 将数据转化为json格式
       contentType:"application/json"        # 指定发送json编码格式
       success:function(){},
       error:function(){},
  })
})
# 后端
request.is_ajax()           # 获取是否是ajax请求
   # json格式数据
   data_bytes = request.body                 # 才能获取到
   data = json.loads(data_bytes)             # 反序列化

4.4.2 文件上传

from表单上传

# form表单     
   1,mothed = "post"
   2,encype = "multipart/form-data"  # 文件分片发送
   
   
# 视图层
data = request.FILES.get("属性")        # 拿到文件句柄
data.name                               # 文件名字
with open(data.name , "wb") as f:
   for i in data.chunks:     # 读取数据不是按\n,默认65536B 64k,固定大小
       f.write(i)                          # 写入文件
       

ajax 文件上传

$(标签).click(function(){
   # 1,文件对象 f
   # 2,利用ForData处理对象
   var formdata = new FormData();
   formdata.append("key","普通数据");
   formdata.append("key",f)
   
   $.ajax({
       url:""
       type:"post"
       data:formdata,
       processData:false,     # 不需要任何处理
       contentType:false,     # 不需要任何编码,自动识别formdata对象
       success:function(args){},
       error:function(args){},
  })
})

# 后端

data = request.FILES.get("key")        # 拿到文件句柄
data.name                               # 文件名字
with open(data.name , "wb") as f:
   for i in data.chunks:     # 读取数据不是按\n,默认65536B 64k,固定大小
       f.write(i)                          # 写入文件

4.5 cookie与session

服务端保存在客户端浏览器上的信息称之为    cookie
数据保存在服务端上的信息称之为           session
服务端不保存数据,加密处理后发送给客户端   token

cookie操作

# 保存用户登录状态
obj = redirect("/home/")
# 让浏览器记录cookie数据(设置)
obj.set_cookie(k,v)
# 设置多组
  obj.set_cookie(k,v,max_age = 3)  # 3秒过期
       # 加盐
      obj.set_signed_cookie(k,v,"盐")
       # 获取
      request.get_signed_cookie(k,salf)
   # 修改(相同键设置不同的值)
  obj.set_cookie(k,xx)  
   # 删除
  obj.delete_cookie(k)  
# 返回值(登录之后才能看到的页面)
return obj
# 获取cookie
request.COOKIES.get(k)

# 注意点
1,明文存储
2,大小限制(一个浏览器最多保存20个cookie)

session

1,密文存储
2,大小无限制
3,数据在服务端数据库

# 设置(可以设置多条)
'''django表中数据,同一个计算机上同一个浏览器只有一条/节省资源'''
request.session[k] = v
   1,操作session,django会自动生产一张表:django_session(key,values,过期时间(默认14天))
   2,生产一个随机字符串key,对应的值
   3,序列化加密,保存到django-session表中
   4,将随机字符串返回给客户端浏览器保存
# 获取
request.session[k]
request.session.get(k)
   1,获取sessionid对应的字符串
   2,拿着字符串去数据库查找对应数据
   3,娶不到,返回None
# 设置过期时间
request.session.set_expiry()
1,整数      
   2,时期对象    到期失效
   3,0          窗口关闭失效
   4,不写       即默认
# 删除(注销)
request.session.delete()     # 只删除服务端
request.session.flush()      # 都删

5, 中间件(MIDDLEWARE)

# 自定义中间件
   1,app下创建文件夹mymidd,xx.py文件

   from django.utils.deprecation import MiddlewareMixin

   class Auth(MiddlewareMixin):
       def process_request(self,request):  # 执行中间件
           print("中间件请求执行了")
           # 如果返回三板斧,不继续,原路返回(不允许访问)
           
       def process_view(self,request,view_func,...):
           print(view_func)             # 要执行的视图函数对象;
           return HTTPResponse("嘿嘿嘿") # 如果返回了HTTPResponse,那么视图函数就不走了
           
       def process_exception(self,request,exception):
           # 要执行的视图函数对象请求错误时执行
           print(exception)    # 打印报错信息
           
       def process_template(self,request,response):
           # 没什么用
           
       def process_response(self,request,response):
           print("中间件响应执行了")
           return response            # 视图函数响应对象
      # 默认返回形参response
       
   2,配置setting文件 MIDDLEWARE(从上到下执行中间件)
       "app.mymidd文件夹.xx文件.方法"    # 每次请求来了自动执行

5.1 csrf(跨站请求伪造)

"""
钓鱼网站:
假中国银行         用户       真中国银行
"""
form 表单解决 # post请求
{% csrf_token %}    

ajax 解决
"""引入静态文件,"""
$("#d1").click(function(){
       url:"",
       type:"post",
       # 第一种
       data:{数据key:数据value,"csrfmiddlewaretoken":"{{ csrf_token}}"}
       # 第二种 引入静态js文件
       data:{数据key:数据value}
       success:function(){}
  })

# 装饰器
     from django.views.decorators.csrf import csrf_protect,csrf_exempt

   
   
FBV
# csrf_protect   需要校验
# csrf_exempt   忽视校验

CBV模式
@mothed_decorator(csrf_protect,name = "方法")
csrf_exempt    只能给dispath加

django外部脚本调用django环境

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "database.settings")    # 去 manage.py 找

import django
django.setup()

from app01 import models

正文

 

 

 

posted @ 2020-09-23 08:19  bajie_new  阅读(251)  评论(0编辑  收藏  举报