type
Post
status
Published
date
Aug 14, 2022
slug
Django-NOTE
summary
Django学习笔记
tags
Python
Django
category
学习思考
icon
password
Property
Aug 14, 2022 09:06 AM
MyDjangoDjango介绍项目结构settings.pyURLpath及相关函数视图请求和响应请求响应GET请求和POST请求GET处理Django的设计模式与模板层Template视图层与模板层之间的交互标签过滤器继承URL反向解析应用及分布路由应用分布式路由应用下的模板层模型层与ORM使用MYSQL数据库模型ORM(Object Relational Mapping)框架基础字段类型字段选项Meta类常见问题数据操作F对象和Q对象聚合查询原生数据库操作后台admin后台管理关系映射cookies和session
MyDjango
Django介绍
组件:
1.基本配置文件/路由系统
2.模型层(M)/模板层(T)/视图层(V)
3.Cookies和Session
4.分页及发邮件
5.Admin管理后台
项目结构
创建项目:
django-admin startproject 项目名称启动服务:
python manage.py runserver (端口号,默认为8000) 前台启动浏览器访问:
http://127.0.0.1:8000settings.py
settings.py包含了Django项目启动的所有配置项。
配置分为公有配置和私有配置。格式例子:BASE_DIR(必须大写)=‘XXXX’
os.path.abspath(__file__) //返回所选文件绝对路径 os.path.dirname(路径) //返回当前路径的上一级目录 DEBUG= //启动模式 1.True 调试模式(1.代码改动后立刻生效2.提供报错页面) 2.False 正式启动模式 ALLOW_HOSTS //请求头里Host头 ROOT_URLCONF //主路由 TEMPLATES //模板
URL
语法格式:
protocol:// hostname[:port]/path[?query][#fragment]处理URL请求:
1.从配置文件中根据ROOT_URLCONF找到主路由文件。
2.加载主路由文件中的urlpatterns变量
urlpatterns=[ path('路径',视图函数), ....... ]
path及相关函数
path(route,views,name=None)
route:字符串类型,匹配请求的路径。 views:指定路径对应试图函数的名称,不能在后面加上括号。 name:为地址起别名,在反向解析中起作用。
转换器 语法:<转换器类型:自定义名称> (转换器类型:str,int,slug,path) 例子:
from django.urls import path from .import views path('page/int:pg',views.xxx) def xxx(request,pg): html="这是一个编号为%s的网页"%(pg) return HttpResponse(html)
re_path(reg,view,name) reg参数可以使用正则表达式,必须使用命名分组模式(?Ppattern)
视图
创建名为views的py文件。
视图函数:
from django.http import HttpResponse def XXX_view(request[,其他参数...]): return HttpResponse(对象)
URLS里需要
from . import views3.依次匹配urlpatterns中的path,匹配第一个成功匹配的内容
4.匹配成功,调用对应的视图函数处理请求
5.匹配失败,返回404
请求和响应
请求
方法:GET,HEAD,POST,PUT,DELETE,CONNECT,OPTIONS,TRACE
请求在Django中实则就是视图函数中的第一个参数,即HtttpRequest对象。
HttpRequest属性和方法:path_info:URL字符串 //request.path_info get_full_path:完整路径,包含数据 method:字符串,表示Http请求方法。 //request.method GET:QueryDict类字典,包含get请求方式的所有数据 //request.GET POST:QuertDict类字典,包含post请求方式的所有数据 //request.POST FILES:上传文件信息 //request.FILES ......
响应
HttpResponse(content=响应体,content_type=响应体数据类型,status=状态码)
GET请求和POST请求
无论是什么请求,二者都是通过视图函数接收请求,通过request.method方法区分动作。
GET处理
一般用于向服务器请求数据。
产生GET请求场景: 1.浏览器输入URL,回车后。 2.
<a herf="地址?参数=值&参数=值">,超链接 3.form表单中的method为get如果有数据需要传递给服务器,通常用Quer String请求传递。 URL格式:xxx?参数名1=值1&参数名2=值2… 相当于讲传递的数据放在URL中 服务器端接受数据:
request.GET['参数名'] request.GET.get('参数名','默认值') request.GET.getlist('参数名')
###POST处理
一般用于向服务器提交大量/隐私数据。 客户端通过表单等POST请求将数据传递给服务器。
服务器端接受参数。 通过request.method判断是否为POST请求。 取消settings.py中MIDDLEWARE的CSRF验证,否则Django会拒绝客户端发来的POST请求。
Django的设计模式与模板层
Django的MTV模式
M模型层Model 负责与数据库交互
T模板层Template 负责呈现内容到浏览器,即HTML。根据视图传递的数据生成HTML文件。
Template
1.创建文件夹<项目名>/templates
2.在settings.py中TEMPLATES配置项 需要修改的部分:DIRS模板的搜索目录 os.path.join(BASE_DIR,‘templates’)
3.加载模板
//方案1 from django.template import loader t=loader.get_template("模板文件名") //加载模板 html=t.render(字典数据) //将t转换成html字符 return HttpResponse(html) //返回 //方案2 from django.shortcuts import render return render(request,'模板文件名',字典数据)
视图层与模板层之间的交互
1.视图函数将python变量封装到字典中传递到模板
def xxx_view(request): dic={ "变量1":"值1", "变量2":"值2", ...... } return render(reuqest,xxx.html,dic)
2.模板中,我们通过{{变量名}}使用视图传递的参数
能传递到模板层中的数据类型(放在dic中)
str,int,list,tuple,dict,func,obj 使用变量的方法{{变量名/变量名.index/变量名.key/对象.方法/函数名}}标签
将服务端的一些功能嵌入到模板中。
{% 标签 %} ... {% 结束标签 %}
if标签
{% if %} ...{% elif %}...{% else %}...{% endif %} 可以使用常规运算符。 但是不能使用括号标注优先级。for标签
{% for 变量 in 可迭代对象%} ...{% empty %}可迭代对象无数据时的填充语句... {% endfor %} 内置变量forloop过滤器
在变量输出时对变量的值进行处理。 语法:{{变量|过滤器1:‘参数1’|过滤器2:‘参数2’…}} 常用过滤器:
lower/upper大小写 safe:不对字符串进行html转义 add:'n'将value的值加n truncatechars:'n'超出指定长度则截断字符串
继承
使父模板复用,子模板直接继承父模板的全部内容并可以覆盖父模板中相应的块标签中(block)。
父模板:定义block块标签,标识出子模板中哪一些块是被允许修改的。
子模版:重写父模板内容
{% extends "xxx.html" %} ... {% block block_name %} 子模版覆盖父模板内容 {% endblock block_name %}
V视图层View 核心,负责接受请求,获取数据,返回结果
URL反向解析
URL书写规范
1.绝对地址
如:
http://127.0.0.1:8000/page/12.相对地址
'/page/1' ’/’开头的地址,浏览器会把当前地址栏协议+ip+端口+该地址当作最终访问的地址'page/1' 没有’/‘开头的相对地址,浏览器根据当前url的最后一个’/’之前的内容加上该相对地址作为访问的地址反向解析
用path定义的名称来动态查找或计算出相应的路由
path(route,views,name="别名") //在模板使用 {% url '别名' %} {% url '别名' ('参数名':)'参数1'('参数名':) '参数2' %} //在视图使用 from django.urls import reverse reverse('别名',args=[],kwargs={})
##静态文件
静态文件配置 settings.py中
1.配置静态文件的访问路径
STATIC_URL='/static/'指定访问静态文件是通过/static/xxx
2.配置静态文件的存储路径STATICFILES_DIRS
STATICFILES_DIRS=( os.path.join(BASE_DIR,"static"),//指名静态文件的存储路径 )
模板中访问静态文件
//方案1 直接拼接访问路径 <image src="xxx"> //方案2 通过标签访问静态文件 {% load static %} <image src="{% static '静态资源路径' %}">
应用及分布路由
应用
1.创建应用:
python manage.py startapp 应用名称 创建应用文件夹2.在settings.py的INSTALLED_APPS列表中配置安装此应用
INSTALLED_APPS=[ '应用名称', //对应应用模块 ...]
分布式路由
主路配置文件不处理用户具体路由,而做请求的分发。
1.主路由中调用include函数
from django.urls import include urlpatterns=[... path('路径/',include('应用名称.urls')) ]
2.应用下配置urls.py
手动创建urls.py文件,文件结构同主路由相同
urlpatterns=[ ... //只管主路由已经匹配的路由的后半部分]
应用下的模板层
1.手动创建templates文件夹
2.settings.py 将TEMPLATE配置项中的’APP_DIR’的值改为True
当应用下templates和外层templates都存在时,优先查找外城templates下的模板,按INSTALLED_APPS配置下的应用按顺序查找。
模型层与ORM
使用MYSQL数据库
1.创建数据库
输入
mysql -u root -p 进入mysql数据库,执行create database 数据库名 default charset urf82.修改settings.py里数据库的配置,修改DATABASES配置项目
DATABASES={ 'default':{ 'ENGINE':'django.db.backgends.mysql', 'NAME':'数据库名', 'USER':'root', 'PASSWORD':'', 'HOST':'127.0.0.1', 'PORT':'3306' } }
模型
模型是一个类,由
django.db.models.Model派生出来的子类。一个模型类代表一个数据库中的一张数据表(TABLE)。
每个类属性代表数据库中的一个字段。
模型是数据交互的接口。
ORM(Object Relational Mapping)框架
即对象关系映射,可以通过类和对象操纵数据库,不用通过SQL语句进行。
1.创建应用,并且在settings.py中注册
2.在创建的应用中的models.py中创建对应的类
from django.db import models class 模型类名(models.Model): 字段名=models.字段类型(字段选项)
3.数据库迁移,即同步对模型所做的修改。
生成迁移文件:
python manage.py makemigrations 将models.py生成一个中间文件,并保存在migrations中。执行迁移脚本程序:
python manage.py migrate将中间文件移动回数据库。基础字段类型
BooleanField()//数据库类型:tinyint(1) 编程中:True or False 数据库中:1 or 0 CharField()//数据库类型:varchar 必须指定max_length参数值 DateField()//数据库类型:date 参数:auto_now(T/F) auto_now_add(T/F) default('xxx') 参数三选一 DateTimeField()//数据库类型:datetime(6) 参数同上 FloatField()数据库类型:double DecimalField()//数据库类型:decimal(x,y) max_digits:位数总数 decaimal_places:小数点后面的数字数量 EmailField()//数据库类型:varchar 字符串 会有正则检查 IntegerField()数据库类型:int ImageField()//数据库类型:varchar(100) 保存图片的路径 TextField()//数据库类型:longtext 不定长字符数据
字段选项
primart_key //主键 如果未指定主键,数据库将创建id字段 blank //设置为True,字段可以为空。为False时,字段不能为空 admin后台控制 null //如果为True,则列值允许为空,如果为False,建议加入default设置默认值 default //默认值 db_index // 如果为True则为该列增加索引 unique //如果为True,则表示该字段在数据库中的值必须唯一 db_column //指定列的名称,如果不指定则采用属性名作为列名 verbose_name //设置此字段在admin界面上的显示名称
Meta类
给模型赋予属性。
from django.db from models class 模型类名(models.Model): xxx class Meta: db_table='xxx'//改表名 verbose_name='单数名'//admin后台显示的名称 verbose_name_pural='复数名'//admin后台显示的名称
常见问题
执行
python manage.py makemigrations出现迁移错误You are trying to add a non-nullable field ‘des’ to book without a default;we can’t do that (the database needs something to populate existing rows).
Please select a fix
1)Provide a one-off default now (will be set on all existing rows with a null value for this column)
2)Quit,and let me add a default in models.py
Select an option:
选择1会进入交互页面,提交默认值,但是并不会在代码中体现
选择2会推出,去代码添加默认值
迁移文件混乱。
数据库中django_migratioms表记录了migrate的全过程,项目中各应用的migrate文件应与之对应,否则migrate会报错。
解决方案:
1)删除所有migrations里所有的
000?_XXXX.py(_init_.py)除外2)删除数据库
drop database mywebdb,重现创建数据库,然后再重新迁移。数据操作
操作 :CRUD 即Create,Read,Update,Delete
核心:模型类.管理器对象
每个继承自models.Model的模型类,都会有一个objects对象被继承下来,这个对象叫管理器对象。
增删改查通过该对象操作。
Django提供了一个Django Shell,它能够在交互模式中项目工程的代码执行相应的操作。
启动
python manage.py shell 项目发生变化时,重新进入Shellfrom xxx.models import xxx //使用模型类,需要引入...
//创建数据 //方案1 类名.objections.create(属性1=值1,属性2=值2...)//成功:返回创建好的实体对象 失败:抛出异常 //方案2 obj=类名(属性1=值1,属性2=值2) obj.属性=值 obj.save() //创建实例对象,并调用save()保存
//查询操作 //管理器对象查询方法 all()//查询全部记录,返回QuerySet容器查询对象,存放模型类实例,当作数组使用。等同select* from table values('列1','列2')//返回值内部格式{'列1':值1,'列2':'值2'} 。等同select 列1,列2 from table values_list('列1','列2')//基本同上,返回值内部存放元组 orde_by('-列','列')//排序,默认升序排序,加上'-'改为降序 QuerySet.query//得到产生对应QuerySet的对应SQL语句 get() //查询符合条件的单一记录,多余或者没有都会出错。返回的单一对象。 filter(属性1=值1,属性2=值2)//查询符合条件的多条记录 exlude(属性1=值1,属性2=值2)//查询符合条件之外的全部记录 //查询谓词 __exact//等值匹配 __contains//包含指定值 __startswith//以XXX开始 __endswith//以XXX结束 __gt//大于 __gte//大于等于 __lt//小于 __lte//小于等于 __in//查找数据是否在指定范围内 __range//查找数据是否在指定区间内 //可以在模型类中定义_str_方法,自定义QuerySet的输出格式 def _str_(self): return '% % %'%(self.xxx,self.xxxx,self.xx)
//更新操作 //单个数据更新,1查2改3保存 get(), obj.属性 obj.save() //批量数据更新,调用QuerySet的update实现批量修改 obj=模型类名.objects.filter(条件) obj.update(条件)
//错误 try: xxx except Exception as e: print('xxx%s'%(e)) return HttpResponse("xxxxx")
//删除操作 //单个数据删除 try: obj=模型类名.objects.get(条件) obj.delete() except: print("删除失败") //批量删除 obj=模型类名.objects.filter(条件) obj.delete() //伪删除 is_active=models.Booleanfield('是否活跃',default=True) is_active=False
F对象和Q对象
//F对象 一个F对象用于代表数据库中某条记录的字段 //可以在不获取的情况下进行操作,实现PV操作 from django.db.models import F F('列名')
//Q对象 //实现逻辑或|和逻辑非~操作 与操作& from django.db.models import Q filter(条件1|~条件2)
聚合查询
//对一个数据表中的一个字段的数据进行部分或全部的统计查询 //整表聚合 from django.db.models import 聚合函数 //聚合函数 Sum,Avg,Count,Max,Min 模型类名.objects.aggregate(结果变量名=聚合函数('列')) //返回{"结果变量名":值} //分组聚合 obj=模型类名.objects.values('列1','列2') obj.annotate(结果变量名=聚合函数('列'))//返回QuertSet
原生数据库操作
模型类名.objects.raw(sql语句,拼接参数)//返回RawQuerySet集合对象,只支持基础操作,比如循环
小心SQL注入
//cursor from django.db import connection with connection.cursor() as cur: cur.execute('执行sql语句','拼接参数')
后台
admin后台管理
django提供了写好的比较完善的后台管理数据库接口。
django会搜集所有已经注册的模型类,提供数据管理界面。
创建后台管理账号:
python manage.py createsuperuser进入
127.0.0.1:8000/admin…
//在后台管理页面管理自己的模型类,需要注册到后台管理页面 //1.在应用中的admin.py导入注册要管理的模型类 from .models import 模型类名 //2.调用admin.site.register注册 admin.site.register(模型类名)
//模型管理类,为后台界面添加便于操作的新功能 //必须继承自django.contrib.admin里的Modeladmin //1.在应用/admin.py里定义模型管理器类 class xxxManger(admin.ModelAdmin) list_display=[...]//列名称 list_display_links=[...]//超链接,从list_display里选择一列进入修改页 list_filter=[...]//过滤器 search_field=[...]//搜索框,模糊查询 list_editable=[...]//可在列表页编辑的字段 //2.绑定注册模型管理器和模型类 from django.contrib import admin from .models import* admin.site.register(模型类,模型管理器类)
关系映射
常见的映射:一对一,一对多,多对多。
//一对一映射 class A(model.Model): ... class B(model.Model): 属性=models.OneToOneField(A,on_delete=xxx)//外键 on_delete级联删除动作 //models.CASCADE级联删除 //models.PROTECT阻止删除 //SET_NULL设置外键为NULL,需要指定null=True //SET_DEFAULT 将外键设置为默认值,必须设置外键的默认值 //创建数据 关联外键 属性名=关联obj//方案1 外键=值//方案2 //查询 //正向查询 通过外键属性查询 A.外键=B //反向查询 没有外键属性的那一方,调用反向属性查询到关联的另一方 B.引用类名(小写)
//一对多映射 //在多表上设置外键 关联一表 class A(model.Model): ... class B(model.Model): 属性=models.ForeignKey('一'的模型类,on_delete=xx) //创建数据 //先创建一 再创建多 防范基本同一对一 //查询 //正向查询 方法同上 //反向查询 引用类名(小写)_set
//多对多映射 //需要依赖第三章表 属性=models.ManyToManyField(模型类名) //创建数据 //例子 //方案1 先创建author再关联book author1=Author.objects.create(name='A') author2=Author.objects.create(name='B')//A和B两个人同写一本书 book11=author1.book_set.create(title='Python') author2.book_set.add(book11) //方案2 先创建book再关联author book=Book.objects.create(title='Python') author3=book.authors.create(name='C') book.authors.add(author10)//A和C都参见了书的创作 //查询 //正向查询 //反向查询 用反向属性
cookies和session
会话
定义:从打开浏览器到关闭浏览器结束成为一次会话。
而cookies和session都是为了保持会话状态而诞生的存储技术
cookies
在浏览器中都是以键值对形式存储的,以ASCII字符存储。
存储数据有生命周期。
数据按域名存储隔离的,不同域名之间无法访问。
内部的数据每次访问此网址时都会携带到服务器端,如果过大会降低响应速度。
HttpResponse.set_cookie(key,value='',max_age=None,expires=None) //key:cookie的名字 //value:cookie的值 //max_age:cookie存活时间,s //expires:具体过期时间 //当不指9定存活过期时间时,关闭浏览器时此数据失效 //在views.py下 def xxx(reuqest): a=HttpResponse('xxxxx') a.set_cookie('','',) return a //删除 HttpResponse.delete_cookie(key) //获取 request.COOKIES//当作字典 request.COOKIES.get('cookies名称','默认值')
登录流程(cookie存本地方案)
1.登录页面登录
2.登陆后,浏览器自动把当前域名下的cookie都发到服务器。
3.服务器进行数据库验证,如果验证成功,set cookie
4.服务器端将cookie交由浏览器保存
5.之后的再次访问,浏览器将cookie传给服务器端,服务器端验证cookie
session
即状态数据存储在服务器上。
在服务器创建对应存储空间后,将sessionID传回浏览器。
浏览器得到sessionID后,存放在cookie里。
//开启配置 //1.在Settings.py中向INSTALLED_APPS添加配置 'django.contrib.sessions' //2.向MIDDLEWARE田间 'django.contrib.sessions.middleware.SessionMiddleware' //使用 对象是类似字典的SessionStore类型 //保存值到服务器 request.session['KEY']=value //取获取值 request.session['KEY'] request.session['KEY','默认值'] //删除 del request.session['KEY']
//cookie SESSION_COOKIE_AGE //指定sessionID在cookies中保存时间,默认为两周 SESSION_EXPIRE_AT_BROWSER_CLOSE=True//关闭浏览器时,session失效
问题:
单表设计。
通过
python manage.py clearsessions清楚过期数据
P1-P30
——2022/7/25夜
