Django 语法笔记

摘要:
存储不同的配置设置。将语言转换为中文语言_ CODE='zh-Hans'定义时区time_zone='亚洲/上海配置模板在TEMPLATES列表字典中配置DIRS,并手动创建模板文件夹TEMPLATES=[{'DIRS':
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也会被删除

免责声明:文章转载自《Django 语法笔记》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇DRF的序列化组件为redis分配一个新的端口下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Matconvet的学习笔记

首先是自己的实践总结后面是转载的别人的内容: 在配置Matconvet时首先要配置MATLAB的编译器,此时你就要查看你的MATLAB的版本支持的编译器有哪些;两个相匹配后,再把msvc120opts.bat文件拷到C:Program FilesMATLABR2014ainwin64mexopts下这样你在MATLAB命令窗口中使用mex -setup c...

网络编程【二】socket(套接字)初识

socket(套接字)  基于tcp协议的socket tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端 server端 import socket sk = socket.socket() sk.bind(('127.0.0.1',8898)) #把地址绑定到套接字 sk.listen() #监听链接 conn...

python--集合-set

1 1 # 集合-set 2 2 # 集合是高中的要给概念 3 3 # 一堆确定的无序的唯一的数据, 集合中的每一个数据成为一个元素 4 4 5 5 # 集合的定义 6 6 s = set() 7 7 print(type(s)) 8 8 print(s) 9 9 10 10 # 此时大括号中一定要有...

websocket之四:WebSocket 的鉴权授权方案

引子 WebSocket 是个好东西,为我们提供了便捷且实时的通讯能力。然而,对于 WebSocket 客户端的鉴权,协议的 RFC 是这么说的: This protocol doesn’t prescribe any particular way that servers canauthenticate clients during the WebSoc...

QString内部仍采用UTF-16存储数据且不会改变(一共10种不同情况下的编码)

出处:https://blog.qt.io/cn/2012/05/16/source-code-must-be-utf-8-and-qstring-wants-it/ 但是注意,这只是QT运行(RunTime)过程中采用的编码,并不代表源码文件里也是这样的。恰恰相反,源码文件必须是UTF8,带不带BOM都可以。我认为,虽然存储在源代码里的中文字是UTF8,...

Phalcon下命令行应用(command line applications)

今天打算在phalcon项目下加入一个定时任务,来发送邮件。 看了官网的例子,配置和运行都少许杂乱,还有个bug,见备注, 我这边主要讲解如何将command line 的配置独立出来,如果初上手的同学,建议先运行官网第一个例子,成功后,再实践一下官网第二个例子,出现报错,就看我备注,然后再看我这如何将配置独立处理。 借鉴思想:主要借鉴Yii框架中,类似功...