• Django 语法笔记


    Django 语法

    创建项目框架

    django-admin startproject 项目名

    创建子app

    • 业务分化,可以优化团队合作,可以明确找锅

    • python manage.py startapp 子app名

    启动项目

    • python manage.py runserver

    项目目录结构

    • __init__.py: 声明当前文件夹为一个可导入的包

    • settings.py: 整个项目的配置文件

    • urls.py: 主控路由映射文件

    • wsgi.py: 项目上线时使用的uwsgi服务器的连接文件

    • manage.py: 控制管理当前项目

    子app目录结构

    • admin.py: django内置了一个数据库管理工具

    • models.py: 数据库,模型类

    • views.py: 存储不同

    配置settings.py


    • 语言 转中文
      LANGUAGE_CODE = 'zh-Hans'

    • 定义时区
      TIME_ZONE = 'Asia/Shanghai'

    • 配置模板 在TEMPLATES列表字典中配置DIRS 并手动创建template文件夹
      TEMPLATES = [
        {
      'DIRS': [os.path.join(BASE_DIR,'template')],
        }]

    • 谁可以访问我
      ALLOWED_HOSTS = ["*"]

    • 配置图片 手动创建static文件夹
      STATICFILES_DIRS=(
        os.path.join(BASE_DIR,'static'),
      )

    • 在INSTALLED_APPS中加入子app 否则无法创建数据库模板类
      INSTALLED_APPS = [
      '子app名',
      ]

    ORM映射

    • 在models.py中创建模板类


      class Student(models.Model):
        # 学生名字
        name = models.CharField(max_length=30,verbose_name='学生名字') # 字符串 最大30字符
        # 年龄
        age = models.IntegerField(default=0,verbose_name='年龄') # 数字类型 默认为 0岁
    • 在admin.py中注册模板类


      from . import models
      admin.site.register(models.Student)
    • 为自己的app创建表


      1. python manage.py migrate 框架Django有自带的数据表 生成相关数据表
      2. python manage.py makemigrations 查找差异 创建迁移文件
      3. python manage.py migrate 根据迁移文件 生成数据表及字段

    admin界面

    • Django所提供用来帮助你管理项目所使用到的数据表的

      *注意: 访问之前先创建 框架Django有自带的数据表 也就是 python manage.py migrate

      否则会保Django-session的错

    • 为admin界面创建超级用户 管理所有app:


    python3 manage.py createsuperuser
    • 用来为数据表具体某一个数据提供一个可读性更高的名字


    #提供一个可读性更高的名字
    def __str__(self):
       return self.name

    Django-Hello

    返回一个html页面

    • 在template中创建一个xxx.html模板文件

    • 在views.py写相关视图函数,连通一个xxx.html模板

    • 在urls.py里配置相关path路径

    html模板语法

    模板变量,模板标签

    ·为模板页面返回模板变量
       - {{ var }}  来自views.py的 var 变量

    ·编写视图函数:
    - app -> views.py -> def(request)
       - 视图函数操作模型类表
           * 让视图函数返回所有学生
           * content = models.Student.objects.all()
           * return render(request,'xxx.html',locals())
    ·编写映射关系: 路由映射关系是通过path函数找到对应视图
       - 路由映射,必须写末尾的斜杠
       - 路由查找,从上到下,匹配的到某一个,直接调用视图函数即可
       - 404:页面没找到 403:服务器拒绝 402:保留位 401:用户权限鉴定失败 400:错误的请求
    ·返回模板页面 == HTML页面
       - 配置模板页面的路径,设置一个路径在settings文件下,保存所有的静态目录,TEMPLATES
       - 视图函数使用render进行页面渲染并返回
    ·模板标签:
       - 必须要有闭合标签
       - 如:{% for i in 迭代对象 %} {% endfor %}  

    静态资源:


    #·css,js,mp3,audio -----》 路径查找: 绝对、相对
    #- settings.py   ->    
       STATICFILES_DIRS=(os.path.join(BASE_DIR,'static'),)

    #·在html中上方全局加载
    - {% load static %}

    让视图函数从数据库里拿数据

    • 有一个数据库:sqlite3 学习使用的轻量级数据库文件

    • 创建表:吧表创建在对应的app下-> models.py

    • python manage.py makemigrations 查找当前数据库差异,迁移文件

    • python manage.py migrate 通过迁移文件执行真正的SQL

    获取用户表单

    • 用户的提交数据方式:get,post request.method == 'GET' or 'POST'

    • 明确防跨站请求伪造令牌

      —— {% csrf_token %}

    视图函数判断请求方式 post

    • request.POST.get(‘表单的name值’) -> 表单-> value

    • 存储数据 models.Student.create(字段=value等等)

    • request.method # 判断当前用户访问方式

      • request.method == 'GET'

      • request.method == 'POST'

    • request.POST:获取POST形式提交的数据

        • 获取表单多值时候,不能使用get函数

        • 我们需要使用getlist 获取多个值

        • 解析到的数据类型为:application/x-www-form-urlencoded,form-data

    • 视图函数判断请求方式 get

      • request.GET:获取GET形式提交的数据

        • get形式提交的数据

      • 获取ip: request.META:访问的头部信息

        • REMOTE_ADDR:获取访问者的IP地址


        • if 'HTTP_X_FORWARDED' in request.META:
             ip = request.META.get('HTTP_X_FORWARDED')
          else:
          ip = request.META['REMOTE_ADDR']
          #查询数据库ip是否已存在
          models.Students.objects.get(ip=IP)
      • 获取文件类型

        • request.FILES

      静态路由


      #例:
      path('路由字符串/', views.index)
      path('abc/', views.index)

      动态路由

      将参数做到连接里

      • 路由命名传参:


        • path('index/<str:name>/<int:age>/', views.index),

        • re_path(r'^index/(?P<name>[a-z]{3})/(?P<age>\d{1,2})/',views.index ),

        • (?P<id>\w+)/
      • 路由非命名传参:更灵活,但是必须对应参数位置


        • re_path(r'^index/([a-z]{3})/(\d{1,2})/',views.index)
      • 空白符号:\r \n \v \t \b

      路由分发

      • 路由分发特性与优点:

        • APP:业务分化,方便团队合作

        • 主路由文件:只做分发


        • from django.urls import path,re_path,include
          urlpatterns = [
             path('admin/', admin.site.urls),
             re_path('',include('xue_app.urls'))
          ]
        • 子路由文件:需要我们手动创建相关app的urls.py,实现视图映射


        • from django.urls import path
          #导入子app的视图文件
          from xue_app import views
          #配置子app路由 结尾加 /
          urlpatterns = [
             path('', views.index),
             path('show/', views.show),
          ]
        • 主路由-》子路由-》分发

      路由命名

      路由命名特性与优点

      当路由修改时,如果HTML页面跳转与视图函数重定向使用的是原始的连接内容,那么都需要更改

      耦合性太强

      现在通过路由反向解析,可以解决这个问题

      • path('', views, name=)

      • html:


        • href={% url 'url_name' 'args1' 'args2'... %}
      • views:


        • from django.shortcuts import render,redirect,reverse
          redirect(reverse('url_name',args=('args1','args2')))

      命名空间

      • 在路由文件:子路由

        • app_name 全局变量,一般使用app名作为命名空间名


        • href={% url 'app_name:url_name' 'args1' 'args2'... %}

        • from django.shortcuts import render,redirect,reverse
          redirect(reverse('app_name:url_name',args=('args1','args2')))
      • 用户的提交数据方式:get,post request.method == 'GET' or 'POST'

      • 明确防跨站请求伪造令牌 {% csrf_token %}

      • 视图函数判断请求方式 POST

      • request.POST.get() -> 表单 -> value值

      • 存储数据 models.Student.create(字段=value等等)

      模板过滤器

      • {{ var|add:1 }}

        • add:过滤器名字

        • 参数:var、1

      • 模板过滤器最多只能接收两个参数,必须要有一个参数:1~2

      自定义过滤器

      创建自定义过滤器流程

      1. 将当前app注册到settings->INSTALL_APPS

      2. 在app目录下创建templatetags文件夹,用来保存所有的过滤器文件

      3. 在templatetags文件夹下创建一个__init__.py文件,声明当前文件夹为一个可导入的包

      4. 在templatetags文件夹下创建一个你的.py文件,用来保存对应的过滤器函数

      5. 导入from django.template import Library

      6. 需要在这个文件下有一个全局变量名为:register = Library()

      7. 编写过滤器函数

      8. 注册函数为真正过滤器

        1. @register.filter(name='your_func')

      9. 模板页面要想使用自定义过滤器,首先导入过滤器文件:{% load youfilter %}

      10. {{ var|your_func}}

      自定义标签

      • 与自定义过滤器一个文件夹下即可

      • @register.simple_tag(name='')

      模板继承

      1. 首先在模板文件夹下定义一个base.html

      2. 可以在子模版中,通过最顶部使用{% extends 'base.html' %}引入过来

      3. 在base.html的父模板页面中可以使用{% block title %}{% endblock %}指明块

      4. 父模板中没有的块,在子模版中强行加入,是不会被渲染出来的

      思考:解决了什么问题?HTML代码编写时,更精简,复用性更高

      模板组件

      1. 使用{% include %} 标签将额外编写的组件HTML代码加载进来

      2. 可以实现HTML代码的复用,解耦和

      3. 节约代码量,使HTML干净整洁

    Django - mysql数据库

    配置settings.py文件

    # 找到DATABASES
    DATABASES = {
       'default': {
           'ENGINE': 'django.db.backends.sqlite3',
           'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
      }
    }
    # 注掉上面 变更为
    DATABASES = {
       'default': {
       'ENGINE': 'django.db.backends.mysql', # 数据库引擎
       'NAME': "django_data", # 使用的数据库库名,该库需要手动创建
       "USER": "root", # 自己的用户名
       "PASSWORD": "chenkai", # 自己的数据库密码
       "HOST": "172.16.19.49", # 数据库主机地址 自己的本地ip
       "PORT": "3306"  # mysql的端口号
      }
    }

    主机“CK”不允许连接到此MySQL服务器的问题

    • 使用wins系统可能会遇到一个问题:

    解决方法:

    进入MySQL的bin目录,执行如下命令:

    #登录mysql
    mysql -u 用户名 -p密码
    # 进入mysql配置
    user mysql;
    # 变更配置
    update user set host = '%' where user = 'root';
    # 给出 特权 Ps:让他可以这么做
    flush privileges;

    关系

    一对一关联反向查询

    查询:

    • 表层面:

      • 查询所有是教授的老师 英雄为母表 ADC为子表

      • 子表 有一个继承母表市局的字段(正向查询),同样母表也有一个隐藏的小写子表表名字段用来查询子表的数据(反向查询)

      • 母表.objects.filter(小写子表名__子表特有字段__gt=0) ------》 反向查询

      • 用的是隐藏起来哪个关联表字段进行查询 就是反向查询

      • 子表名.继承母表字段名 ---》 正向

    • 数据层面

      • m1 = 子表.objects.get() ---》反向m1.继承母表的变量字段 ----》 正向

      • 小写子表名 不是一条m1的字段,他是django做出来隐藏的


      • #英雄 --》 ADC(为子表)
        #增
        a1 = models.Hero.objects.create(name='黄忠')
        a2 = models.Skill.objects.create(kill=a1,skill='百步穿杨')
        #查
        b1 = models.Hero.objects.get(name='黄忠')
        b2 = models.Skill.objects.get(kill=b1)
        #改
        b2.skill='一箭狙神'
        b2.save()
        #删
        b2.delete()

    多对一查询

    • 关系Foreigkey建立在多的一方

      • 例:关系:老师学生

    • 数据层面

      • 老师结果.student_set.all() -----》 反向

      • _set == models.objects

      • 根据外键 查询 ---》 正向

    • 表层面:

      • Teacher.objects.filter(student__name__startswith='贾') ---》 反向

      • Student.objects.filter(tea__name='贾老师') ---》 正向

    • 修改

      • 单独修改简单:直接字段赋值,save() 即可

      • 批量修改

      • 结果集.update(tea=要变更的值) 直接为这些set数据 批量修改

      • 直接立竿见影到数据库,不需要save

    • 删除:

      • on_delete =

      • models.CASCADE:老师删除,球员也跟着消失,外键绑定

      • models.SET_NULL:老师删除,球员外键为null,数据还在,外键关系消失

      • null=True

      • blank=True

    shell

    • 开启一个包含当前项目所有环境的命令行工具命令: python manage.py shell

    • 例:终端在manage.py 同级目录下:python manage.py shell

    • 表关系 学生 ---》 老师

    添加


    from s_app import models
    a1 = models.Teacher.objects.create(name='李老师')
    a2 = models.Teacher.objects.create(name='贾老师')
    a1
    <Teacher: 李老师>
    a2
    <Teacher: 贾老师>
    q1 = models.Student.objects.create(tea=a1,name='张小宁')
    q2 = models.Student.objects.create(tea=a1,name='贾小璇')
    q3 = models.Student.objects.create(tea=a2,name='李小括')
    q4 = models.Student.objects.create(tea=a2,name='潘小飞')
    q1
    <Student: 张小宁>
    q2
    <Student: 贾小璇>
    q3
    <Student: 李小括>
    q4
    <Student: 潘小飞>
    q1.tea.name
    '李老师'

    查:

    • 查看贾老师班里都有谁


    c1 = models.Student.objects.filter(tea__name='贾老师')
    c1
    <QuerySet [<Student: 李小括>, <Student: 潘小飞>]>
    • 产看潘小飞是哪个老师教的


    c2 = models.Teacher.objects.filter(student__name='潘小飞')
    c2
    <QuerySet [<Teacher: 贾老师>]>

    改:


    # 把潘小飞调给李老师教
    q4.tea.name = '李老师'
    q4.save()
    q4.tea.name
    '李老师'
    把所有同学调给贾老师教
    l = models.Student.objects.filter(tea=a1)
    j = models.Student.objects.filter(tea=a2)
    l.update(tea=a2)

    • 结果集.直接delete()


     #删除张小宁
    q1.delete()
     #批量删除贾老师所有学生(将一个数据集直接删除)
    j.delete()

    多对多

    • 多对多关系在模型中使用 ManyToManyField 字段定义

    修改/外键关系操作

    • ​ 数据保留,外键关系消失,删除和添加只影响外键关系

    指定或批量 添加外键关系

    • add -----》 例: 子表结果.关联字段.add(某结果集[0],某结果集[3],某结果集[6],)

    指定或批量 删除外键关系

    • remove -----》 例: 子表结果.关联字段.remove(某结果集[0],某结果集[3],某结果集[6],)

    彻底删除

    • 结果/结果集.delete()

    查询

    • 数据层面 :针对某些特定字段数据进行查询 ---> (反向查询:关联表_set)

      • 正向

        • 子表结果.关联字段.all()

      • 反向

        • 母表结果.隐藏小写子表名字段__set.all()

    • 表层面 : 针对的是整张表的数据 ---> (反向查询:直接使用小写关联表名)

      • 正向

        • 子表.objects.filter(关联字段__子表某字段=‘一个指定结果’)

      • 反向

        • 母表.objects.filter(隐藏的小写子表名__子表某字段=‘一个指定结果’

     

    cookie 和 session

    COOKIE:

    • 什么是cookie?

      • 类似令牌一样的东西,用来把每次客户端访问服务端的数据信息提交给我

      • request 获取

      • response 设置

      • 明文传输,极度不安全

      • 默认有效期:随客户端关闭而消失

    Django对于Cookie的处理方式

    每个HttpRequest对象都对应一个COOKIES对象,该对象是字典形式.

    request.COOKIES['session变量名']  # 获取

    对COOKIES的设置通过一个页面HttpResponse对象的set_cookie


    HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)
    #语法: 页面.set_cookie('session变量名',session的值)   # 设置 session值


    delete_cookie['session变量名']

    防止篡改COOKIE

    • 通过 set_signed_cookie 函数进行持有签名的 COOKIE 值设置,避免用户在客户端进行修改

    • 要记得,这个函数并不是对 COOKIE 值进行加密


    HttpResonse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/',
    domain=None, secure=None, httponly=True)
    • 为 cookie 值添加签名,其余参数与 set_cookie 相同


    Request.get_signed_cookie(key, salt='', max_age=None)
    • 从用户请求中获取通过salt盐值加了签名的 Cookie 值。 这里的 salt 要与之前存储时使用的 salt 值相同才可以解析出正确结果。 还要注意的是,如果对应的key值不存在,则会引发KeyError异常,所以要记得异常捕获来确定是否含 有 Cookie 值


      def check_salt_cookie(request):    try:        salt_cookie = request.get_signed_cookie(key='salt_cookie',salt='nice')    except KeyError: #获取不到该key值的Cookie        response = HttpResponse('正在设置一个salt Cookie值')        response.set_signed_cookie(key='salt_cookie',salt='nice',value='salt_cookie')        return response    else: #获取到了对应key值,展示到新的HttpResonse中        return HttpResponse('获取到的salt Cookie值:%s' % salt_cookie)

      ​ 第一次访问的时候,还没有加 Cookie 值,所以我们在获取的时候会抛出 KeyError 异常

      ​ 此时捕获异常,并且设置 Cookie 即可;

      ​ 再次刷新的时候,因为这里已经给出了 Cookie 值,则不会引发异常,会在页面中展示获取到的加盐 cookie

    session

    • ​ 什么是session?

      • session是基于cookie的,在网络中,又称会话控制,简称会话。用以存储用户访问站点时所需的信息及配置属性。当用户在我 们的 Web 服务中跳转时,存储在 Session 中的数据不会丢失,可以一直在整个会话过程中存活。

      • django中,默认的 Session 存储在数据库中session表里。默认有效期为两个星期

      • 加密传输 更安全

      • 客户端访问服务端,服务端为每一个客户端返回一个唯一的 sessionid ,比如 xxx 。

      • 客户端需要保持某些状态,比如维持登陆。那么服务端会构造一个 {sessionid: xxx } 类似这样的字典数据加 到 Cookie 中发送给用户。注意此时,只是一个随机字符串,返回给客户端的内容并不会像之前一样包含实际数 据。

      • 服务端在后台把返回给客户端的 xxx 字符串作为 key 值,对应需要保存的服务端数据为一个新的字典,存储在 服务器上,例如: {xxx : {id:1}}

    获取Session

    session_data = request.session.get(Key)session_data = request.session[Key]

    获取Session

    ession_data = request.session.get(Key)session_data = request.session[Key]

    删除Session

    del request.seesion[Key]

    • 删除对应session, Key 值不存在时,引发 KeyError

    request.session.clear()

    • 清空 Session 中的所有数据。这里客户端还会保留 sessionid 只不过在服务端 sessionid 对应的数据没有了。

    request.session.flush()

    INSTALLED_APPS = ( ...    'django.contrib.sessions',   ... )

    • MIDDLEWARE_CLASSES = (    'django.contrib.sessions.middleware.SessionMiddleware', ... )

    • 直接删除当前客户端的的Seesion数据。这里不光服务端sessionid对应的数据没有了,客户端的 sessionid也会被删除

  • 相关阅读:
    虚拟目录
    【C/C++学习】之十四、RTTI
    【C/C++学习】之十五、内存管理
    【C/C++学习】之十六、关于空指针NULL、野指针、通用指针
    统计在线人数
    [置顶] 分步实现具有分页功能的自定义DataList控件【附源代码】
    进制转换
    栈和队列2 数据结构和算法24
    二进制跟十六进制
    进制转换
  • 原文地址:https://www.cnblogs.com/canhun/p/10964089.html
Copyright © 2020-2023  润新知