zoukankan      html  css  js  c++  java
  • Django

    Django

    Django项目是一个python定制框架,采用了MVT的框架模式,即模型M,视图V和模板T

    本质还是MVC(Models、Views、Controller)

    Django项目的创建

    1. 命令行式

      #1.cmd
      >>django-admin startproject project_name
      
      #2.切换到项目文件夹下
      #>>python2 manage.py runserver 127.0.0.1:8000(可指定ip地址)
      >>python3 manage.py runserver
      
      #3.创建应用(django支持多应用开发)
      >>python3 manage.py startapp app_name
      '''
      注意:
      1.不会自动创建templates文件夹
      2.配置文件中不会自动书写templates文件路径
      '''
      

      Django中的app

      Django是一个以开发app为主要功能的web框架

      一个app是一套Django功能的集合,通常包括模型和视图,按python的包结构的方式存在

      Django为app提供了前期的环境配置

      *创建好的app需要在Django配置文件中注册方可生效

    Django框架的分层

    Django框架就是为了开发app,而app的工作过程本质就是根据不同的请求返回不同的数据

    Django框架将工作过程分为四层:

    1. 路由层 urls.py 根据不同的地址执行不同的视图函数u
    2. 视图层 views.py 定义处理业务逻辑的视图函数
    3. 模型层 models.py 和数据库交互
    4. 模板层 templates.py 存储返回给浏览器的html文件

    请求生命周期

    Django文件功能

    Django项目名(根目录)

    项目同名的文件夹

    settings.py 暴露给用户可以配置的配置文件

    urls.py 路由和视图函数的对应关系

    manage.py

    Django的入口文件

    应用名文件夹

    migrations文件夹 所有数据库的相关操作记录

    admin.py Django-admin后台管理

    apps.py 注册app使用

    models.py 存放数据库所有有关的模型类

    tests.py 测试文件

    views.py 处理业务逻辑的视图函数

    基本操作

    #HttpRespnonse	返回字符串
    def httpresp(request):
        return HttpRespnonse('这是一个字符串')
    
    
    #render		返回html文件,可以给html页面传值
    def ren(request):
        user_dic = {'username':'slk'}
        return render(request,'login.html',{'user_info':user_dic})
    
    
    #redirect  重定向,可以是本网站的路径后缀,也可以是全路径
    def home(request):
        return redirect('https://baidu,com')
    	retur redirect('/add_user/')  #如果是本网站路径后缀要加斜杠
    

    注意事项

    前期配置相关

    • 静态文件配置

      1. 默认情况下,所有的html文件都是放在templates文件夹内

      2. 静态文件是指网站所用到的提前写好的css、js、第三方的前端模块以及图片等静态资源

      3. 默认情况下,网站所用到的静态文件资源全部放在static文件夹(需要手动创建)下,static文件夹下可以在细分css文件夹、js文件夹、font文件夹、img文件夹、Bootstrap文件夹以及fontawesome文件夹等

      4. 路径配置

        STATIC_URL = '/static/'
        
        STATICFILES_DIRS = [
            os.path.join(BASE_DIR, 'static')
        ]
        
      5. 静态文件夹的动态绑定

        #在html的py文件中
        {% load static %}
        <link rel="stylesheet" href="{% static 'css文件相对路径' %}">
        <script src="{% static 'js文件相对路径' %}"></script>
        
    • 前期在向后端提交post请求出现403,需要在配置文件中注释一行内容

      # 中间件
      MIDDLEWARE = [
      'django.middleware.security.SecurityMiddleware',
      'django.contrib.sessions.middleware.SessionMiddleware',
      'django.middleware.common.CommonMiddleware',
      # 'django.middleware.csrf.CsrfViewMiddleware',
      'django.contrib.auth.middleware.AuthenticationMiddleware',
      'django.contrib.messages.middleware.MessageMiddleware',
      'django.middleware.clickjacking.XFrameOptionsMiddleware',
      ]
      
    • 连接数据库
      Django自带SQLite
      在右侧点击Database;第一次连接某个数据库时,需要下载驱动
      Django只会帮你建表,数据库需要手动创建,一个项目用一个数据库

      #配置文件
      DATABASES = {
          'default': {
          'ENGINE': 'django.db.backends.mysql',  # 指定数据库类型
          'NAME': 'day49',  # 指定库的名字
          'USER':'root',  # 注意 键必须是全大写
          'PASSWORD':'123qwe',
          'HOST':'127.0.0.1',
          'PORT':3306,
          'CHARSET':'utf8'
          }
      }
      
      #更改连接模块
      #在项目名下的__init__.py 或 应用名下的__init__.py 中
      import pymysql
      pymysql.install_as_MySQLdb()
      
    • orm 对象关系映射 缺点:封装程度太高,效率偏低;一个项目对应一个数据库

    • 取消django自动浏览器加斜杠的功能:

      #settings
      APPEND_SLASH = False
      

    数据库相关

    • 夺命13条

      1. # all()	查询所有	返回Queryset对象
        res = models.Table.objects.all()
        
      2. # filter()	筛选	相当于sql中的where关键字
        res = models.Table.objects.filter(pk=1,)
        
      3. # get()	筛选		获取到的是对象本身	条件不存在直接报错
        res = models.Table.objects.get(title='西游记',)
        
      4. # first()	取queryset中的第一个数据对象
        res = models.Books.objects.filter(title='西游记').first()
        
      5. # last()		取queryset中的最后一个数据对象
        res = models.Books.objects.filter(title='西游记').last()
        
      6. # count()  统计数据的个数   数字
        num = models.Books.objects.count()
        print(type(num))
        
      7. # values()  获取数据对象中指定的字段的值    返回queryset对象  列表套字典
        res = models.Books.objects.values('title','price')
        print(res)
        # <QuerySet [{'title': '三国演义', 'price': Decimal('222.66')}, {'title': '红楼梦', 'price': Decimal('888.99')}, {'title': '西游记', 'price': Decimal('444.66')}, {'title': '西游记', 'price': Decimal('666.22')}]>
        
      8. # values_list()  获取数据对象中指定的字段的值   返回queryset对象  列表套元祖
        res = models.Books.objects.values_list('title','price')
        print(res)
        #<QuerySet [('三国演义', Decimal('222.66')), ('红楼梦', Decimal('888.99')), ('西游记', Decimal('444.66')), ('西游记', Decimal('666.22'))]>
        
      9. # order_by()      按照指定的字段排序
        res = models.Books.objects.order_by('price')  # 默认是升序
        res1 = models.Books.objects.all().order_by('price')  # 默认是升序   两者等价 下面的方式 语义更明确
        # 降序  字段前面加负号
        res1 = models.Books.objects.all().order_by('-price')
        print(res1)
        
      10. # reverse()      颠倒顺序   前提是跌倒的对象必须有顺序(提前排序之后才能跌倒)
        res = models.Books.objects.all()
        res1 = models.Books.objects.all().reverse()
        res2 = models.Books.objects.all().order_by('price')
        res3 = models.Books.objects.all().order_by('price').reverse()
        print(res2,res3)
        
      11. # exclude()      排除什么什么之外   queryset对象
        res = models.Books.objects.all().exclude(title='三国演义')
        print(res)
        <QuerySet [<Books: 红楼梦>, <Books: 西游记1>, <Books: 西游记2>]>
        
      12. # exists()      判断查询结果是否有值 返回结果是一个布尔值	鸡肋
        res = models.Books.objects.filter(pk=1).exists()
        print(res)
        
      13. # distinct()    对查询结果进行去重操作     去重的前提:数据必须是完全想要的情况下 才能够去重(容易忽略主键),多和values()连用
        res = models.Books.objects.values('title','price')
        res = models.Books.objects.values('title','price').distinct()
        print(res)
        
      14. 小结:

        • 返回QuerySet对象的方法:

          all(),filter(),exclude(),order_by(),reverse(),ditince()
          
        • 特殊的QuerySet:

          values			返回列表套字典
          values_list		返回列表套元组
          
        • 返回具体对象:

          get(),first(),last()
          
        • 返回布尔值:

          exists()
          
        • 返回数字:

          count()
          

    urls相关

    • url正则匹配

      
      
    • 首页地址

      url(r'^$', views.home, name='home'),
      

    models相关

    • 数据库中已有记录,要新建字段

      1. 设置默认值,default=xxx
      2. 允许控制,null=True
      3. 根据报错提示,给默认值
    • CharField字段,必须要有max_length属性

    • INtegerField字段,默认长度11位

    • 与数据库结构相关的修改,必须要有数据库迁移命令,将操作同步到数据库中

      >>python manage.py makemigrations
      >>python manage.py migrate
      
    • 默认帮你定义了id(主键),自定义的是主键AutoField()

    • 添加外键

      # 一对多
      models.ForeignKey(to='表',to_field='字段',to_delete='级联操作')
      
      # 默认关联主键字段
      #默认级联删除和更新(models.CASCADE),只在应用层生效,在db层(数据库直接操作)RESTRICT(受限制)
      
      # 多对多,建议建在查询频率较高的表中,虚拟字段,在表中看不见,orm会自动创建一张关系表
      models.ManyToManyField(to='表')
      
      **************************************************************************************
      # through参数 可以来自定义的多对多关系的第三张表
      
      # Artical表
      tags = models.ManyToManyField(
          to='Tag',through='Article2Tag',
          through_fields=('article','tags')
      )
      
      # 自定义的Artical2Tag表
      class Article2Tag(models.Model):
          '''文章to标签表'''
      
          article = models.ForeignKey(to='Article')
          tags = models.ForeignKey(to='Tag')
      
      # 一对一,建议建在查询频率较高的表中
      models.OneToOneField(to='表')
      
      # 外键+唯一,不推荐
      models.FoeignKey(to='表',db_constraint='unique')
      
    • choice参数

      可以明确列出用户的所有选择

      先定义好对应关系,在通过choices参数来指定关系

    • auth模块:自动生成的包含各种用户信息的表

      from django.contrib import auth
      
      # 没有自定义用户表时
      from django.contrib.auth.models import User
      
      # 创建普通用户 密码自动加密
      User.objects.create_user(
          username=username,
          password=password
      )  
      
      # 创建超级用户   需要邮箱数据
      User.objects.create_superuser(
      	username=username,
      	password=password,
      	email='123@qq.com'
      )
      
      # 校验用户
      from django.contrib import auth
      user_obj = auth.authenticate(
      	request,
      	username=username,
      	password=password
      	)
      
      # 保存用户状态 执行了这句话,之后在任意位置就可通过 request.user获得当前登陆的用户对象
      auth.login(request,user_obj)  #只能使用调用一次?
      
      # 判断用户登陆
      request.user.is_authenticated()
      
      # 校验密码
      request.user.check_password(old_password)
      
      # 修改密码
      request.user.set_password(new_password)
      request.user.save()
      
      #注销用户 没有登陆也不会报错
      auth.logout(request)
      
      # 自定义继承user表的用户表,会保留原有的字段
      from django.contrib.auth.models import AbstractUser
      
      class Userinfo(AbstractUser):
          '''用户信息表'''
      
          phone = models.BigIntegerField(null=True)
          # auto_now_add会在创建时添加时间,auto_now会在创建和修改时修改时间
          register_time = models.DateField(auto_now_add=True)
          
      # 一定要注意 还需要去配置文件中配置
      # 这么写完之后 之前所有的auth模块功能全都以你写的表为准
      AUTH_USER_MODEL = 'app01.Userinfo'  # 应用名.表名
      

    views相关

    • 获取请求方式

      type_of_request = request.method(都是大写)
      
    • 获取请求数据

      #如果是a标签中href中携带的数据也用GET
      #当请求方式是GET时,一般使用render返回页面
      name = request.GET.get('name')
      
      #当请求方式时POST时,一般使用redirect重定向一个页面
      name = request.POST.get('name')
      
      #使用get()默认拿到列表的最后一个
      request.GET.getlist()
      request.POST.getlist()
      
    • 数据库操作

      #增
      new_obj = models.ClassName.objects.create(**kwargs)
      
      #删	根据filter查询的结果批量操作
      models.ClassName.objects.filter(**kwargs).delete()
      
      #改 根据filter查询结果批量操作
      models.ClassName.objects.filter(**kwargs).update(key=value)
      
      #查,支持切片,但不持支负数切片
      obj_list = models.ClassName.objects.filter(**kwargs)
      obj = obj_list.first()
      
      all_obj_list = models.ClassName.objects.all()
      #等价于
      all_obj_list = models.ClassName.objects.filter()
      

    前后端传输数据编码格式

    前后端交互是一个数据编码格式,针对不同的数据类型,后端会进行不同的处理

    • a标签href参数:get
    • form表单:get/post
    • ajax:get/post
    #获取方式
    
    request.POST
    request.GET
    request.FILES
    
    #三种格式
    urlencoded
    formdata
    application/json
    
    • form表单默认的编码方式是urlencoded,对应的数据格式username=jason&password=123,Django中会自动解析,并封装到POST中
    • form表单发送文件编码格式ContentType: multipart/formdata,针对formdata格式的数据,在浏览器上是无法查看到的;Django后端只要数据满足urlencoded格式,就会自动帮你解析到request.POST中;如果是文件对象,Django也会自动识别并封装到request.FILES
    • form表单无法发送json格式的数据,只能借助ajax
    • ajax能发送urlencodedformdataapplication/json三种格式数据;ajaz默认的编码格式是urlencoded,Django后端也是将数据解析到request.POST

    Ajax

    Asynchronous(异步) Javascript And XML

    ajax可以只刷新页面局部

    当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应

    Ajax基本语法结构

    $.ajax({
        url:'',
        type:'post',
        data:{'i1':$('#d1').val(),},
        success:function (data) {
            $('#d3').val(data)
        }
    })
    

    Ajax传输json格式数据

    Django后端针对json格式的数据,不会做任何处理,只会放到requset.body中,需要手动处理

    $('#d1').click(function () {
          $.ajax({
              url:'',
              type:'post',
              contentType:'application/json',  # 1.注意点1
              data:JSON.stringify({'username':'jason','password':'123'}),  # 2.注意点2
              success:function (data) {
                  alert(123)
              }
          })
      })
    

    Ajax传输文件数据

    借助于内置对象new,该对象既可以携带文件数据,也支持普通的键值对

    $('#d1').click(function () {
       // 先生成一个内置对象
       var MyFormData = new FormData();
       // 1. 先添加普通的键值
       MyFormData.append('username','jason');  // 添加了一组普通的简直对
       MyFormData.append('password','123');
       // 2. 添加文件数据
       MyFormData.append('myfile',$('#d2')[0].files[0]);  // 如何获取input框中文件对象$('#d1')[0].files[0]
       $.ajax({
          url:'',
          type:'post',
          data:MyFormData,  # 1
    
          // 发送文件必须要指定的两个参数
          contentType:false,  // 不适用任何编码  MyFormData对象内部自带编码 django后端能够识别  # 2
          processData:false,  // 不要处理数据  # 3
    
          success:function (data) {
    
          }
    
       })
     })
    

    orm相关

    • only

      only方法返回的是一个queryset对象,本质上是列表套对象;该对象内只含有only括号内所指定的属性
      
    • defer

      defer返回的是一个queryset对象,本质是列表套对象;该对象只含有除了defer括号内所指定的属性
      
    • select_related

      括号内只能放外键字段,并且外键字段只能是一对一或一对多;

      内部是连表操作;

      返回的结果是一个queryset,列表套对象;

      该数据对象后取当前表中的数据或关联表中的数据,不会再走数据库;

      主要耗时在连表操作;

    • prefetch_related

      括号内外键字段,类型全部支持;

      内部是子查询;

      返回结果是queryset,列表套对象;

      该数据对象后取当前表中的数据或关联表中的数据,不会再走数据库;

      主要耗时在查询次数;

    前端js相关

    • 获取input框中文件对象

      $('#d2')[0].files[0])
      
    • 序列化表单内键值对

       {# 自动序列化form表单内键值对 #}
       $.each($('#myform').serializeArray(), function (index, obj) {
       	MyFormData.append(obj.name, obj.value)
       });
      
    • 利用内置对象FormData传文件

      $('#submit').click(function () {
      
              {# FormData既可以传普通键值对,也可传文件对对象 #}
              let MyFormData = new FormData();
              {# 自动序列化form表单内键值对 #}
              $.each($('#myform').serializeArray(), function (index, obj) {
                  MyFormData.append(obj.name, obj.value)
              });
      
              MyFormData.append('avatar', $('#mdd')[0].files[0]);
              console.log($('#mdd')[0].files[0]);
              $.ajax({
                  url:'',
                  type:'post',
                  data:MyFormData,
                  {#  发送文件一定要指定两个参数  #}
                  processData:false,
                  contentType:false,
      
                  success:function (data) {
                      if (data.code == 1000){
                          window.location.href = data.url
                      }else{
                          // index是报错字段,obj是数组形式的报错信息
                          $.each(data.msg, function (index, obj) {
                              /* 上面for循环渲染的input框,foo.auto_id给每个input框添										加'id_fieldname'形式的id #}*/
                              let targetId = '#id_' + index;
                              {# 当输入有误时,打印错误信息并是对应的输入框变红 #}
                              $(targetId).next().text(obj[0]).parent().addClass('has-error')
      
                          })
                      }
                  
                  }
              })
          });
      

    其他

    • django是默认重启的,内有检测机制,实时检测所有文件的变化

    • form表单默认请求方式是get请求,也能携带极小量的数据而且不安全

      <a href="http://127.0.0.1:8000/login/?username=jason&password=jason123"></a>
      
    • web身份校验(cookie、session、token)

      • cookie:Cookie指的是浏览器里能永久存储的一种数据,是浏览器实现的一种数据存储功能。Cookie是由服务端生成,发送给浏览器,浏览器把Cookie以key-value的形式保存到某个目录下的文本文件内,下一次请求同一个网站的时候会把该Cookie发送给服务端。由于Cookie是存在客户端上的,所以浏览器加入了一些限制确保Cookie不会被恶意使用,同时不会占据太多的磁盘空间,每个域的Cookie的数量都是有限的
      • session:会话。Coookie中存放着一个sessionID,请求时会发送这个sessionID;session因为请求(request对象)而产生;session是一个容器,相当于一个字典,可以存放会话过程中的任何对象;session的创建与使用总是在服务端,浏览器从来没有得到过session对象;session是一种http存储机制,目的是为了武装http提供持久机制
      • token:令牌,是用户身份的验证方式。可以在token中包含足够多的信息,以便在后续请求中减少查询数据库的几率;
  • 相关阅读:
    Win7+CentOS7双系统安装
    python中的 __getattr__ __setattr__ __getitem__ __add__
    对象.函数名 叫方法 和 类.函数名 叫函数
    python中的__str__ __name__ 和__call__方法
    flask中的登录验证 装饰器版 befor_request版
    装饰器
    Django model中的 class Meta 详解
    跨域问题cors
    reids缓存
    python-django目录
  • 原文地址:https://www.cnblogs.com/shenblog/p/11918418.html
Copyright © 2011-2022 走看看