• diango基础知识总结


    下载

    1. 命令行

      pip install django==1.11.26 -i https://pypi.tuna.tsinghua.edu.cn/simple

    2. pycharm

    创建项目

    1. 命令行

      django-admin startproject 项目名

    2. pycharm

      file _> new project _> django _> 输入路径 _> 选择解释器 _> create

    启动项目

    1. 命令行

      python manage.py runserver # 127.0.0.1:8000

      python manage.py runserver 80 # 127.0.0.1:80

      python manage.py runserver 0.0.0.0:80 # 0.0.0.0:80

    2. pycharm

      点绿三角 django 前面是dj

      可以修改配置 可以改IP和端口

    使用顺序

    settings 静态文件配置

    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  #文件夹根目录
    
    DEBUG = True   #因为启动出错调试模式 上线后改为Flase,出错不报错,给用户更好的用户体验
    
    ALLOWED_HOSTS = ['*'] #让所有的用户可以访问
    
    INSTALLED_APPS = [       #app注册
    	'app01', 
        'app01.apps.App01Config'   # 推荐写法
    ]
    
    MIDDLEWARE = [
        # 'django.middleware.csrf.CsrfViewMiddleware',   #提交POST请求注释一个中间件
    ]
    
    
    
    
    """
    如果使用sqlite3数据库
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3', 
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
    """
    
    """
    #如果使用mysql数据库
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',   #diango的服务器引擎
            'NAME': 'bookmanager',
            'USER': 'root',
            'PASSWORD': '123',
            'HOST': '127.0.0.1',
            'PORT': 3306,
        }
    }
    
    #默认使用pymysql模块 替换
    import pymysql
    pymysql.install_as_MySQLdb()
    """
    
    
    
    
    LANGUAGE_CODE = 'en-us'       #汉语 'zh-hans'  
    
    TIME_ZONE = 'UTC'   #时区:英国的,改为亚洲上海 'Asia/Shanghai'  
    
    STATIC_URL = '/static/'    #静态文件夹的别名,配置静态文件要以/static/为开头
    
    
    STATICFILES_DIRS = [                  # 路由
        os.path.join(BASE_DIR,'static1'),   # 存放静态文件的路径
        os.path.join(BASE_DIR,'static1'),
    ]
    				 # join(BASE_DIR必须是这个,静态文件夹static1)
    					# 加上静态文件的存放路径
    
    

    models.py 映射关系

    写映射关系操作数据库

    settings 配置:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql', #使用mysql数据库引擎
            'NAME': 'day43',		#默认操作的库
            'HOST': '127.0.0.1',	#库所在的服务器地址		
            'PORT': 3306,			#端口
            'USER': 'root',			#用户名
            'PASSWORD': '123',		#密登密码
        }
    }
    
    
    #默认使用pymysql模块 替换  也可以写在day43的__init__.py里
    import pymysql
    pymysql.install_as_MySQLdb()
    
    

    创库

    用可视化工具创建一个MySQL数据库

    创表

    class User(models.Model):
        username = models.CharField(max_length=32)  # varchar(32)
        password = models.CharField(max_length=32)  # varchar(32)
        
    #类 对象   属性
    #表 数据行 字段
    
    
    python manage.py  makemigrations  # 制作迁移文件 出现在migrations
    python manage.py migrate  # 执行SQL语句 同步 
    		#terminal里执行命令
    

    △id字段是自动添加的,如果你想要指定自定义主键,只需在其中一个字段中指定 primary_key=True 即可。如果Django发现你已经明确地设置了Field.primary_key,它将不会添加自动ID列。

    urls.py 路由

    路径 函数转换

    ==settings配置:

    STATICFILES_DIRS = [                  # 路由
        os.path.join(BASE_DIR,'static1'),   # 存放静态文件的路径
        os.path.join(BASE_DIR,'static2'),
    ]
    

    url(r^'用户输入输入的路径 0.0.0.0:80/index/',不加括号的函数名)

    urlpatterns = [ 	
        url(r'^admin/', admin.site.urls),
        url(r'^index/', index),   # 路径和函数的对应关系,
        url(r'^modal/', modal),  
    ]
    

    views.py 函数

    def index(request):  		    # 函数里写处理逻辑,request拿到网络路径,固定写法
        print(request.path_info)	# 打印网络路
    

    import 导入:

    导入返回字符串的包HttpResponse,返回html文件的包render,返回执行另一个逻辑的包

    from django.shortcuts import HttpResponse,render, redirect 
    

    导入dpp01文件中的创建数据表的类的models.py文件

    from app01 import models
    

    return 返回:

    return HttpResponse('

    index

    ')

    返回字符串

    return HttpResponse('<h1>index</h1>')         # 返回字符串
    

    return render(,,)

    返回接受到请求的网络路径要渲染的html文件和要传的值

    return render(request, 'index.html',{'k1':v1}) 
    #返回   (网络路径必添,要渲染的html文件,{别名:要传的值})
    

    return redirecct('路径')

    执行另一个逻辑

    ORM的操作

    写函数来实现增删该查

    .all 获取所有的数据

    all_publishers = models.Publisher.objects.all() 
    #变量 = 文件名.类名.对象.取值方法
    # objects.all() 查询出所有的出版社的信息,是一个对象列表
    

    .filter(pk=pk) 获取所一个数据

    第一个pk列名,第二个pk为从request中get到的

    变量 = models.User.objects.filter(password='dsb')   # 对象列表	
    # 用.first取第一个,若无,返回空列表,if 变量;判断时,不会报错,只是不会执行这个语句了
    # 用[0]取值时,,若无,取不到值,if 判断时变量,会报错
    

    get 获取所一个数据

    变量 = models.User.objects.get(password='dsb')  # 对象 特点 获取不到或者获取到多个都报错
    

    create(name=pub_name) 添加数据

    利用类的对象

    obj = models.Publisher.objects.create(name=pub_name)
    

    update(name=pub_name) 跟新数据

    templates HTML文件

    模板

    某.html的settings配置

    MIDDLEWARE = [
      
        # 'django.middleware.csrf.CsrfViewMiddleware',   #提交POST请求注释一个中间件
      
    ]
    

    hyml中的样式路径配置

    <head>  
        <title>Title</title>
        <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.min.css">
        <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.min.css">
        
        <script src="/static/js/jquery.js"></script>
        <script src="/static/plugins/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    </head>
    

    模板语法

    △登录

    <div class="container">
    
        <form class="form-signin" method="post" action="" novalidate>
            <h2 class="form-signin-heading">Please sign in</h2>
            <label for="inputEmail" class="sr-only">用户名</label>
            <input type="text" id="inputEmail" class="form-control" name="username" placeholder="输入用户名" required=""
                   autofocus="">
            <label for="inputPassword" class="sr-only">密码</label>
            <input type="password" id="inputPassword" class="form-control" name="password" placeholder="输入密码" required="">
            <div>{{ error }}</div>
            <div class="checkbox">
                <label>
                    <input type="checkbox" value="remember-me"> Remember me
                </label>
            </div>
            <button class="btn btn-lg btn-primary btn-block">登录</button>
    
        </form>
    

    △查询所有的作者信息

        all_authors = models.Author.objects.all()
        for author in all_authors:
            print(author)
            print(author.name)
            print(author.books,type(author.books))  # 关系管理对象
            print(author.books.all(),type(author.books.all()))  # 所关联的所有的对象
    

    △for循环

    views.py传过来的参数:
    render(request,'pub.html',{'all_publishers':all_publishers}) 
    {{ all_publishers }} 
    
    html的for循环:
    {% for i in all_publishers  %}
    
    	{{ forloop.counter }}
    	{{ i }}
    	{{ i.id }}  {{ i.pk }}
    	{{ i.name }}
    	
    {% endfor %}
    
    
    

    △if

    {% if 条件 %}
    	xxx
    {% else %}	
    	xxxxx
    {% endif %}
    

    △form的注意点

    1. form标签的属性 action='提交的地址' method='post' novalidate 取消input标签自带的校验
    2. input标签必须要有name属性 有些标签有value值
    3. 需要有一个button按钮 或者 type='submit'的input

    △get 和 post

    get : 获取一个页面

    1.直接在浏览器的地址栏中输入地址 回车

    2.form表单 不指定method

    3.a标签

    参数: ?k1=v1&k2=v2

    获取参数: request.GET.get('k1')

    post : 提交数据

    form表单  method = 'post'
    

    获取数据: request.POST.get('k1')

    static1 渲染

    一个项目的结构

    day43项目

    .idea 配置

    pycharm自动帮配的配置,打开别人的diango项目时要先删了此项

    app01

    方便在一个大的Django项目中,管理实现不同的业务功能

    migrations 放表

    放和数据库同步的表

    admin.py 后台

    后台管理:

    1、应用注册

    2、admin界面汉化

    apps.py 元数据

    应用程序设置

    元数据

    models.py

    写映射关系操作数据库

    它包含了你存储的数据的重要字段和行为

    • 每个模型都是一个Python类,它是django.db.models.Model的子类。
    • 模型的每个属性都代表一个数据库字段。
    #类 对象   属性
    #表 数据行 字段
    class User(models.Model):
        username = models.CharField(max_length=32) #varchar
        password = models.CharField(max_length=32) #varchar
    

    image-20191212191131843

    tests.py 测试

    views.py

    写函数逻辑
    

    day43项目包

    init.py 自动执行

    #默认使用pymysql模块 替换  也可以写在settings.py里
    import pymysql
    pymysql.install_as_MySQLdb()
    

    settings

    静态文件配置

    urls.py

    路径 函数转换

    wsgi.py 网关接口

    WSGI(Python Web Server Gateway Intergace)

    中文名:python服务器网关接口,python应用于web服务器之间的接口,很少用到,但是最好不要修改其内容

    static1

    templates

    manage.py 命令行接口

    应用的命令行接口

    将Django project放到sys.path目录中,同时设置DJANGO_SETTINGS_MODULE环境变量为当前project的setting.py文件。

    diango运行流程

    Django处理一个请求的流程:

    1. 在浏览器的地址栏中输入地址,回车,发了一个GET请求
    2. wsgi模块接收了请求,将请求的相关信息封装成request对象
    3. 根据地址找到对应函数
    4. 执行函数获取到返回结果,wsgi模块将结果返回给浏览器

    发请求的途径:

    1. 在浏览器的地址栏中输入地址 get请求
    2. a标签 get请求
    3. form表单 get/post

    reqeust

    ​ reqeust.GET url上携带的参数 ?k1=v1&k2=v2

    ​ reqeust.POST form表单提交POST请求的参数

    ​ request.method 请求方式 GET、POST

    response

    ​ HttpResponse('字符串') ——》 返回字符串

    ​ render(request,'模板的名字',{}) ——》 返回一个页面

    ​ redirect('地址') ——》 重定向

    创建一个app

    terminal里执行命令

    python manage.py startapp app名称

    注册

    settings配置
    INSTALLED_APPS = [
    	'app01', 
        'app01.apps.App01Config'   # 推荐写法
    ]
    

    Django使用MySQL数据库的流程

    手动创建一个MySQL数据库

    配置数据库

    ENGINE   MySQL
    NAME	数据库的名字
    HOST    ip 
    PORT    3306
    USER    用户名
    PASSWORD  密码
    

    在与settings同级目录下的__init__.py中写代码:

    import pymysql
    pymysql.install_as_MySQLdb()
    

    写models:

    form django.db import models 
    class Publisher(models.Model):
    	name = models.CharField(max_length=32)
    
    

    执行迁移的命令

    python  manage.py  makemigrations  # 检查已经注册的APP下面的models.py的变更情况
    python manage.py migrate   # 执行迁移 
    

    ORM 对象关系映射

    对应关系:

    ​ 类 _> 表

    ​ 对象 _> 数据行(记录)

    ​ 属性 _> 字段

    ORM能做的事情:对数据做修改、对表做修改

    常用的字段

    AutoField  自增字段
    IntegerField  整数
    CharField 字符串
    DatetimeField  DateField 日期时间
    	auto_now:每次修改时修改为当前日期时间。
    	auto_now_add:新创建对象时自动添加当前日期时间。
    BooleanField  布尔值
    TextField   大文本
    ImageField  图片
    DecimalField   10进制小数
    

    字段参数

    null=True   # 数据库中该字段可以为空
    blank=True  # 用户输入可以为空
    db_column   # 数据库字段的名
    default     # 默认值
    primary_key  # 主键
    db_index    # True 索引
    unique      # 唯一约束
    verbose_name   # 中文提示
    choices        # 让用户选择的数据
    

    建表的参数

        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "person"
    
            # # admin中显示的表名称
            verbose_name = '个人信息'
    
            # verbose_name加s
            verbose_name_plural = '所有用户信息'
    
            # 联合索引
            # index_together = [
            #     ("name", "age"),  # 应为两个存在的字段
            # ]
            #
            # # 联合唯一索引
            unique_together = (("name", "age"),)  # 应为两个存在的字段
    

    ORM的操作

    from django.db import models
    
    class Publisher(models.Model):
        name = models.CharField(max_length=32)
        
    # 一对多的关系
    class Book(models.Model):
        name = models.CharField(max_length=32)
        pub = models.ForeignKey(to='Publisher',on_delete=None) 
        
        def __str__(self):
            return self.name
    

    查询

    from app01 import models 
    
    models.Publisher.objects.all()  #查询所有的数据  QuerySet  对象列表 
    models.Publisher.objects.get(name='xxx') 
    					#查询一条数据  只能查有且唯一的数据
    models.Publisher.objects.filter(name='xxx') 
    					#查询所有满足条件的数据 对象列表 
        
    for book in all_books:
        print(book)
        print(book.id)
        print(book.pk)
        print(book.name)
        print(book.pub)  # 所关联的出版社对象    	对象.外键
        print(book.pub_id)  # 所关联的出版社对象的id   对象.外键_id
    

    新增

    obj = models.Publisher.objects.create(name='xxxx')
    
    models.Book.objects.create(name=book_name,
                               pub=models.Publisher.objects.get(pk=pub_id))
    obj = models.Book.objects.create(name=book_name, pub_id=pub_id)
    
    obj = models.Publisher(name='xxxx')
    obj.save()  # 保存到数据库
    
    obj = models.Book(name='xxx',pub_id=出版社的对象id)
    obj.save()
    
    
    多对多的新增:
    书对作者
    book_id = request.POST.getlist('book_id')
    # 插入数据
    obj = models.Author.objects.create(name=author_name)
    obj.books.set(book_id) # 设置多对多的关系
    

    删除

    models.Publisher.objects.filter(pk=pk).delete()   # 批量删除
    models.Publisher.objects.get(pk=pk).delete()	# 单条数据的删除
    

    更新

    models.Book.objects.filter(pk=pk).update(name=book_name,pub_id=pub_id)  # 批量更新
    
    obj = models.Book.objects.filter(pk=1).first()
    obj.name = 'xxxx'
    obj.pub_id = 2
    # book_obj.pub  =  出版社的对象
    obj.save()  #保存更新
    

    外键

    一对多的关系

    class Book(models.Model):
        name = models.CharField(max_length=32)
        pub = models.ForeignKey('Publisher', on_delete=models.CASCADE)
      
     
        """
        on_delete 在2.0版本之后是必填的
        on_delete= 
            models.CASCADE  级联删除
            PROTECT   保护
            SET(1)    
            SET_DEFAULT  设置为默认值设置为某一个值
            SET_NULL   设置为空
            DO_NOTHING 什么都不变
        """
    
    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
    import django
    
    django.setup()  # 初始化
    
    from app01 import models
    
    # 基于对象的查询
    # 正向查询
    book_obj = models.Book.objects.get(pk=3)
    # print(book_obj)
    # print(book_obj.pub)
    
    # 反向查询
    # 没有指定related_name  表名小写_set
    pub_obj = models.Publisher.objects.get(pk=2)
    # print(pub_obj.book_set,type(pub_obj.book_set))  # 关系管理对象
    print(pub_obj.book_set.all())
    
    # related_name='books'
    # print(pub_obj.books.all())
    
    
    # 基于字段的查询
    ret = models.Book.objects.filter(pub__name='老男孩出版社')
    # print(ret)
    
    # 没有指定related_name  类名小写__字段
    ret = models.Publisher.objects.filter(book__name='没有页码的python书')
    # 指定related_name  related_name__字段
    ret = models.Publisher.objects.filter(books__name='没有页码的python书')
    
    # 指定related_query_name='book'  related_query_name_name__字段
    # ret = models.Publisher.objects.filter(book__name='没有页码的python书')
    # print(ret)
    
    

    多对多

    class Pulisher(models.Model):
    	name = models.CharField(max_length=32)
    
    class Book(models.Model):
    	name = models.CharField(max_length=32)
        pub = models.ForeignKey('Pulisher',on_delete=models.DO_NOTHING)
    
    class Author(models.Model):
    	name = models.CharField(max_length=32)
    	books= models.ManyToManyField(to='Book') 
    
    # 查询
    book_obj.pub   # 所关联的对象   book_obj.pub_id  所关联的对象的id
    
    author_obj.books  # 关系管理对象
    author_obj.books.all()   # 所关联的所有的书籍对象
    
    # 新增
    Book.objects.create(name='xxx',pub=对象)
    Book.objects.create(name='xxx',pub_id=对象的ID)
    
    obj= Book(name='xxx',pub_id=对象的ID)
    obj.save()
    
    obj = Author.objects.create(name='xxx')
    obj.books.set([书籍id,书籍id])
    
    # 删除
    Book.objects.filter(pk=pk).delete()  # QuerySet 删除
    Author.objects.get(pk=pk).delete()   # 对象 删除
    
    # 编辑
    Book.objects.filter(pk=pk).update(name='xxx')
    
    book_obj.name ='xxxx'
    book_obj.save()
    
    Author.objects.filter(pk=pk).update(name='xxx')
    author_obj.books.set([id,id])
    
    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
    import django
    
    django.setup()  # 初始化
    
    from app01 import models
    
    author_obj = models.Author.objects.get(pk=1)
    
    # print(author_obj.books.all())
    
    book_obj = models.Book.objects.get(pk=1)
    # print(book_obj.author_set.all())
    
    ret = models.Author.objects.filter(books__name='没有页码的python书')
    ret = models.Book.objects.filter(author__name='bigbao')
    
    # print(ret)
    # set 设置多对多的关系  [id]   [对象]
    # author_obj.books.set([3,])
    # author_obj.books.set( models.Book.objects.all()) # [对象,对象]
    
    # add 添加多对多的关系  id   对象
    # author_obj.books.add(1,2,3)
    # author_obj.books.add(*models.Book.objects.all())  # *[对象,对象]
    
    # remove 删除多对多的关系  id   对象
    # author_obj.books.remove(1,2)
    # author_obj.books.remove(*models.Book.objects.filter(pk__in=[1,2])) # [对象,对象]
    
    
    # clear 清除多对多的关系
    # author_obj.books.clear()
    
    # create 新增一个所关联的对象 并且和当前的对象设置关系
    author_obj.books.create(name='跟和尚学合气道', pub_id=1)
    
    # book_obj.author_set
    
    # 多对一  反向查询 一 ——》 多  关系管理对象
    # 关系管理对象.set([对象,对象])
    # 关系管理对象.add(对象,对象)
    
    #  外键字段 null=True, 才有remove,clear
    # 关系管理对象.remove(对象,对象)
    # 关系管理对象.clear()
    
    # 关系管理对象.create()
    

    必知必会13条

    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
    import django
    
    django.setup()  # 初始化
    
    from app01 import models
    
    # all()  查询所有的数据  QuerySet 对象列表
    ret = models.Person.objects.all()
    
    # filter  获取满足条件的所有的对象  QuerySet 对象列表
    ret = models.Person.objects.filter(name='alex')
    
    # exclude  获取不满足条件的所有的对象  QuerySet 对象列表
    ret = models.Person.objects.exclude(name='alex')
    
    # values()
    #  不指定字段 获取所有字段名和值  QuerySet 对象列表  [ {},{} ]
    #  指定字段  values('pid','name')  获取指定字段名和值  QuerySet 对象列表  [ {},{} ]
    ret = models.Person.objects.all().values()
    ret = models.Person.objects.filter(name='alex').values('pid', 'name')
    
    # values_list()
    #  不指定字段 获取所有的值  QuerySet 对象列表  [ (),() ]
    #  指定字段  values_list('pid','name')  获取指定的值  QuerySet 对象列表  [ (),() ]
    ret = models.Person.objects.all().values_list()
    ret = models.Person.objects.filter(name='alex').values_list('name', 'pid', )
    
    # order_by  排序 默认升序  -降序  可以多个字段排序
    ret = models.Person.objects.all().order_by('age', '-pid')
    
    # reverse  对已经排序的QuerySet做的反转
    ret = models.Person.objects.all().order_by('pid').reverse()
    
    # get    获取满足条件的一个的对象  对象
    ret = models.Person.objects.get(name='alex')
    
    # first  获取第一个元素   对象  获取不到的时候是none
    ret = models.Person.objects.filter(name='xxx').first()
    
    # last  获取最后一个元素   对象  获取不到的时候是none
    ret = models.Person.objects.filter(name='xxx').last()
    
    #  count 计数
    ret = models.Person.objects.all().filter(age=84).count()
    
    # exists 数据是否存在
    ret = models.Person.objects.filter(age=84).exists()
    
    # distinct  去重  数据时完全一样才去重
    ret = models.Person.objects.filter(age=84).values('age').distinct()
    
    
    
    """
    返回对象列表
    all
    filter 
    exclude 
    order_by 
    reverse
    values   [{}] 
    values_list   [()] 
    distinct  
    
    返回对象
    get
    first  
    last 
    
    返回数字
    count
    
    返回布尔值
    exists
    
    """
    

    单表的双下划线

    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
    import django
    
    django.setup()  # 初始化
    
    from app01 import models
    
    ret = models.Person.objects.filter(pk__gt=3)  # greater than   where pk > 3
    ret = models.Person.objects.filter(pk__gte=3)  # greater than equal   where pk >= 3
    
    ret = models.Person.objects.filter(pk__lt=3)  # less than   where pk < 3
    ret = models.Person.objects.filter(pk__lte=3)  # less than equal   where pk <= 3
    
    ret = models.Person.objects.filter(pk__range=[1,3])  # 1 <= pk <= 3
    ret = models.Person.objects.filter(pk__in=[1,3,7,10,100])  # 成员判断
    
    ret = models.Person.objects.filter(name__contains='bigbao')  # like   不忽略大小写
    ret = models.Person.objects.filter(name__icontains='bigbao')  # like  ignore  忽略大小写
    
    ret = models.Person.objects.filter(name__startswith='b')  # 以什么开头 不忽略大小写
    ret = models.Person.objects.filter(name__istartswith='b')  # 以什么开头 忽略大小写
    
    ret = models.Person.objects.filter(name__endswith='o')  # 以什么结尾 不忽略大小写
    ret = models.Person.objects.filter(name__iendswith='o')  # 以什么结尾 忽略大小写
    
    ret = models.Person.objects.filter(age__isnull=False)   # 字段是否为空
    
    
    ret = models.Person.objects.filter(birth__year='2019')   # 按照年份
    ret = models.Person.objects.filter(birth__contains='2019-12-19')  # 时间包含
    
    
    print(ret)
    
    

    外间的操作

    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
    import django
    
    django.setup()  # 初始化
    
    from app01 import models
    
    # 基于对象的查询
    # 正向查询
    book_obj = models.Book.objects.get(pk=3)
    # print(book_obj)
    # print(book_obj.pub)
    
    # 反向查询
    # 没有指定related_name  表名小写_set
    pub_obj = models.Publisher.objects.get(pk=2)
    # print(pub_obj.book_set,type(pub_obj.book_set))  # 关系管理对象
    print(pub_obj.book_set.all())
    
    # related_name='books'
    # print(pub_obj.books.all())
    
    
    # 基于字段的查询
    ret = models.Book.objects.filter(pub__name='老男孩出版社')
    # print(ret)
    
    # 没有指定related_name  类名小写__字段
    ret = models.Publisher.objects.filter(book__name='没有页码的python书')
    # 指定related_name  related_name__字段
    ret = models.Publisher.objects.filter(books__name='没有页码的python书')
    
    # 指定related_query_name='book'  related_query_name_name__字段
    # ret = models.Publisher.objects.filter(book__name='没有页码的python书')
    # print(ret)
    
    
    

    聚会和分组

    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
    import django
    
    django.setup()  # 初始化
    
    from app01 import models
    
    from django.db.models import Max, Min, Avg, Sum, Count
    
    ret = models.Book.objects.filter(id__gt=3).aggregate(max=Max('price'), min=Min('price'))
    
    # 统计每一本书的作者个数
    ret = models.Book.objects.annotate(Count('author'))  # 按照book进行分组  统计作者的个数
    
    # 统计出每个出版社的最便宜的书的价格
    ret = models.Publisher.objects.annotate(Min('book__price')).values()
    
    ret = models.Book.objects.values('pub', 'pub__name').annotate(Min('price'))
    
    # 统计作者的图书的个数
    
    ret = models.Author.objects.annotate(Count('books')).values()
    
    ret = models.Book.objects.values('author').annotate(Count('id'))
    
    # 统计不止一个作者的图书
    ret = models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)
    
    # 根据一本图书作者数量的多少对查询集 QuerySet进行排序
    ret = models.Book.objects.annotate(count=Count('author')).order_by('-count')
    
    # 查询各个作者出的书的总价格
    ret = models.Author.objects.annotate(Sum('books__price')).values()
    
    ret = models.Book.objects.values('author').annotate(Sum('price'))
    
    print(ret)
    
    

    F

    可以拿字段出来对比

    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
    import django
    
    django.setup()  # 初始化
    
    from app01 import models
    from django.db.models import F, Q
    
    
    # ret = models.Book.objects.filter(sale__gt=F('kucun'))
    # ret = models.Book.objects.update(sale=F('sale')*2)
    
    
    print(ret)
    

    Q

    | 或

    & 与
    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
    import django
    
    django.setup()  # 初始化
    
    from app01 import models
    from django.db.models import F, Q
    
    ret = models.Book.objects.exclude(pk__lte=3, pk__gte=2)
    ret = models.Book.objects.filter(Q(~Q(Q(pk__gt=3) & Q(pk__lt=2))) & Q(name__contains='跟'))
    
    print(ret)
    

    事务

    import os
    
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
    import django
    
    django.setup()  # 初始化
    
    from app01 import models
    
    from django.db import transaction
    
    try:
        with transaction.atomic():
            # 一系列的ORM操作
            models.Publisher.objects.create(name='xxx')
            models.Publisher.objects.create(name='xxx')
    except Exception as e:
        print(e)
    
    print('xxx')
    
    

    cookie

    定义

    ​ 保存在浏览器本地上一组组键值对

    特点

    1.cookie是由服务器进行设置的
    2.浏览器保存在本地的
    3.下次访问时自动携带对应的cookie

    设置

    response.set_cookie(key,value)   # Set-Cookie: is_login=1; Path=/
    response.set_signed_cookie('is_login','1',salt='xxxx')
    #两种操作方式相同,第二种推荐,salt='xxxx',以xxxx来进行加盐
    response.set_signed_cookie(key,value,salt='xxxx',max_age=5,path='/')
    	#max_age=5,让浏览器记住登录状态的时间最大为五秒,超过五秒清楚is_login
    

    获取

    request.COOKIES #  {} 
    request.COOKIES[key]# 没有会报错
    request.COOKIES.get(key)
    request.get_signed_cookie(key,salt='xxxx',default='')
    #default='' 默认值设置为空,不然取不到会报错
    

    删除

    response.delete_cookie(key)  # 设置键值对的值为空 超时时间为0
    

    装饰器

    让装了装饰器的函数的名字不是inner,而是原来的名字

    from functools import wraps
    
    def wrapper(func):
        @wraps(func)  # 复制了原来函数的名字和注释
    	def inner(request,*arg,**kwargs):
            # 之前
            ret = func(request,*arg,**kwargs)
            # 之后
            return ret 
        return inner
    
    @wrapper  # f1 = wrapper(f1)
    def f1(request):
        pass
    
    f1.__name__  #  inner _> f1   #让装了装饰器的函数的名字不是inner,而是原来的名字
    

    response

    diango中有三种response

    from django.shortcuts import render, redirect, HttpResponse
    HttpResponse()
    render()
    redirect()
    

    session

    定义

    保存在服务器上的一组组键值对,必须依赖cookie

    为什么要有session?

    1. cookie保存在浏览器上,不太安全
    2. cookie的大小和个数有限制

    设置

    request.session[key] = value 
    request.session[is.login]=1
    

    获取

    request.session[key] #这样取值没有取值会报错
    request.session.get(key)
    

    删除

    request.session.pop('is_login')
    request.session.delete()  #  删除所有的session数据
    request.session.flush()   #  删除所有的session数据和cookie
    

    其他

    request.session.clear_expired()		#清除过期的session  ?
    request.session.set_expiry(value)   #设置session过期的时间
    

    配置

    from django.conf import global_settings
    #在global_settings中查看全局配置
    #在settings中覆盖修改
    
    SESSION_COOKIE_NAME = 'session'   # cookie的名字
    SESSION_SAVE_EVERY_REQUEST = True  # 每次请求都更新session
    SESSION_EXPIRE_AT_BROWSER_CLOSE = True  # 浏览器关闭session就失效
    
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'
    from django.contrib.sessions.backends import db #session在哪储存
    # 数据库  缓存  缓存+数据库  文件 加密cookie
    

    正则表达式

    ^ 开头

    $ 结尾

    [0-9] 数字

    [a-zA-Z] 英文字母

    [asd]{4,6}

    +(一个或多个)
    *(0个或多个)

    ? (0个或1个)

    d 阿拉伯数字

    w 匹配字母或数字或下划线或汉字 等价于'[^A-Za-z0-9_]

    .(除了换行符之外的任意字符)

    url的命名和反向解析

    静态路由

    url(r'^login/', views.login,name='login'),
    

    反向解析ht

    模板

    {% url 'login' %}   ——》  '/app01/login/'
    

    py文件

    from django.urls import reverse
    reverse('login')   ——》  '/app01/login/'
    

    分组路由

    位置传参

    url(r'^del_publisher/(d+)/', views.del_publisher,name='del_pub'),
    #分组后从url中捕获参数,捕获的参数会按照 位置传参 传递给函数
    

    关键字传参

    url(r'^del_publisher/(?P<pk>d+)/', views.del_publisher),
    #分组后从url中捕获参数,捕获的参数会按照 关键字传参 传递给函数
    

    反向解析

    模板

    {% url 'del_pub' '1' %}   ——》  '/app01/del_publisher/1/'
    

    py文件

    from django.urls import reverse
    reverse('del_pub',args=('1',))   ——》  '/app01/del_publisher/1/'
    

    命令分组 路由

    url(r'^del_publisher/(?P<pk>d+)/', views.del_publisher,name='del_pub'),
    

    反向解析

    模板

    {% url 'del_pub' '1' %}   ——》  '/app01/del_publisher/1/'     位置传参
    {% url 'del_pub' pk='1' %}   ——》  '/app01/del_publisher/1/'  关键字传参
    

    py文件

    from django.urls import reverse
    reverse('del_pub',args=('1',))   ——》  '/app01/del_publisher/1/'    位置传参
    reverse('del_pub',kwargs={'pk':'1'})   ——》  '/app01/del_publisher/1/'  关键字传参
    

    namespace

    多人合作开发解决路径重复问题

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^app01/',include('app01.urls',namespace='app01' )),   
        url(r'^app02/',include('app02.urls',namespace='app02')),    
    ]
    
    {% url 'app01:del_pub' '1' %}
    reverse('app01:del_pub',args=('1',)) 
    

    MVC

    M: model 模型 与数据库交互

    V: view 视图 HTML

    C:controller 控制器 流程 和 业务逻辑

    MTV

    M:model ORM

    T:template 模板 HTML

    V:view 视图 业务逻辑

    Django中的视图

    FBV

    def add_publisher(request,*args,**kwargs):
    	# 逻辑
    	return  response
    

    urls.py

      url(r'^add_publisher',add_publisher )
    

    CBV

    from django.views import View
    class Addpublisher(View):
    	def get(self,reuqest,*args,**kwargs)
            # 处理GET请求的逻辑
            self.request
            return  response
        
        def post(self,reuqest,*args,**kwargs)
            # 处理POST请求的逻辑
            return  response
    

    urls.py

      url(r'^add_publisher',Addpublisher.as_view() )
    

    CBV中不同的请求能找到相应函数执行的原因:
    继承了View,程序加载的时候,执行View中的Addpublisher.as_view(),
    Addpublisher.as_view()定义了一个view函数,返回view,通过反射获取请求方式对应的方法(get/post)。

    as_view的流程:
    
    1. 程序加载的时候,执行Addpublisher.as_view():
    
       定义了一个view函数,返回view
    
       url(r'^add_publisher',view )
    
    2. 请求到来时,执行view函数:
    
       1. 实例化对象  ——》 self
       2. self.request = request
       3. 执行self.dispatch(request, *args, **kwargs)
          1. 判断请求方式是否被允许:
             1. 允许: 通过反射获取请求方式对应的方法(get/post)  ——》 handler
             2. 不允许:self.http_method_not_allowed  ——》 handler
          2. 执行handler,将它的结果返回
    

    加装饰器

    FBV

    FBV 直接加

    @login_required
    def publisher(request):
    

    CBV

    解决装饰器加同时加在类和函数上时的参数导致的复用性问题:
    不加method_decorator,加在类方法上,需要第一个参数需要是self,如果在login_required的inner括号里加上了self,函数便无法用这个装饰器了,所以装饰器加在类上时要借助method_decorator

    from django.utils.decorators import method_decorator
    
    登录验证的装饰器
    def login_required(func):
        def inner(request, *args, **kwargs):
            # print(request.COOKIES)
            # is_login = request.COOKIES.get('is_login')
            # is_login = request.get_signed_cookie('is_login', salt='xxxx', default='')
            is_login = request.session.get('is_login')
            # print(request.path_info)
            # print(request.get_full_path())
            print(request.META.get('HTTP_ACCEPT'))
    
            print(is_login)
            if is_login != 1:
                # 没有登录 跳转到登录页面
                url = request.path_info
                return redirect('/login/?url={}'.format(url))
            ret = func(request, *args, **kwargs)
    
            return ret
    
            # if is_login == '1':
            #     # 登录
            #     ret = func(request, *args, **kwargs)
            #     return ret
            # else:
            #     url = request.path_info
            #     return redirect('/login/?url={}'.format(url))
    
        return inner
    
    
    
    # 加在方法上
    @method_decorator(login_required)
    def get(self, request, *args, **kwargs):
    
    # 重写dispatch方法,加在dispatch方法上
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        ret = super().dispatch(request, *args, **kwargs)
        return ret
    
    #直接找到父类的dispatch方法加上去 ——最简单!推荐!
    @method_decorator(login_required,name='dispatch')
    class Addpublisher(View)
    
    # 加在类上
    @method_decorator(login_required,name='post')
    @method_decorator(login_required,name='get')
    class Addpublisher(View)
    
    

    request对象的方法

    request.method  # 请求方法 GET POST 
    request.GET     # url上携带的参数  {}  
    request.POST   # form提交POST请求的参数  {}   编码类型是urlencode 
    request.body   # 请求体  b''
    request.path_info  # 路径  不包含ip和端口  也不包含参数
    request.COOKIES  # cookie的字典 
    request.session  # session的数据
    request.FILES  # 上传的文件  编码的类型是  enctype="multipart/form-data"
    request.META     # 请求头   小写 ——》 大写  HTTP_    - _> _
    
    request.get_full_path()   # 路径  不包含ip和端口  包含参数
    request.get_signed_cookie(key)  # 获取加密cookie
    request.is_ajax()   # 是否是ajax
    

    response对象的方法

    HttpResponse('xxxx')  # 返回字符串   Content-Type: text/html; charset=utf-8
    render(request,'模板的路径',{})   # 返回一个页面
    redirect('路径')   # 重定向  状态码301 302  响应头 Location:路径
    
    from django.http.response import JsonResponse
    

    模板中

    变量 {{ 变量名 }}

    通过(.)取相应的内容

    .key > .属性 .方法 > .索引

    过滤器

    {{ 变量|过滤器 }} {{ 变量|过滤器:参数 }}

    {{ kong | default:'没有传参' }}
    

    filter

    {{ 变量|filter:参数 }}

    default add length slice join first last lower upper title truncatechars truncatewords

    date:"Y-m-d H:i:s" safe

    USE_L10N = False
    DATETIME_FORMAT = 'Y-m-d H:i:s'
    

    标签

    {% %}

    for

    {%  for i in list %}
    
    	{{ i }}
    
    {% endfor %}
    

    forloop.counter 循环的序号 从1开始

    forloop.counter0 循环的序号 从0开始

    forloop.revcounter 循环的序号 到1结束

    forloop.revcounter0 循环的序号 到0结束

    forloop.first 是否是第一次循环

    forloop.last 是否是最后一次循环

    forloop.parentloop 当前循环的外层循环 {}

    {% for i in list  %}
    	{{ forloop }}
    	{{ i }}
    	
    {% empty %}
    	空空如也
    {% endfor %}
    

    if 不支持算数运算

    {% if  条件  %}
    	x
    {% elif  条件1  %}
    	xx
    {% else %}
    	xxx
    {% endif %}
    

    注意点:

    1. 不支持算数运算
    2. 不支持连续判断 10 > 5 > 1 false

    csrf

    {% csrf_token %}  #  form表单中有一个隐藏的input标签  name=‘csrfmiddlewaretoken’
    

    母版和继承

    母版:

    ​ 模板,提取出多个页面公共部分放在一个母版中,定义上多个block块,让子页面重新复写。

    继承:

    1. {% extends ‘母版的名字’ %}
      2. 重写block块。

    注意点:

    1. {% extends ‘母版的名字’  %}  母版名字 的引号好带上   不带会当做变量
    
    1. {% extends ‘母版的名字’ %} 上不要写内容

      1. 要替换母版的内容都写在block块中

      2. 定义多个block块, css,js

    组件:

    把一小段的HTML代码段 ——》 nav.html

    {% include 'nav.html ' %}
    

    静态文件的使用:

    {% load static %}
    "{% static '静态文件的相对路径' %}"
    

    母版和组件的继承和引用怎么用?

    使用admin的步骤

    1. 创建超级用户

      python manage.py createsuperuser

    2. 注册model

      在app下的admin.py中注册

      from django.contrib import admin
      from app01 import models
      # Register your models here.
      admin.site.register(models.Person)
      
    3. 访问网站登录操作

    中间件

    process_request(self,request)

    参数:

    ​ request 请求的对象,和视图中的request是同一个

    执行时间:视图函数之前

    执行顺序:

    ​ 按照注册的顺序 顺序执行

    返回值

    ​ None : 正常流程

    ​ HttpReponse: 当前中间件之后的中间件的process_request方法、路由匹配、视图也不执行,直接执行当前中间件的process_response方法

    process_response(self, request, response)

    参数:

    ​ request 请求的对象,和视图中的request是同一个

    ​ response 返回的响应对象

    执行时间:视图函数之后

    执行顺序:

    ​ 按照注册的顺序 倒叙执行

    返回值

    ​ HttpReponse: 必须返回响应对象

    process_view(self, request, view_func, view_args, view_kwargs)

    参数:

    ​ request 请求的对象,和视图中的request是同一个

    ​ view_func 视图函数

    ​ view_args 视图函数的位置参数

    ​ view_kwargs 视图函数的关键字参数

    执行时间:路由匹配之后,视图函数之前

    执行顺序:

    ​ 按照注册的顺序 顺序执行

    返回值

    ​ None 正常流程

    ​ HttpReponse: 当前中间件之后的process_view、视图不执行,执行最后一个中间的process_response

    process_exception(self, request, exception)

    参数:

    ​ request 请求的对象,和视图中的request是同一个

    ​ exception 错误对象

    执行时间(触发条件):视图层面有错误才执行

    执行顺序:

    ​ 按照注册的顺序 倒叙执行

    返回值

    ​ None 当前中间没有处理异常,交由下一个中间件处理异常,所有的中间件都没有处理,Django处理错误

    ​ HttpReponse: 当前中间处理好异常,之后执行最后一个中间件的process_response方法

    pocess_template_response(self,request,response)

    参数:

    ​ request 请求的对象,和视图中的request是同一个

    ​ response 返回的响应对象

    执行时间:视图必须返回一个template_response对象

    执行顺序:

    ​ 按照注册的顺序 倒叙执行

    返回值

    ​ HttpReponse: 必须返回响应对象

    response.template_name = 'index1.html'  # 改模板
    response.context_data # 改变量
    

    Django的请求的生命周期

    1. 简介目录
    ![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/p/9029086.html

    2. 路由系统
    ![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9282718.html

    3. 视图
    ![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9285269.html

    4. 模板
    ![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9333821.html

    5.ORM
    字段和参数:![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9323320.html
    查询操作:![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9403501.html
    练习题:![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9414626.html

    6. cookie和session
    ![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9502602.html

    7.中间件
    ![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9333824.html

    8. ajax
    ![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9524153.html

    9. form组件
    ![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9537309.html

    AJAX

    js技术,发送请求的一种方式.

    特点:

    1. 异步
    2. 传输的数据量小
    3. 局部刷新

    发请求的途径:

    1. form表单发请求 指定method GET/POST
      1. action 地址 method enctype
      2. input select option 标签要有name属性,有的还需要有value
      3. 有button按钮或者type='submit'的input框
    2. 直接在地址栏中输入地址 回车 get
    3. a标签 get
    4. ajax

    发ajax请求的写法:

    jQuery:

    $.ajax({
        url: '/test/',   //  url路径
        type: 'post',    // 请求方式
        data: {          // 请求数据
            name: 'alex',
            age: 84,
            hobby: JSON.stringify(['吐口水', 'TESA', '篮球', '毒鸡汤']),
        },
        success: function (res) {   // 响应成功的回调函数
            console.log(res);
            console.log(res.status);
            console.log(typeof(res))
        },
        error:function (res) {		// 响应失败的回调函数
            console.log(res)
    
        }
    })
    

    上传文件

    $('#b1').click(function () {
    
            var form_obj = new FormData();  // enctype="multipart/form-data"
            form_obj.append('name', 'alex')
            form_obj.append('f1', $('#f1')[0].files[0])
    
            $.ajax({
                url: '/upload/',
                type: 'post',
                data: form_obj,
                processData: false, // 不需要处理编码方式
                contentType: false, // 不需要处理contentType请求头
                success:function (res) {  //  响应成功的回调函数  res _> 返回的响应体
                    alert(res)
                }
    
            })
        })
    

    CSRF中间件

    1. process_request方法:

      从cookie中获取csrftoken的值,放到request.META中

    2. process_view方法:

      1. 判断视图是否使用csrf_exempt装饰器,使用了就不校验
      2. 判断请求方式是否是'GET', 'HEAD', 'OPTIONS', 'TRACE',如果是,也不校验
      3. 进行校验:
        1. csrf_token = request.META.get('CSRF_COOKIE') # cookie中获取csrftoken的值
      4. 请求方式是POST
        1. request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
        2. 获取不到,从头中获取x-csrftoken的值 = >request_csrf_token
        3. 进行比较csrf_token request_csrf_token的值:
          1. 对比成功 接收请求
          2. 对比不成功 拒绝请求

    ajax通过Django的csrf校验

    前提:

    有csrftoken的cookie:

    1. {% csrf_token %}

    2. from django.views.decorators.csrf ensure_csrf_cookie
      

    方式一:

    给data中添加csrfmiddlewaretoken的键值对

    方式二:

    给headers添加x-csrftoken的键值对

    headers: { 
    'x-csrftoken': $('[name="csrfmiddlewaretoken"]').val()},
    

    方式三:

    导入文件

    csrf相关的装饰器

    from django.views.decorators.csrf import csrf_exempt,csrf_protect,ensure_csrf_cookie
    
    csrf_exempt   豁免csrf的校验   CBV需要加在dispatch方法上才生效
    csrf_protect  强制校验
    ensure_csrf_cookie  添加csrftoken的cookie
    

    form组件

    定义:

    from django import forms
    
    class RegForm(forms.Form):
        user = forms.CharField(label='用户名')
        pwd = forms.CharField(label='密码',widget=forms.PasswordInput)
    

    使用:

    视图函数:

    def reg2(request):
        form_obj = RegForm()
        if request.method == 'POST':
            form_obj = RegForm(request.POST)
            if form_obj.is_valid():
                # 校验成功
                # form_obj.cleaned_data # 清洗后的数据
                return HttpResponse('注册成功')
    
    
        return render(request, 'reg2.html', {'form_obj': form_obj})
    

    模板:

    {{ form_obj.as_p }}   _>       生成所有字段的input框
    
    {{ form_obj.user }}         _> 某个字段的input框
    {{ form_obj.user.label }}   _> 某个字段的中文提示
    {{ form_obj.user.id_for_label }}   _> 某个字段的input框的ID
    
    
    {{ form_obj.errors }}   _>  所有的错误
    {{ form_obj.user.errors }}  _>  某个字段的所有错误
    {{ form_obj.user.errors.0 }}  _>  某个字段的第一个错误
    

    常用的字段

    CharField  
    ChoiceField
    MultipleChoiceField  
    

    字段的参数

    initial  初始值
    required  是否必填
    disabled  是否禁用
    label 	  中文提示
    initial   默认值
    min_length  最小长度
    error_messages   错误信息
    choices   可选择的数据
    

    校验

    1. 自带的校验

    2. 自定义校验规则

      1. 写函数

        from django.core.exceptions import ValidationError
        
        
        def check_name(value):
            # 自定义校验规则
            # 如果校验合格 什么都不做
            # 校验不合格   抛出异常
            if 'alex' in value:
                raise ValidationError('不能包含alex,非法字符')
                
        
    3. 使用内置的校验器

      from django.core.validators import RegexValidator
      
      validators=[RegexValidator(r'^1[3-9]d{9}$', '手机号格式不正确')]
      

    局部钩子和全局钩子

    def clean_user(self):
        # 局部钩子
        # 校验成功  返回当前字段的值
        # 校验不成功  抛出异常
        if 'alex' in self.cleaned_data.get('user'):
            raise ValidationError('不能包含alex,非法字符')
        return self.cleaned_data.get('user')
    
    def clean(self):
        # 全局钩子
        # 校验成功  返回所有字段的值 self.cleaned_data
        # 校验不成功  抛出异常
        pwd = self.cleaned_data.get('pwd')
        re_pwd = self.cleaned_data.get('re_pwd')
        if pwd == re_pwd:
            return self.cleaned_data
        else:
            self.add_error('re_pwd','两次密码不一致!!!')
            raise ValidationError('两次密码不一致')
    
    
  • 相关阅读:
    数据可视化图表详解(一)
    大数据思维
    常用的107条Javascript
    common.js js中常用方法
    MVC框架
    实现手机发送验证码 进行验证
    css3媒体查询实现网站响应式布局
    用谷歌浏览器来模拟手机浏览器
    响应式web网站设计制作方法
    css命名
  • 原文地址:https://www.cnblogs.com/-xct/p/12026175.html
Copyright © 2020-2023  润新知