前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

Django

作者头像
Dean0731
发布2020-05-08 15:41:41
3.4K0
发布2020-05-08 15:41:41
举报
文章被收录于专栏:blog-技术博客blog-技术博客

1,http

小提示:"{:0>3}".formate(9) 右对齐若小于3位 --->00n 0位占位符,> 表示右对齐

响应格式

请求格式

代码语言:javascript
复制
import socket
import os
# =========================================================
def ret(path):
    dir = "../html/"
    file = os.path.join(dir,path.strip(r"[/\]"))
    if os.path.exists(file):
        with open(file,"rb") as f:
            return f.read()
    else:
        with open(os.path.join(dir,"error.html"),"rb") as f:
            return f.read()
# =========================================================
sk = socket.socket()
sk.bind(("127.0.0.1",8080))
sk.listen()
while True:
    conn,_ = sk.accept()
    data = conn.recv(8096)
    data_str = str(data,encoding="utf8")
    list = data_str.split("\r\n")
    # for i in list:
    #     print(i) # 获取每行,还可以通过 空格分隔 获取访问路径,根据路径返回不同那内容
    # # 通过请求路径,建立字典,对应但会数据,可直接返回
    firstLine = str(list[0]).split(' ')
    temp = firstLine[1].split("?")
    path = temp[0]
    #print(path)
    conn.send(b'http1.1 200 \r\n\r\n')
    conn.send(ret(path))
    conn.close()
sk.close()
"""
# http 请求
GET /sadasd/?name=dzf HTTP/1.1\r\n
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36\r\n
Sec-Fetch-Mode: navigate\r\n
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3\r\n
Sec-Fetch-Site: none\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7\r\n\r\n'
"""
# =========================================================
"""
Python中 Web框架的分类:
1. web框架的本质:
    socket服务端  与 浏览器的通信
2. socket服务端功能划分:
    a. 负责与浏览器收发消息(socket通信)  --> wsgiref/uWsgi/gunicorn...  自己写的长时间连接会报错
    b. 根据用户访问不同的路径执行不同的函数
    c. 从HTML读取出内容,并且完成字符串的替换(动态网站的本质)  --> jinja2(模板语言)
1. 按上面三个功能划分:
    1. 框架自带a,b,c                 --> Tornado
    2. 框架自带b和c(和jinja2类似),使用第三方的a(wsgiref)    --> Django
    3. 框架自带b,使用第三方的a和c(jinja2)   --> Flask
2. 按另一个维度来划分:
    1. Django   --> 大而全(你做一个网站能用到的它都有)
    2. 其他     --> Flask 轻量级
"""
# 安装jinja2
from wsgiref.simple_server import make_server #   a 功能
from jinja2 import Template # c功能
​
​
def index():
    with open("09 jinja2版web框架.html", "r", encoding="utf-8") as f:
        data = f.read()
    template = Template(data)  # 生成模板文件
    # 从数据库中取数据
    import pymysql
    conn = pymysql.connect(
        host="127.0.0.1",
        port=3306,
        user="root",
        password="123456",
        database="day59",
        charset="utf8",
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    cursor.execute("select * from userinfo;")
    user_list = cursor.fetchall()
    # 实现字符串的替换
    ret = template.render({"user_list": user_list})  # 把数据填充到模板里面
    return [bytes(ret, encoding="utf8"), ]
def home():
    with open("home.html", "rb") as f:
        data = f.read()
    return [data, ]
# 定义一个url和函数的对应关系
URL_LIST = [
    ("/index/", index),
    ("/home/", home),
]
def run_server(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 设置HTTP响应的状态码和头信息
    url = environ['PATH_INFO']  # 取到用户输入的url
    func = None  # 将要执行的函数
    for i in URL_LIST:
        if i[0] == url:
            func = i[1]  # 去之前定义好的url列表里找url应该执行的函数
            break
    if func:  # 如果能找到要执行的函数
        return func()  # 返回函数的执行结果
    else:
        return [bytes("404没有该页面", encoding="utf8"), ]
​
if __name__ == '__main__':
    httpd = make_server('127.0.0.1', 8000, run_server)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()
"""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
​
​
<table border="1">
    <thead>
    <tr>
        <th>ID</th>
        <th>用户名</th>
        <th>密码</th>
    </tr>
    </thead>
    <tbody>
    {% for user in user_list %}
    <tr>
        <td>{{user.id}}</td>
        <td>{{user.name}}</td>
        <td>{{user.pwd}}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>
</body>
</html>
"""

2 django基础

代码语言:javascript
复制
# ==============================================================================
# 安装  pip install Django==2.2.4
# setting 中添加库 https://pypi.tuna.tsinghua.edu.cn/simple/ 防止time out
# cmd 新建项目 进入目标目录 django-admin startprojext project_name
# 或pycharm 新建Django 使用存在的解释器,第二个
# # 项目配置
"""
1,urls.py
urlpatterns:保存了路径与函数的对应关系
    在该文件中定义新的项,并写函数,支持正则
    也可以建立专门的函数文件,只需在urls 中导入即可
    import django.shortcuts import HttpResponse
    def admin(request): # request为所有请求的参数
        return HttpResponse("xxx)
    patterns,函数内容都可以动态修改,
项目启动
普通启动后,只能127.0.0.1 访问
若要使用ip访问,allowed_host = ['*'] runserver 0.0.0.0:80
1,cmd中python manage.py runserver [port]
2,选择项目 ,点击旁边三角 edit config 也可改端口
template下建立html文件
所有与html文件有关的设置都放在 setting的templates下
如何那绝对路径:在/下建立文件 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
指定html文件目录:'DIRS': [os.path.join(BASE_DIR, 'templates')]
    用到的时候 直接写文件名即可,"./写template",或"./xx/xx.html"
    不能直接写文件名
返回方式:
    字符:直接写或文件--->字符 打开文件 字节返回
    文件使用模块: render(request,"文件路径")
    return render(request,"Hello.html") # 此处可直接写文件名
此处注意,若在template下有多级文件夹,文件夹下有文件,此时访问 只写(xxx/xx.html) 不用加"/",以文件夹开头即可
​
对于static下的文件
​
2,配置静态文件,js,css等
setting 最后添加
    STATICFILES_DIRS=[
        os.path.join(BASE_DIR,"static") # static 为自己制定的文件夹,名字随意,可配置多个
    ]
STATIC_URL="/static/" 就代表的是  "D:/xxx/yy/static/"  别名 若有多个都当做在static下
html引用时使用绝对路径就不用从头开始写
    例:href="/static/bootstrap/css/bootstrap.min.css"
3,若出现403   中间价问题
    注释settings中47行 'django.middleware.csrf.CsrfViewMiddleware',
4,连接数据库,后边详细
"""
# 登录时,一个函数处理即可,若为get 表示请求html,若为post,处理数据,返回页面
# if request.method=="POST" "GET"
# 默认的页面请求是get,a标签也是get
​
"""
def 
    if post:
        处理
    return html
    
render(request,"xx.html",{"msg":"xxx"})   html中使用{{msg}}可获取
​
redirect 模块 跳转
return redirect("http://www.baidu.com") # 让浏览器请求新的页面,不是服务器返回的
return redirect("/login/") # 本网站  用"/"包裹
​
"""
# ===============================================
# app:方便在项目中管理实现不同的业务功能
"""
    project -->项目 (学校)   
    app --> 学院(软件学院,量子力学)
    1,创建app 
        在cmd ,某个project 根目录 python(3) manage.py startapp app_name
        执行后会在根目录下创建文件夹 app_name
        文件夹 migrations
        文件 __init__.py
            admin.py:管理控制台
            apps.py:app相关的配置
            models.py:ORM的类  entity
            tests.py:测试文件
            views.py:函数文件
    2,或在创建项目的时候直接添加一个
settings 
    INSTALLED_APPS 配置,添加上"app_01"
    或"app_01.apps.App_01Config" 类 推荐
"""
# =============================================
# ORM 简单,开发效率高, 执行效率低
# 不能创建数据库
# 步骤
"""
1,创建数据库
2,setting 配置数据库
DATABASES = {
    'default': {
        #数据库类型
        'ENGINE': 'django.db.backends.mysql',
        'HOST':'127.0.0.1',
        'PORT':3306,
        'NAME':'test',
        'USER':'root',
        'PASSWORD':'xxxx'
    }
}
3,告诉Django用什么连接数据库??MYsqlDB(不支持python3), pymysql
    mysqldb是默认的,需要更改为pymysql
    项目下,__init__.py 不是app的init 
        import pymysql
        pymysql.install_as_MySQLdb()
4,创建类 modules.py 必须在个文件,必须继承(models.Model)
class UserInfo(models.Model):
    id = models.AutoField(primary_key=True)  # 创建一个自增的主键字段
    name = models.CharField(null=False, max_length=32,unique=True)   # 创建一个varchar(20)类型的不能为空的字段
5,创建表
    创建后 不能修改,若要修改只能通过 modules修改,不然函数调用会报错
    1. python3 manage.py makemigrations  # 记录moduls 的变化,会记录在app/migrations下
    2. python3 manage.py migrate # 转变为sql执行
    可能pymsql驱动的mysqlclient客户端版本过低,修改G:\Program\Python\Python3.7.4\Lib\site-packages\django\db\backends\mysql\base.py
    注释掉如下,但还有错误 str 编码错误,还要修改operations.py
    # if version < (1, 3, 13):
    #    raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)   # 需要更换pymsql
    或
    下载mysqlclient,手动下载安装 https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient
    mysqlclient‑1.4.4‑cp37‑cp37m‑win32.whl  37为对应版本,还有显卡版本 注意app一定要在setting注册 否则会失败 # init 中不用写了
6, 会创建很多表,默认实体表名为 app_name_class_name 还有其他权限表,会话表等
"""
# ========================================================
"""
    request.GET[POST] 大字典
    在函数中获取数据库中数据
    from app_01 import modules
    ### 查询所有的数据
        ret = modules.Userinfo(类名).objects.all().order_by('id') 列表返回 userinfo对象,并根据id排序
        
        ret[0].id 或name 即可得到对应数据
        使用render传入html即可
    ### 创建
        modules.Userinfo(类名).objects.create(name="xxx")
    ### 删除
        request.Get.get("id",None)
        ret = modules.Userinfo(类名).objects.get(id="xxx") 请求不到会报错,可以使用 filter(id="xxx")
        ret.delete()
    ### 修改
        request.Get.get("id",None)
        ret = modules.Userinfo(类名).objects.get(id="xxx") 请求不到会报错,可以使用 filter(id="xxx")
        ret.name = new_name
        ret.save() # 提交到数据库
        
"""

3 django web实例

代码语言:javascript
复制
# 1,get 携带数据最大40k url长度不同浏览器不同2k-8k
# 2,... makemigrate app_name 只有一个时可省
# 3,外键
"""
class A(modules):pass
class B(modules):
    public = modules.Foreignkey(to=A) # A必须在前面存在
    public = modules.Foreignkey(to="A") # 没要求,只要最后有A即可
    最后 public列在库中名为 public_A主键名,好像是这个如果不是的话就是
    public_id,(好像这个可能比较大)
注:存入的时候public存的是A的id,使用create(public_id=xxx)
或使用  create(public=查到id的对象)
但获取get() B对象时 获取到所有属性,public 这个属性对应的是一个对象,若要获取某个属性,需再次加点
"""
# 4,数据库中已存在数据,此时修改modules,例如添加列,
# 会指定让你输入默认值,或直接在modules中 default="xxx"
# 5,多对多关系,需要第三张表  (id,table_id,table2_id)
"""
# 例如作者,书
    class book(modules):pass 只写 属性即可
    class auther(modules):
        .....
        book=modules.ManyToMany(to="book")
        
        auther 类执行后会生成2个表
            第一张:app_name_auther,注意没有book属性
            第二张:app_name_ManyToMany所在类名_赋值名(book)
                属性:id ,auther_id,book(book类名)_id
例:查询某个作者
1,先ret = get(id=x)得到作者
2,ret.book(是上边的manytomany的book).all() 帮助查询关联的对象 
控制台打印all 有括号 列表返回所有书对象
for 显示的时候 for b in  ret.book.all 没有括号
"""
# 6,request.POST.get("xxx") 若xxx中多个参数 返回值列表中对后一个
#   使用getlist("xxx") 获取列表
# 7,添加作者并关联存在的书本
#   author =....creat(name=...等属性赋值)  注意没有book
#   author.book(manytomany那个book).set(getlist中得到的books列表)
#   注意不用save()
# 8,删除作者 普通的删除,只不过是关联删除,先删书,再删作者
# 9,更改作者,与普通更改相同,获取目标对象obj,修改普通属性,
#   再obj.book.set(获取到的list) obj.save()

4,MVC

代码语言:javascript
复制
# 在python中称为MTV
# module(modules),
# view(Templates)
# controller(urls,views),
# 母板
"""
1,新建公共html
    ....
    {# 这里是页面不同部分 #}
    {% block  page_main(名字随意) %}
    {% endblock %}
    ....
2,建立子html
    {% extends "base.html路径"%}
    {% block page-css %}{% endblock%}
    {% block page-main %}<h1>直接写即可,不用body等标签</h1>{% endblock%}
    {% block page-js %}{% endblock%}
用处:1,替换固定的模板内容
    2,替换某个html专用css ,其实在子html中可直接加入cssdeng
        但会造成css位置混乱,此方法可使css等都位于head标签
注意:
    1,模板不能嵌套,
    2,extends行一定在第一行, 路径必须加引号
    3,可有多个block,一般3个
    4,views中返回的是子html,不是base.html
"""
# 导入组件:就是替换
"""
    将导航条放入单一功能模块
    {% include "xxx.html" %}
"""
# 引入静态文件
"""
    若static别名更改,引入的css等路径都要更改
    解决方案: 路径拼接
        {%load  static%}
        <link href="{% static 'bootstrap/xxx'%}" rel="stylesheet>
        或者
        {%load  static%} 也要导入
        <link href="{%get_static_prefix%}bootstrap/xxx" rel="stylesheet>
多次使用的图片
{% load static%}
{%static 'xxx.jpg' as yy%}
<img src="{{yy}}"/> 即可
"""
# simpletag
"""
复杂的filter
路径是实在app下templatags下
from...
register...  注意register不能更改
@register.simple_tag(name="xx") 可不指定名字默认是函数名
def my_sum(arg1,arg2,arg3):
    return arg1+arg2+arg3
​
html使用
{%load xxx文件%}
{% xx arg1 arg2 arg3 %}
"""
# inclusion_tag 返回html代码
"""
    与simple类似
@register.inclusion_tag("xxx.html") 注意此处没有name ,调用使用函数名,向下12行
def my_inclusion(arg1):
    data = 处理参数args,变为其他数据,列表,字典等
    return {"result":data}
xxx.html
<ui>
{% for i in result %} # 加入为迭代对象
    <li>{{i}}</li>
{%endfor%}
</ui>
调用{{my_inclusion arg}} 
"""
​
# ======================================
# view(接受响应的部分)
# CBV(基于类的视图) FBA(基于函数的视图:前面的都是)
"""
form django.views import View
class add_list(View): 
    # urls调用时使用类名add_list ,会根据请求方式转到对应方法
    def get(self,request):pass
    def post(self,request):pass
urls 中
    path("xx",add_list.as_view()) 调用
"""
# request
"""
request.method
request.GET
request.POST
request.path_info  "/xxx/yy/" 形式,不带ip,端口,参数
request.body 
    若为get     ---->b''
    若为post    ----->b'提交的参数名=值(若为中文会变成%E6879AS7D54%等编码数据)'
"""
# =============================================
# 上传文件
"""
    form 注意使用post 还有enctype="multipart/form-data"
    def upload(request):
        request.FILES 字典,{"file1":obj,"file2",obj}
        filname =request.FILES['表单中name'].name
        with open0.....
            for i in request.FILES['表单中name'].chunks()
                f.write(i)
"""
# ===============================================
# response
""""
1,HttpResponse
2,render
3,redirect
​
4,返回json
import json
return HttpResponse(json.dumps(xxx)) 返回json字符串
或
from django.http import JsonHttpResponse # 封装的json ,不能串list
return JsonHttpResponse(xxxx)直接返回
    若要传list JsonHttpResponse(xxxx,safe=False) 即可
"""

5,django 路由系统

代码语言:javascript
复制
# 路由系统
"""
urlpatterns=[
    url,path(2.0以后)(正则,函数名,参数,别名)
]
    r"^book/[0-9]{2,4}/$"
    r"^book/([0-9]{2,4})/([a-zA-Z]{2})/$"
分组匹配时,会把分组的内容当做参数传入:位置参数
    例: book/11/ac   对应函数应该为(request,arg1,arg2) 接受
    <(?P<name1>\w*)> 匹配"<里边是字符>"  (?P=name1) 复制匹配规则
多路径匹配, 最后注意加  /  $
    对于路径上的"/" 最后会默认添加"/" 若要取消
    settings APPEND_SLASH=False
​
分组命名匹配
    r"^book/(?P<year>[0-9]{2,4})/(?P<month>[a-zA-Z]{2})/$"
    def fun(request,year,month) 要明确变量
    def fun(request,**kwargs) 也可 接收到kwargs为{"year":xx,"month":yy}
    注意不能混用,若month不写,后边分组匹配不到
多个路径对应一个函数:通常适用于 无参时访问第一页,有参访问对应页面
    def  fun(res,id="1"):指定默认值即可
​
app中建立app01_urls.py 名字无规定
    import django.urls import url
    urlpatterns=[]  必须有这个属性
在主urls中导入
    from ... import app01_urls
    urlpattrens=[
        ...
        url(r"^app01/",include(urls)) # 所有以app01开头的  分流
    ]
    查找时 /app01/xx/yy 注意为r"^app01",后边没有"/" 会报错
注:url(xxx,yy,{"age":18}) 对应的yy函数 使用def yy(req,age)
    可以传参,但不常用
"""
# 页面之间跳转的时候 不能写死跳转路径:反向解析 ->通过别名方式
# 命名url与url解析:urlpattern中的url会发生变化,html中写死了
#   url(xx,yy,name="zzz") 此时html中 写 href="{url 'zzz'}" 相当于xxx  即可跳转到yy函数
# 若在函数中跳转,也不能写死
#   from django.urls import reverse
#   analysis_url=reverse("zzz")
#   return redirect(analysis_url)
# 注意对于传参数的url 需要传参数
#   reverse("zzz",kwargs={"xx":1,"yy":2}) 当分组有别名时字典传入,若不是 args=(..) 元祖传入即可
#   {% url 'zzz' arg1 arg2 ...%}
# 在不同的app中了能会出现相同的别名
#   可以再父urls中  url(xx,include(app01_urls.py,namespace="app01"))
#       html {% url 'app01:zzz'%} 找到app01 里面的别名zzz
# ==========================================
# orm 配合 路由系统
"""
    1,不同的表的删除,可以使用一个方法:
    url(r"^delete/([a-zA-Z]+)/(\d)/$",delete) 传递表名,id
    对于比较长的正则,可以建文件夹,编译 r = re.complie(xxx),再引入即可
    2,def fun(res,arg1,arg2):
        hasttr(py文件,"xxx") getattr(py文件,"xxx")得到目标
        if hasattr(modules,arg1.capitalized()) 首字母打大写
            cls = get....
            cls.Object.get(id=arg2).delete try本句
"""
# ==========================================
# orm常用字段 charfiled 对应varchar,没有固定长度的字段,可自定义
"""
class FixedCharField(models.Field):
    自定义的char类型的字段类
    def __init__(self, max_length, *args, **kwargs):
        self.max_length = max_length
        super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs)
​
    def db_type(self, connection):
​
        限定生成数据库表的字段类型为char,长度为max_length指定的值
        return 'char(%s)' % self.max_length
class Person(models.Model):
    name = models.CharField(max_length=32)
    new_name = FixedCharField(max_length=64, default="张三")  # char(64)
    age = models.IntegerField(default=18)
    birthday = models.DateField(auto_now_add=True)
​
    def __str__(self):
        return self.name
​
    class Meta:
        db_table = "person" 指明 生成的数据库名
​
​
"""
#   1,AutoField int自增列,必须primary_key=True,若没有自增列,会自动创建id自增列
#   2,IntegerField 整数范围 21亿那个
#   3,CharField 必须max_length, 指定长度
#   4,DateTimeField 相当于datetime模块
#       yyyy-mm-dd hh:MM[:ss[.uuuuu]][TZ]
#   5,DateField
#          auto_now_add=True 创建记录时会添加当前是时间,不用写default
#          auto_now=True 每次更新记录时会更新该字段
#  不常用字段
#   BigAutoField,大整数
#   SmallIntegerField 小整数 -32768-32767
#   PositiveSmallIntegerField 正小整的 0-32767
#   PositiveIntegerField 0-21亿
#   BigIntegerField -922..... ---  922....
#   BooleanFiled
#   NullBooleanField 可为空的bool
#   TextField 大文本
#   EmailField 还是charfiled django做了校验
#   IPAddressField 有验证
#   GenericIPAddressField 支持ipv4,ipv6
#   URLFiled charfiled 验证
#   SlugFiled 字符串类型,字母数字下划线连字符等
#   CommaSeparatedIntegerFiled 格式为逗号分割的数字
#   UUIDField UUID验证
#   TimeFiled
#   DurationFiled 长整数,时间间隔orm中获取到的类型为datetime.timedel类型
#   FloatField 浮点型
#   DecimalField 10进制小数
#       max_dights,小数总长度,decimal_places,小数位长度
#   BinaryField 二进制数据
# =========================================
# 字段参数
#   null 没写=True 表示不能为空
#   unique
#   db_index=true 表示为此字段设置索引
#   default
#   to 设置关联的表
#   to_field="xxx" 设置关联的列 默认是id
#   related_name 反向操作时使用的字段名,用于代替反向查询时的"表名_set"
#   related_query_name 反向查询操作时,使用的链接前缀,用于替换表明
#   on_delete 当删除关联表中的数据时,当前表与其的关联行为
#       modules.Cascade 关联删除 默认的
#       modules.DO_NOTHING 引发Integrity错误
#       modules.PROJECT 引发protected错误
#       modules.SET_NLL 关联的字段置位NULL(前提字段可空)
#       modules.SET_DEFAULT 关联的字段为默认值(前提字段有默认值)
#       modules.SET(func) 可自定义函数
#   db_constraint=Flase 用上了外键,但是没有级联操作,
#   软外键:方法1,代码实现 方法2,db_constraint=Flase
# ======================================
# class Mate:
# db_table 重写表名
# index_together 联合索引   2列做索引
# unique_together 联合唯一索引 2列可以有一个重复,不能都重复
# ordering 指定an什么字段排序,设置了该属性,结果才可以reverse() 

5_orm_1

代码语言:javascript
复制
# ORM小练习 如何在一个Python脚本或文件中 加载Django项目的配置和变量信息
# 常用的查询方法
import os
if __name__ == '__main__':
    # 加载Django项目的配置信息
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ormday69.settings")
    # 导入Django,并启动Django项目
    import django
    django.setup()
​
    #  from app_01 import models
​
    # # 查询所有的人
    # ret = models.Person.objects.all()
​
    # # get查询
    # ret = models.Person.objects.get(name="小黑") 只查询到 第一个
​
    # # filter
    # ret = models.Person.objects.filter(id=100)  # 不存在返回一个空的QuerySet,不会报错
    # # 就算查询的结果只有一个,返回的也是QuerySet,我们要用索引的方式取出第一个元素
    # ret = models.Person.objects.filter(id=1)[0]
​
    # print("exclude".center(80, "*"))  # 占80个字符居中,*号填充
    # # exclude
    # ret = models.Person.objects.exclude(id=1)  反向查询 id!=1
​
    # print("values".center(80, "*"))
    # # values 返回一个QuerySet对象,里面都是字典。 不写字段名,默认查询所有字段
    # ret = models.Person.objects.values("name", "birthday")
​
    # print("values_list".center(80, "*"))
    # # values_list 返回一个QuerySet对象,里面都是元祖。 不写字段名,直接写字段值,默认查询所有字段
    # ret = models.Person.objects.values_list()
​
    # print("order_by".center(80, "*"))
    # # order_by 按照指定的字段排序
    # ret = models.Person.objects.all().order_by("birthday")
​
    # print("reverse".center(80, "*"))
    # # reverse 将一个有序的QuerySet 反转顺序
    # # 对有序的QuerySet才能调用reverse
    # ret = models.Person.objects.all().reverse()
​
    # print("count".center(80, "*"))
    # # count 返回QuerySet中对象的数量
    # ret = models.Person.objects.all().count()
​
    # print("first".center(80, "*"))
    # # first 返回QuerySet中第一个对象
    # ret = models.Person.objects.all().first()
​
    # print("last".center(80, "*"))
    # # last 返回QuerySet中最后一个对象
    # ret = models.Person.objects.all().last()
​
    # print("exists".center(80, "*"))
    # # exists 判断表里有没有数据
    # ret = models.Book.objects.exists()
    # print(ret)
# ===================================================
​
    # 单表查询之神奇的双下划线
    # # 查询id值大于1小于4的结果
    # ret = models.Person.objects.filter(id__gt=1, id__lt=4)
# ===================================================
    # # in
    # # 查询 id 在 [1, 3, 5, 7]中的结果
    # ret = models.Person.objects.filter(id__in=[1, 3, 5, 7])
    # ret = models.Person.objects.exclude(id__in=[1, 3, 5, 7])  等于not in
# ===================================================
    # 模糊查询
    # # contains 字段包含指定值的
    # # icontains 忽略大小写包含指定值
    # ret = models.Person.objects.filter(name__contains="小")
    # isstartwith,startwith,endwith,isendwith
# ===================================================
    # # range
    # # 判断id值在 哪个区间的 SQL语句中的between and  1<= <=3
    # ret = models.Person.objects.filter(id__range=[1,3])
# ===================================================
    # # 日期和时间字段还可以有以下写法,按照日期中的某一项查询
    # ret = models.Person.objects.filter(birthday__year=2000)
    # ret = models.Person.objects.filter(birthday__year=2000, birthday__month=5)
# ===================================================
    # 注意 obj得到的是对象,不能直接.value或value_list
​
    # 外键的查询操作
​
    # 正向查询,通过有外键字段的表查没得是正向
    # 基于对象 跨表查询
    # book_obj = models.Book.objects.all().first()
    # ret = book_obj.publisher  # 和我这本书关联的出版社对象
    # ret = book_obj.publisher.name  # 和我这本书关联的出版社对象
​
    # 查询id是1的书的出版社的名称
    # 利用双下划线 跨表查询
    # 双下划线就表示跨了一张表
    # ret = models.Book.objects.filter(id=1).values_list("publisher__name")或value
# =================================================================
​
    # 反向查询
    # 1. 基于对象查询
    # publisher_obj = models.Publisher.objects.get(id=1)  # 得到一个具体的对象
    # # ret = publisher_obj.book_set.all() # 反向得到书的信息,默认是表名_set
    # 建表时通过related_name="books"可更改
    # ret = publisher_obj.books.all()
​
    # # 2. 基于双下划线
    # ret = models.Publisher.objects.filter(id=1).values_list("(related_query_name)__title")
# =================================================================
    # 多对多
    # 查询
    # author_obj = models.Author.objects.first()
    # print(author_obj.name)
    # 查询金老板写过的书
    # ret = author_obj.books.all() 前边学过 author_obj.books:关联管理器
# ==========================
    # 1. create
    # 通过作者创建一本书,会自动保存
    # 做了两件事:
    # 1. 在book表里面创建一本新书,2. 在作者和书的关系表中添加关联记录
    # author_obj.books.create(title="金老板自传", publisher_id=2)
# =============
    # 2. add
    # 在金老板关联的书里面,再加一本id是4的书
    # book_obj = models.Book.objects.get(id=4)
    # author_obj.books.add(book_obj)  # 加已经存在的书
    # 添加多个
    # book_objs = models.Book.objects.filter(id__gt=5)
    # author_obj.books.add(*book_objs)  # 要把列表打散再传进去
    # 直接添加id
    # author_obj.books.add(9)
# =======================================
    # remove
    # 从金老板关联的书里面把 开飞船 删掉
    # book_obj = models.Book.objects.get(title="跟金老板学开飞船")
    # author_obj.books.remove(book_obj)
    # 从金老板关联的书里面把 id是8的记录 删掉
    # author_obj.books.remove(8)
# =======================================
    # clear
    # 清空
    # 把景女神 关联的所有书都删掉
    # jing_obj = models.Author.objects.get(id=2)
    # jing_obj.books.clear()
# =======================================
​
    # 额外补充的,外键的反向操作
​
    # 找到id是1的出版社
    # publisher_obj = models.Publisher.objects.get(id=2)
    # publisher_obj.books.clear() # 注意books的 外键是否可为空
# =================================================================
    # 聚合
    from django.db.models import Avg, Sum, Max, Min, Count
    # ret = models.Book.objects.all().aggregate(price_avg=Avg("price"))
    # print(ret) 返回字典{"price":xxx} 按price列指定, 可修改(k=Avg("price"))
​
    # ret = models.Book.objects.all().aggregate(price_avg=Avg("price"), price_max=Max("price"), price_min=Min("price"))
    #  也是字典返回
    # print(ret.get("price_max"), type(ret.get("price_max")))
# =================================================================
    # 分组查询
​
    # 查询每一本书的作者个数
    # ret = models.Book.objects.all().annotate(author_num=Count("author")) queryset 书对象
    # # print(ret)
    # for book in ret:
    #     print("书名:{},作者数量:{}".format(book.title, book.author_num)) # 书多了一个author_num属性
​
    # 查询作者数量大于1的书
    # ret = models.Book.objects.all().annotate(author_num=Count("author")).filter(author_num__gt=1)
    # print(ret)
​
    # 查询各个作者出的书的总价格
    # ret = models.Author.objects.all().annotate(price_sum=Sum("books__price")).values_list("name", "price_sum")
    # ret = models.Author.objects.all().annotate(price_sum=Sum("books__price"))
    # print(ret)
    # for i in ret:
    #     print(i, i.name, i.price_sum)
    # print(ret.values_list("id", "name", "price_sum")) 与for类似
# =================================================================
    # F(两个字段作比较)和Q
        # ret = models.Book.objects.filter(price__gt=9.99)
        # print(ret)
​
    # 查询出 库存数 大于 卖出数的 所有书(两个字段做比较)
    from django.db.models import F
    # ret = models.Book.objects.filter(kucun__gt=F("maichu"))
# =================================================================
    # 刷单 把每一本书的卖出数都乘以3
    # obj = models.Book.objects.first()
    # obj.maichu = 1000 * 3
    # obj.save() 只修改一个对象
    # 具体的对象没有update(),QuerySet对象才有update()方法。
​
    # models.Book.objects.update(maichu=F("maichu")*3) 全都修改了
​
    # 给每一本书的书名后面加上 第一版
    # from django.db.models.functions import Concat
    # from django.db.models import Value
    # 修改字符串
    # models.Book.objects.update(title=Concat(F("title"), Value("第一版")))
​
​
    # Q查询
    from django.db.models import Q
    # 查询 卖出数大于1000,并且 价格小于100的所有书
    # ret = models.Book.objects.filter(maichu__gt=1000, price__lt=100) # 并且
    # print(ret)
    # 查询 卖出数大于1000,或者 价格小于100的所有书
    # ret = models.Book.objects.filter(Q(maichu__gt=1000) | Q(price__lt=100))
    # print(ret)
    # Q查询和字段查询同时存在时, 字段查询要放在Q查询的后面  后边的与前边是 与的关系
    # ret = models.Book.objects.filter(Q(maichu__gt=1000) | Q(price__lt=100), title__contains="金老板")
    # print(ret)
​
​
    # Django ORM 事务
​
    # try:
    #     from django.db import transaction
    #
    #     with transaction.atomic():   # 加入事务
    #         # 先创建一个出版社
    #         new_publisher = models.Publisher.objects.create(name="火星出版社")
    #         # 创建一本书
    #         models.Book.objects.create(
    #             title="橘子物语",
    #             price=11.11,
    #             kucun=10,
    #             maichu=10,
    #             publisher_id=1000  # 指定一个不存在的出版社id
    #         )
    # except Exception as e:
    #     print(str(e))
​
    # 没有指定原子操作
    # try:
    #
    #     # 先创建一个出版社
    #     new_publisher = models.Publisher.objects.create(name="火星出版社")
    #     # 创建一本书
    #     models.Book.objects.create(
    #         title="橘子物语",
    #         price=11.11,
    #         kucun=10,
    #         maichu=10,
    #         publisher_id=1000  # 指定一个不存在的出版社id
    #     )
    # except Exception as e:
    #     print(str(e))
​
    # 执行原生SQL
    # 更高灵活度的方式执行原生SQL语句
    # from django.db import connection
    # cursor = connection.cursor()  # cursor = connections['default'].cursor()
    # cursor.execute("SELECT * from app01_book where id = %s", [1])
    # ret = cursor.fetchone()
    # print(ret)
​
​
    # 在QuerSet查询的基础上自己指定其他的SQL语句(了解即可)
    ret = models.Book.objects.extra(
        # 把出版社计数 赋值给newid
        select={'newid': 'select count(1) from app01_publisher where id>%s'},
        select_params=[1, ],
​
        where=["app01_book.id=%s"],
​
        params=[1, ],
        tables=['app01_publisher']
    )
​
    print(ret)
    for i in ret:
        print(i)

6_orm_2

代码语言:javascript
复制
# orm一对一:
#   当一个表中属性过多的时候,将属性分开,分为常用的属性表,和不常用的
#   例如第三方登录时,常请求的用户名,密码,而爱好,身份证号等不常用信息,可存放在另一张表中
#   构成一对一关系
"""
class A(model.Model):
    ...
    detail=models.OneToOneField(to="B") 逐数据库中 列名为detail_id
class B(models.Model):
    ...若没有主键会自动创建id列
通过A获取B a = models.A.objects.get(id=1)  b = a.deatil b.xxx可获取属性
"""
# orm多对多:
#   1,自动创建第三张表
#   2,自己创建
""" 自己创建第三张表 查询比较慢,不能使用author.books了
class Author_Book(model.Model):
    ...
    author = modelsForeignKey("Author")  author_id
    book = modelsForeignKey("Book) book_id
查询时,手动经
过第三张表查询
"""
#   3,自己创建表,但使用ManyToMany
"""
    第三张表的建立与2相同
    class Author():
        ...
        books = models.ManyToMany(to="Book",throuth="第三张表",throght_fields=(author,book))
        里边是元祖,顺序固定,应为是在author中 所以先写author(第三张表中的author)
        注意第三张表  class Meta:
                                unique_tgether = ("author","book")
"""
# 第三张表无其他字段,第一种
# 有其他字段:第三种 如聊天记录,不仅要双方那个id,还有时间,内容.... 因此需要自己创建
#   使用第三种方法时,是没有add方法,remove()方法等
#   例:给作者1加一本书 obj.get(id=1).books.add(xxx) 第一种
#    第三种:直接添加记录
#   反查有book查author   ...filter(id=1).value("related__name__author的属性")
​
# ===========================================
# csfr 跨站请求伪造 服务器返回给用户一个html页面,里面有form表单   action="xxxx"
#   此时即可得到xxxx请求地址, 即可自定义html,form添加其他input 请求服务器,即跨站请求伪造
#   解决方案:服务器返回的html中有一项input name=key value="每个用户不同,或每次请求不同",以此识别用户
# 默认是开启的, 即不能跨站请求,弱不需要注释即可
"""
    使用方法:在form中 {% csrf_token%}  在html中会变为 <input type="hidden" name="csrfmiddlewaretoken"
    value="随机字符串"/>
    若出现跨站请求即会禁止 一般就是403
    在render中 生成html时,会自动产生key,通过Post接受参数时,会自动校验,不通过即拒绝 
"""

7_分页_session_cookies

代码语言:javascript
复制
# 分页
class Page():
​
    def __init__(self, page_num, total_count, url_prefix, per_page=10, max_page=11):
        """
        :param page_num: 当前页码数
        :param total_count: 数据总数
        :param url_prefix: a标签href的前缀
        :param per_page: 每页显示多少条数据
        :param max_page: 页面上最多显示几个页码
        """
        self.url_prefix = url_prefix
        self.max_page = max_page
        # 每一页显示多少条数据
        # 总共需要多少页码来展示
        total_page, m = divmod(total_count, per_page)
        if m:
            total_page += 1
        self.total_page = total_page
​
        try:
            page_num = int(page_num)
            # 如果输入的页码数超过了最大的页码数,默认返回最后一页
            if page_num > total_page:
                page_num = total_page
        except Exception as e:
            # 当输入的页码不是正经数字的时候 默认返回第一页的数据
            page_num = 1
        self.page_num = page_num
​
        # 定义两个变量保存数据从哪儿取到哪儿
        self.data_start = (page_num - 1) * 10
        self.data_end = page_num * 10
​
        # 页面上总共展示多少页码
        if total_page < self.max_page:
            self.max_page = total_page
​
        half_max_page = self.max_page // 2
        # 页面上展示的页码从哪儿开始
        page_start = page_num - half_max_page
        # 页面上展示的页码到哪儿结束
        page_end = page_num + half_max_page
        # 如果当前页减一半 比1还小
        if page_start <= 1:
            page_start = 1
            page_end = self.max_page
        # 如果 当前页 加 一半 比总页码数还大
        if page_end >= total_page:
            page_end = total_page
            page_start = total_page - self.max_page + 1
        self.page_start = page_start
        self.page_end = page_end
​
    @property
    def start(self):
        return self.data_start
​
    @property
    def end(self):
        return self.data_end
​
​
    def page_html(self):
        # 自己拼接分页的HTML代码
        html_str_list = []
        # 加上第一页
        html_str_list.append('<li><a href="{}?page=1">首页</a></li>'.format( self.url_prefix))
​
        # 判断一下 如果是第一页,就没有上一页
        if self.page_num <= 1:
            html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">&laquo;</span></a></li>'.format(self.page_num-1))
        else:
            # 加一个上一页的标签
            html_str_list.append('<li><a href="{}?page={}"><span aria-hidden="true">&laquo;</span></a></li>'.format( self.url_prefix, self.page_num-1))
​
        for i in range(self.page_start, self.page_end+1):
            # 如果是当前页就加一个active样式类
            if i == self.page_num:
                tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)
            else:
                tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format( self.url_prefix, i)
​
            html_str_list.append(tmp)
​
        # 加一个下一页的按钮
        # 判断,如果是最后一页,就没有下一页
        if self.page_num >= self.total_page:
            html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">&raquo;</span></a></li>')
        else:
            html_str_list.append('<li><a href="{}?page={}"><span aria-hidden="true">&raquo;</span></a></li>'.format( self.url_prefix, self.page_num+1))
        # 加最后一页
        html_str_list.append('<li><a href="{}?page={}">尾页</a></li>'.format( self.url_prefix, self.total_page))
​
        page_html = "".join(html_str_list)
        return page_html
    # from utils.mypage import Page
    # page_obj = Page(page_num, total_count, per_page=10, url_prefix="/books/", max_page=9,)
    # ret = models.Book.objects.all()[page_obj.start:page_obj.end]
    # page_html = page_obj.page_html()
    # return render(request, "books.html", {"books": ret, "page_html": page_html})
# ====================================================================
# cookies 和session  因为http请求是无状态的,请求之间无关系
# cookie 保存在浏览器上的键值对,访问时会自动添加
#   例如:登录,输入密码登陆后,若成功,响应请求,让浏览器保存cookie本机,下次访问会默认带上cookie
#   都是键值对name value
"""
用法:得到响应对象 rep = render()或redirect或httpresponse
1,rep.set_cookies("xxx","yyy")  默认关闭浏览器失效
2,rep.set_signed_cookie("xxx","yyy",salt="zzz",max_age=10 单位是s) 设置加盐cookies
1,request.COOKIES['xxx'] 获取到
2,rep.get_signed_cookie("xxx",default="yy"取不到异常,加default,salt="zzz")
​
清除cookies:rep.delete_cookie("xxxx")
​
当多个页面需要校验cookies时
使用装饰器
def cookies(fun):
    @wraps(fun) 修复注释,文档名等
    def inner(request,*args,**kwargs):
        if not request.get_singed_cookies.get("xxx",default="yyy",salt=""):
           return render()
        else:
            跳转登录,   跳转后应该再次到请求的页面,不能固定,写死
            1,获取请求的url:Request.path_info
            redirect("..html/?next={}".format(url))   在对应方法中取出next值,动态跳转即可
        ret = fun(request,*args,**kwargs)
        return ret 
    return inner 
request.get_full_path:全路径带参数
request.path_info:不带参数
HTML中 action={{request.get_full_path}} 跳转到url中的路径   action 为空的时候默认跳转到当前url
action 要么不写要么 使用{{}}
expire= 针对ie的超时参数
path="/" 生效路径 默认是"/"
domain= 生效域名
source=False https传输
httponly=False 只能使用http协议传输,无法被javascript获取,不是绝对的,抓包可以修改
​
最大4kb
"""
# =============================================
# session  它依赖于cookie
#   cookies 键值保存在客户端
#   session中的键值保存在服务器,通过sessionid连接,保存在cookie中
#   Django session  存
#       1,生成字符串
#       2,生成大字典对应1中字符串
#       生成的数据是在数据库中的 django_session session_key session_date(加密过得) expire_date session默认两周
#       3,返回给cookie 浏览器
#   取
#   1,从cookie中找到字符串
#   2,找到的大字典
#   3,大字典取值
""""
request.session['k1']
request.session.get('k1',None)
request.session.set('k1',"123") 存在则不设置
del request.session['k1']
request.session.delete() 删除所有session中的值,没神魔用,会使cookiezhaobudao对应值,等于无效
request.session.flush() session,cookie都删除
​
request.session.clear_expired() 数据库中的session记录不会自动删除,本语句就是删除过期的session
request.session.exists("key") 判断key存在
request.session.set_expiry(整数秒,datatime或timedelta,0表示关闭失效,None settings中设置) 失效的是cookie
 
"""
# settings中配置全局session信息
# 默认引擎
SESSION_ENGINE="django.contrib.session.backends.db"
# 缓存session
SESSION_ENGINE = "django.contrib.session.backends.cache"
SESSION_CACHE_ALLAS="default" # 使用的缓存别名默认内存缓存,也可memcache
# 文件Session
SESSION_ENGINE = "django.contrib.session.backends.file"
SESSION_FILE_PATH=None # 若为None tempfile.gettempdir获取临时地址
# 缓存加数据库
SESSION_ENGINE="django.contrib.session.backends.cached_db"
# 加密Cookie Session 加密的cookies 相当于没有使用session
SESSION_ENGINE="django.contrib.session.backends.singed_cookies"
​
# 其他设置
SESSION_COOKIE="sessionid"
SESSION_COOKIE_PATH="/"
SESSION_COOKIE_DOMAIN=None
SESSION_COOKIE_SECURE=False
SESSION_COOKIE_HTTPONLY=True
SESSION_COOKIE_AGE=1209600 # 2 WEEK
SESSION_EXPIRE_AT_BROWSER_CLOSE=False # 浏览器关闭清除Session
SESSION_SAVE_EVERY_REQUEST=False #每次请求后更改SESSION
# ==========================================
# cvb(类中get) 使用装饰器
#   get,post (self,request)  装饰器中第一个参数是request,不匹配
#   解决方案:form django.utils.decorators import method_decorator
#   get或post方法上 @method_decorator(自定义的装饰器)  也可以加在类上 但要指明方法
#   @method_decorator(自定义的装饰器,name="get")
# 注意:其实在cvb中有dispatch方法
"""
    def dispatch(self,request,*args,**kwargs): 用来选择是get请求还是post请求 
        return super(本类名,self).dispatch(request,*args,**kwargs)
        若在此上边加,表示get,post都加装饰器
"""
# 补充 csfr token
# 对于cvb中
"""
    from django.views.decorator.csrf import csrf_protect,csrf_exempt
    @method_decorator(csfr_protect) 即时sttting中注释了,不验证跨站请求,加了本装饰器,也会验证
    @method_decorator(csfr_exempt) 即时sttting中验证跨站请求,加了本装饰器,也不会验证,即取消跨站验证
    只能放在cvb的dispatch方法上
    
"""

8_Django 中的html javascript

代码语言:javascript
复制
# json (javascript object Notation)
# 是javascript中的对象类型
# javascript 数字,字符串,布尔,数组,对象,null
# python 整形浮点,字符串,布尔,列表,字典,None 因此python不能json对象
# 二者通过json字符串转化
# json注意事项: 1,key必须双引号,
#              2,不能16进制,
#              3,不能undefined,
#              4,value不能是函数,或日起对象
# ====================================================
# JQuery 发ajax请求
"""
$.ajax(
    {
        url:"xxx",
        type:"get"
        data:{字典}
        success:function(data){
        }
    }
)
ajax 发送跨站请求时
    方法1:要把{{csrf_token}} 的值取到拼接到发送的数据中
    方法2:引入jquery.cookie.js
        type下多个headers:{"X-CSFRToken":$.cookie("csfrtoken")},
    方法3:存入js文件,发ajax前引入,发送步骤与普通相同,不用再额外添加
    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);
    }
  }
});
"""
# ==============================================
# 对象的序列化 需要转为字典 然后变为json字符串,
# from django.core import serializers
#   s= serializers.serializer("json",数据库查询的对象列表)
# ========================================
# sweetalert 插件,漂亮的弹出框
"""
1,swal("title","content","css") 
css:success,warning,info,error
2,
 swal({
          title: "你确定要删除吗?",
          text: "一旦删除就找不回来了",
          type: "warning",
          showCancelButton: true,
          confirmButtonClass: "btn-warning",
          confirmButtonText: "确认",
          cancelButtonText: "取消",
          closeOnConfirm: false,
          showLoaderOnConfirm: true //若删除耗时,显示加载状态
        },
        function(){
            // 向后端发送删除的请求
            $.ajax({
                url: "/delete/",
                type: "post",
                datatype:"json", //返回值的格式,回调函数中,按照此类型解析,不写就是字符串类型
                traditional:True,// 为true,阻止深度序列化,不懂什么意思,反正就可以传list了
                data: {"id":delId,"list":[1,2,3]}, 接受的时候使用getlist接受,但不能是双层列表 
                success:function (arg) {
                    swal(arg, "你可以跑路了!", "success");
                    $trEle.remove();
                }
            });
            
        }
    );
"""
# ==================================================
# Django 的form组件
# 第一步:定义class
# from django import  forms
# from django.forms import  widgets
# class RegForm(forms.Form):
#     name = forms.CharField(max_length=16,label="用户名") 校验规则
#     pwd = forms.CharField(
#     label="密码",
#     widget = widgets.PasswordInput(attr={'class':'xx'},render_value=True), //表示为密码类型,切验证后密码还存在 html相关
#     min_length=6,
#     error_message={"required":"不能为空","invalid":"格式错误","min_length":"最短6位"}
#     )

# def fun(request):
#     form_obj = RegForm()
#     if reauest.method=="post":
#         form_obj=RegForm(request.POST)
#         if form_obj.is_valid :存入数据库
#               name = form_obj.cleanned_data.get("name") 经过验证的数据
#               先从字典中去掉无用字符串pop("xxx")这种不报错
#               .create(**form_obj.cleanned_data) 但要注意名字与数据库中列相同
#     return render(request,"xxx.html",{"html":form_obj})
# 第二部,html中调用属性
# <form  novalidate> 关闭浏览器校验
# {{csrf_token}}
# {{form_obj.as_p}} 每个都用p标签包裹
# {{form_obj.errors.pwd}}
# <p><input type="submit" /></p>
# </form>
# 或在form中自己写
"""<div>
{{form_obj.name.label}}
{{form_obj.name}}
<span>{{form_obj.name.errors.0}}</span>
</div>这种,只不过每个都要自己写

服务器端校验,通常是request中获取值,再返回,比较麻烦
django 校验后还可以保留信息
其他组件
单选按钮:forms.fields.ChoiceField(
        choices=((1,"男"),(2,"女")),
        label="性别",
        initial=3,默认是3选中
        widget = forms.widgets.RadioSelect
    )
单选框,修改为widget = forms.widgets.Select 就是下拉菜单
多选框forms.MutipleChoiceField
        initial=[1,3]
        widget = forms.widgets.SelectMultiple  下拉菜单全部显示的那种
单选框,记住密码那种:forms.fields.ChoiceField
            widget = forms.widgets.CheckboxInput
            initial="checked"
多选框,
forms.fields.MultipleChoiceField(
        choices=((1,"男"),(2,"女")),
        label="爱好",
        initial=[1,3],默认是3选中
        widget = forms.widgets.CheckBoxSelectMultiple
    )
"""
"""
自定义校验规则
from django.core.validators import RegexValidator
Charfield(
    加上字段validators=[ 正则列表
    RegexValidator(r"[0-9]+$","请输入数字"),
    RegexValidator(r"^1[3-9][0-9]{9}$","159开头"),
    ]
)
在类中定义方法
def clean_name(self): 名字固定 clean_列名
    value = self.cleanned_data.get("校验的列名 如name")
    if "非法字符" in value:
        raise ValidationError("含有非法字符")
    return value
def  clean(self): 重写父类clean方法,父类的方法默认什么都没干
    pwd = self.cleaned_date.get("pwd")
    ...
    if xx==yy
        self.add_error("字段",ValidatorError("不一致") )  应该在那里显示呢?
        raise ValidatorError("不一致")
    return self.cleaned_data
    
reg_pwd  {{ form_obj.errors}}
"""
# =====================多选框从数据库取值
forms.CharField(
    choices=models.xxx.objects.all().value_list("id",....)
    #此时虽然可以获取,但是静态字段,若数据库增加,不重启服务器,新的数据不能获取
)
需要从写from的__init__方法
def __init__(self,*args,**kwargs):
    super().__init__(*args,**kwargs)
    self.fields['那一列'].widget.choices=models......
内置字段:等待添加....

9_ 中间件

https://www.cnblogs.com/liwenzhou/

代码语言:javascript
复制
# importlib的使用
import importlib
o = importlib.import_module("模块字符串")
# 这样即可导入模块 ,其实是通过反射

# 要实现权限验证,如登陆后访问,原来是装饰器,但若函数过多...
# 中间件:官方说是 用来处理Django的请求和响应的框架级级别的钩子,轻量级
#   全局的,慎用,使用不当,影响性能 说白了就是在执行urls.py前后,执行某些方法
# setting  MIDDLEWARE   定义后加入列表即可
# 固定方法 其实中间件相当于过滤器
from django.utils.deprecation import MiddlewareMixin
class A(MiddlewareMixin):
    # 先request,次view 最后response
    def process_request(self,request):pass
    # 按照setting中的顺序,请求时 123 响应是 321 是反向
    # 返回None 继续执行url,若有return httpresponse 则直接返回
    def process_request(self,request,response):# 必须要两个参数,且必须返回值,要么自定义返回 ,或返回视图的response
        pass
    def process_view(self,request,view_func,view_args,view_kwargs):
        """
        :param request: 请求
        :param view_func: 要执行的函数名字
        :param view_args: 位置参数
        :param view_kwargs: 关键字参数
        :return:
        在找到urls.py前执行,按顺序执行,
        """
    def process_exception(self):pass
    # 只有在视图函数中出现异常的时候执行, 也是倒序
    # 返回None,继续执行其他中间件的exception
    # HttpResponse,跳过其他中间件的exception ,通常是视图页面错误,既不能正常返回,在此定义返回页面
    def process_template_response(self,request,response):pass
    #  倒序执行, 在视图函数执行完毕 但没有返回render()之前
    # 返回Noneh或HttpResponse
    # 因此返回的对象中必须存在render()方法,然后会执行render()方法,名字必须为render(),内容可自定义



    # request列表没执行完毕,某一个request返回了响应,则直接跳到该中间件的response
    # request列表执行完毕,会继续第一个中间件的view --->到最后一个view
    #   若view列表没执行完毕,某一个返回响应了,后边的view不执行,  跳到第一个response(返回时候的第一个res) (urls中的view不执行)
    #   若view列表执行完毕,执行urls view ,然后response列表
#
#     1,process_request
#         urls.py
#     2,process_view
#         view
#     3,有异常process_exception
#     4,若视图函数返回对象有render()方法,执行
#     5,process_response
#
# day74
# 2018 - 05 - 21
#
# 课程安排
# 周一:
# 中间件
# auth模块 + 分析BBS项目需求(小组讨论把表结构设计出来)
#
#
# 1.
# 今日内容
# 中间件:http: // www.cnblogs.com / liwenzhou / p / 8761803.
# html
#
# 1.
# URL的白名单
# url = ["/xx/", "/oo/", "/haha/"]
# 2.
# 登陆之后才能访问某些URL
# 之前使用装饰器
#
# 中间件的定义:
# wsgi之后
# urls.py之前
# 在全局
# 操作Django请求和响应的模块!
#
# 中间件的使用:
# 5
# 个固定的方法
# process_request(self, request)
# 执行顺序:
# 按照注册的顺序(在settings.py里面设置中
# 从上到下的顺序)
# 何时执行:
# 请求从wsgi拿到之后
# 返回值:
# 返回None,继续执行后续的中间件的process_request方法
# 返回response, 不执行后续的中间件的process_request方法
#
# process_response
# 执行顺序:
# 按照注册顺序的倒序(在settings.py里面设置中
# 从下到上的顺序)
# 何时执行:
# 请求有响应的时候
# 返回值:
# 必须返回一个response对象
#
# process_view(self, request, view_func, view_args, view_kwargs):
# 执行顺序:
# 按照注册的顺序(在settings.py里面设置中
# 从上到下的顺序)
# 何时执行:
# 在urls.py中找到对应关系之后
# 在执行真正的视图函数之前
# 返回值:
# 返回None,继续执行后续的中间件的process_view方法
# 返回response,
#
# process_exception(self, request, exception)
# 执行顺序:
# 按照注册顺序的倒序(在settings.py里面设置中
# 从下到上的顺序)
# 何时执行:
# 视图函数中抛出异常的时候才执行
# 返回值:
# 返回None, 继续执行后续中间件的process_exception
# 返回response,
#
#
#
# process_template_response(self, request, response)
# 执行顺序:
# 按照注册顺序的倒序(在settings.py里面设置中
# 从下到上的顺序)
# 何时执行:
# 视图函数执行完,在执行视图函数返回的响应对象的render方法之前
# 返回值:
# 返回None, 继续执行后续中间件的process_exception
# 返回response,
#
#
# Django调用
# 注册的中间件里面五个方法的顺序:
# 1.
# process_request
# urls.py
# 2.
# process_view
# view
# 3.
# 有异常就执行
# process_exception
# 4.
# 如果视图函数返回的响应对象有render方法, 就执行process_template_response
# 5.
# process_response
#
# Django已经学过的知识点:
# 1.
# Urls.py
# 路由系统:
#
# 正则
# 分组匹配 --> 位置参数
# 分组命名匹配 --> 关键字参数
#
# 分级路由
# include
#
# 给路由起别名
# name = "xx"
#
# 反向解析url
# view
# from django.urls import reverse
#
# reverse("xx", args=[1, 2, 3])
# reverse("xx", kwargs={”k
# ": "
# v
# "})
#
# 自取其辱
#
# 2.
# 视图
# views.py
# request
# request.method
# request.GET --> URL里面的参数
# request.POST --> post请求的数据
#
# request.path_info --> 路径
# request.get_full_path() --> 路径加路径的参数
#
# response
# 新手必备3件套
# render(request, "xx.html", {“k”: "v", ...})
# HttpResponse("响应")
# redirect("/index/")
# redirect("http://www.luffycity.com")
#
# from django.http import JsonResponse
#
# JsonResponse()
#
# FBV和CBV
#
# 函数装饰器和方法装饰器的区别
#
# 3.
# 模板
#
# filter
# 内置的filter方法
# 自定义的filter方法
#
# tag
# 内置的tag
# 自定义的simpleTag
# 自定义的inclusionTag
#
# 母版和继承
#
# { % extends ‘base.html’ %}
#
# { % block
# page - main %}
# { % block
# small %}
# { % endblock
# small %}
# { % endblock
# page - main %}
#
#
# 组件
# { % include
# nav %}
#
#
# 静态文件相关的tag
#
# 在模板语言里面反向解析url
#
# { % url
# 'url的别名'
# xx %}
#
#
# 4.
# ORM
#
# 对应关系
# 类 --> 数据表
# 对象 --> 数据行
# 属性 --> 字段
#
# Django连接MySQL数据库的步骤:
# 1.
# 手动创建库
# 2.
# 配置settings.py中数据库的连接信息
# 3.
# 修改settings.py同目录下的__init__.py文件,添加两句
# import pymysql
#
# pymysql.install_as_MySQLdb()
# 4.
# 在app下面的models.py中定义类,类一定要继承mdoels.Model
# 5.
# 执行两句命令
# 1.
# python
# manage.py
# makemigrations
# 2.
# python
# manage.py
# migrate
#
# 操作数据表
#
# 操作数据行(增删改查)
# 单表
# 外键
# 多对多
# 一对一
#
# ORM高级:
# 常用字段和方法
# 必知必会13条
# 神奇的双下划线
# 跨表的正向查询反向查询
#
# F和Q
#
# 聚合和分组
#
# 事务
#
# 执行原生的SQL语句
#
# 5.
# Cookie和Session, 分页
#
# 6.
# AJAX
#
# $.ajax({
#     url: “”,
# type: "post",
# data: {"k1": JSON.stringify([1, 2, 3])},
# success: function(data)
# {
#
# }
# })
# 7.
# form表单
#
# 8.
# 中间件

10_auth模块

代码语言:javascript
复制
# 当在html要获取当前用户信息的时候,通常是session存id
# 视图中查询到,传入html,存在问题:需要的页面都要获取,再传入
# 解决方案:自带的中间件,自带的倒数第三个 auth有关的
"""
python manage.py createsuperuser 向auth_user 添加用户 
from django.contrib import auth
  obj = auth.authenticate(username="xx",password="xx")
    将认证的用户放入request.user:
  auth.login(request,obj)根据cookie,将用户放入session, 检测当前用户,下次来的是会有请求中会放入user
  auth.lgout(request) 相当于request.session.flush()

from django.contrib.auth.decorators import login_required

需要登陆权限的视图 @login_requried() 装饰器 默认""
默认LOGIN_URL="/accounts/login/" 不存在 添加 修改即可  而且实现的登陆跳转

request.user.is_authenticated() 返回

from django.contrib.auth.models import User
    注意username不能重复
    User.Objects.create(...)  不能使用这个创建,创建后是明文密码
    User.Objects.create_superuser()
    User.Objects.create_user(....) 密文密码


    obj.check_password("密码") 检测密码正确与否
    obj.set_password("xxx") 修改密码
    obj.save() 修改后要保存

"""
# ====================================
# 扩展自带的表
# 1,models.OneToOneField(to=User)
# 2,继承自带的类,auth_user 不会创建了
"""
    from django.contrib.auth.models import User,AbstractUser
    继承后添加额外属性
    若使用本方法 sttings指定 AUTH_USER_MODELS='appname.类名'
"""
python manager.py createsuperuser
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-10-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1,http
    • 响应格式
      • 请求格式
        • 2 django基础
        • 3 django web实例
        • 4,MVC
        • 5,django 路由系统
        • 5_orm_1
        • 6_orm_2
        • 7_分页_session_cookies
        • 9_ 中间件
        • 10_auth模块
        相关产品与服务
        消息队列 TDMQ
        消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档