Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。
使用 Django,只要很少的代码,Python 的程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的 Web 服务 Django 本身基于 MVC 模型,即 Model(模型)+ View(视图)+ Controller(控制器)设计模式,MVC 模式使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。
MVC 优势:
Python 加 Django 是快速开发、设计、部署网站的最佳组合。
MVC 模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
MVC 以一种插件式的、松耦合的方式连接在一起。
简易图:
用户操作流程图:
Django 的 MTV 模式本质上和 MVC 是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django 的 MTV 分别是指:
除了以上三层之外,还需要一个 URL 分发器,它的作用是将一个个 URL 的页面请求分发给不同的 View 处理,View 再调用相应的 Model 和 Template,MTV 的响应模式如下所示:
简易图:
用户操作流程图:
解析:
用户通过浏览器向我们的服务器发起一个请求(request),这个请求会去访问视图函数:
视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。
django-admin startproject 项目名称
使用 Pycharm 创建项目
file ---> new project ---- 选择Django ---> 配置路径和项目名称 ---> 配置环境(默认用系统环境) ----> 点击create(完成创建)
项目目录介绍
|---mysite # 项目的/目录
|---mysite # 项目目录
|---__init__.py
|---settings.py # 配置文件
|---urls.py # 路由系统 ===> url与视图的对应关系
|---wsgi.py # runserver命令就使用wsgiref模块做简单的web server
|---manage.py # 管理文件
创建应用
使用命令行模式创建应用
在 Terminal 中输入 python manage.py startapp 应用名:
使用 Pycharm 创建应用
注意:使用命令行创建的应用,一定要在 settings.py–>INSTALLED_APPS 中加入你的应用名字进行注册, 使用Pycharm创建的应用则不用。 认识应用结构
运行项目
使用命令行运行项目:
python3 manage.py runserver
manage.py runserver 80 # 指定端口
注意:要在 manage.py 同级目录执行命令。
Pycharm 启动项目
点击右上角的绿色的三角按钮。
如需更改配置信息,请下拉选择 edit configurations,进行配置。
配置完以上信息之后,直接按 Ctrl+shift+F10 运行一下 manage.py 文件。
出现如下结果,表示配置成功。
django-admin startproject + 项目名称
python3 manage.py runserver (+端口号/default:8000) python3 manage.py runserver 0.0.0.0:8000
在终端crtl+c sudo lsof -i:8000 ->kill -9ubuntu
python manage.py startapp
python3 manage.py
python manage.py makemigrations
python manage.py migrate
python manage.py shell
python manage.py createsuperuser
python manage.py clearsessions
pip freeze > requirements.txt
python manage.py createcachetable
manage.py 包含项目管理的子命令 项目同名文件夹 init:python包的初始化文件 wsgi.py:WEB网关的配置文件,正式启动django时才需要用到 urls.py:项目主路由配置-HTTP请求进入Django,有限调用 settings.py:项目的配置文件-包含项目启动需要的配置。
项目的绝对路径
BASE_DIR = Path(file).resolve().parent.parent
启动模式: True调试模式:
False正式启动模式、上线模式
DEBUG = True
请求Host头,只处理请求头在在列表中的请求,过滤一些请求,debug = 1在调试模式下默认接收127.0.0.1和localhost两个值。 局域网内部访问时需要把局域网IP加上,一旦不为空就必须都配置上
ALLOWED_HOSTS = []
主路由文件位置:
ROOT_URLCONF = ‘hworld.urls’
语言配置:
LANGUAGE_CODE = ‘en-us’(zh-Hans)
时区:
TIME_ZONE = ‘UTC’(Asia/Shanghai)
统一资源定位符(Uniform Resource Locator)
protocal(协议)://hostname(主机)[:port(端口)]/path(路由)[?query(查询字符串)][#fragment(锚点)]
Django如何处理URL? 1.从配置文件中根据ROOT_URLCONF找到主路由文件,默认urls.py 2.加载urlpatterns变量[包含很多数组的路由] 3.依次匹配urlspatterns的path,匹配到第一个合适的中断后续匹配 4.匹配成功-返回响应 5.匹配失败-返回404
用于接收浏览器请求并通过HttpResponse对象返回响应的函数。此函数可以接收浏览器请求并根据业务逻辑返回相应的响应内容给浏览器。 语法:
def xxx_view(request[,其他参数…]):
return HttpResponse对象
书写位置:项目同名文件夹下/views.py
from django.http import HttpResponse
def page1_view(request):
html = '<h1>这是一个页面</h1>'
return HttpResponse(html)
path函数 from django.urls import path path(route,views,name = None)
path转化器
path转换器 <转换器类型:自定义名> 作用:若转换器类型匹配到对应类型的数据,则将数据按照关键字传参的方式传递给视图函数
path(‘page/int:page‘,views.xxx)
转换器:
re_path函数: 正则匹配,更加精密的匹配规则 re_path(reg,view,name = xx) 正则表达式为命名分组模式(?Ppattern);
1.请求:浏览器通过HTTP协议发送给服务器端的数据 2.响应:服务器端接收到请求后做相应的处理后再回复给浏览器端的数据。
起始行:方法、路由、协议
headers:请求头 K:V
请求体(body):可能为空
Django中的请求: 实际就是视图函数的第一个参数,及HttpRequest对象 个人理解就是Django预先将请求转变为了对象,将请求内容转变为对象属性。说到底是对报文进行了预处理。
起始行(协议版本 状态码)
响应头(K:V)
响应体body
响应状态码:
分类:
Django的响应对象
HttpResponse(content = 响应体,content_type = 响应体数据类型default:html,status = 状态码,default:200) 作用:向客户端浏览器返回响应,同时携带响应体内容。
常用Content_Type
统一由视图函数接收,因此一定是需要隔离业务逻辑
if request.method == 'GET':
处理GET业务逻辑
elif request.method =='POST':
处理POST的业务逻辑
else:
其他业务逻辑
````
**GET处理:**
一般用于向服务器获取数据。
能够产生GET请求的场景:
+ 浏览器地址栏输入URL并回车
+ <a href = "地址?参数=值&参数=值"\>
+ form表单中的method为get
GET请求方法中,如果有数据需要传递给服务器,通常会使用查询字符串传递。【注意不要传递敏感数据】
URL:http://127.0.0.1:8000/page1\?a=100&b=200
服务器端接收参数
获取客户端请求GET请求提交的数据:
```python
request.GET['参数名']
request.GET.get('参数名','默认值')
request.GET.getlist('参数名')
如果有传递多个值,则参数对应的应该是一个列表,需要使用getlist方法取出所有值,get方法只能取出最后一个值。 应用场景:问卷调查的复选框
POST处理 一般用于向服务器提交大量/隐私数据 通过表单
<form method = 'post' action = '/login'>
姓名:<input type = 'text' name = 'username'>
<input type = 'submit' value = '登录'>
</form>
本身是django的防御措施,防御CSRF攻击问题,会阻止POST,暂时关闭: settings.py》注释django.middleware.csrf.CsrfViewMiddleware
传统的MVC Mode-View-Controller(模型-视图-控制器)模式。 特点:低耦合
Django:MTV模式 把MVC的V拆成了两层,并且弱化C层为路由文件。
模板:根据字典数据动态变化的html网页,根据视图中传递的字典数据动态生成相应的html页面 模板配置:
模板加载方案1:
from django.template import loader
1.通过loader加载模板
t = loader.get_template("模板文件名")
2.将t转化为HTML字符串
html = t.render(字典数据)
3.用响应对象将转换的字符串内容返回给浏览器
return HttpResponse(html)
模板加载方案2: 使用render直接加载并且响应模板。 在视图函数中
from django.shortcuts import render
return render(request,'模板文件名',字典数据)
视图层与模板层之间的交互
def xxx_view(request):
dic = {
k1: v1,
k2: v2
}
return render(request, 'xxx.html', dic)
能传递到模板中的变量类型:str,int,list,tuple,dict,func,obj
在模板中使用变量的语法:
作用:将一些服务器端的功能嵌入到模板中,例如流程控制等
语法
{% 标签 %}
…
{% 结束标签 %}
例: if标签
{% if 条件表达式 1 %}
…
{% elif 条件表达式 2 %}
…
{% elif 条件表达式 3 %}
…
{% else %}
…
{% endif %}#!!一定记住要封口
NOTICE!在模板中使用实际括号是无效的语法,如果需要指示优先级,则应该选择嵌套if
for标签 语法
{% for 变量 in 可迭代对象 %}
…循环语句
{% empty %}
…可迭代对象无数据时填充语句
{% endfor %}
内置变量forloop forloop.counter:循环的当前迭代(从1开始索引) forloop.counter0:循环的当前迭代(从0开始索引) forloop.revcounter:counter倒序 forloop.revcounter0:counter0倒序 forloop.first:第一次循环为真‘ forloop.last:最后一次循环为真 forloop.parentloop:外层循环
过滤器:在变量输出时对变量的值进行处理 可以通过使用过滤器来改变变量的输出显示
语法:
{{变量|过滤器1:'参数1'|过滤器2:'参数值2'…}}
常用过滤器:
模板继承使父模板内容重用,子模板直接继承父模板的全部内容并可以覆盖父模板中相应的块。
语法——父模板中:
语法——子模板中:
继承模板extends标签(写在模板第一行) 例如
{%extend 'base.html'}
子模板 复写父模板中的内容块
{block block_name}
{% endblock blockname %}
重写的覆盖规则
代码中url的位置: 1.模板
2.视图函数中 - 302跳转 HttpResponseRedirect(‘url’) 将用户地址栏中的地址跳转到url
代码中的url书写规范
url反向解析 指在视图或模板中,用path定义的别名来动态查找或计算出相应的路由。 path:
模板中:
{% url '别名'%}
{% url '别名' '参数值1' '参数值2'%}
视图函数中 调用reverse方法进行方向解析
from django.urls import reverse
reverse('别名', args=[], kwargs={})
ex: print(reverse(‘pagen’,args=[300])) print(reverse(‘person’,kwargs={‘name’:’xixi’,’age’:18}))
什么是静态文件:图片、css、js、音频、视频 静态文件属于静态请求,不经过视图函数 静态文件配置-settings.py
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
3.方案2通过
{% static %}
标签访问静态文件
1.加载static-
{% load static %}
2.使用静态资源-
{% static'静态资源路径' %}
3.样例:
<img src="{% static 'images/lena.jpg' %}">
每一个应用都是一个MTV 创建应用
python manage.py startapp music
执行创建应用后,应用文件夹下
Django中,主路由配置文件可以不处理用户具体路由,主路由配置文件的可以做请求的分发(分布式请求处理)。具体的请求可以由各自的应用来进行处理。 主路由匹配前缀,如/news/,再往下分发到子路由配置。 配置分布式路由:
http://127.0.0.1:8000/music/index -> path('music/',include('music.urls'))
应用内部可以配置模板目录
TEMPLATE配置项中的’APP_DIRS’值为True即可、
important:查找模板的顺序:外层templates文件夹->注册顺序的app内部的templates文件夹 解决方法:在应用层的templates下创建嵌套同名子目录,从而在views.py render中使得html获得不一样的路径
模型层:负责与数据库之间进行通信 Django配置mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mysite3',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'POST': '3306'
}
什么是模型:
ORM(对象关系映射),是一种程序技术,能够使用类和对象对数据库进行操作,从而避免通过SQL语句操作数据库。
作用
优点:
缺点:
映射图: ORM———->DB 类———->数据表 对象——–>数据行 属性——–>字段
数据库迁移: 迁移是Django同步您对模型所做出的更改(添加字段,删除模型等)到您的数据库模式的方式。
python manage.py makemigrations 生成一个中间文件,并保存在migrations文件夹中
python manage.py migrate 执行迁移程序实现迁移,将每个应用下的migrations目录中的中间文件同步回数据库。
模型类-创建
from django.db import models
class 模型类名(models.Model):
字段名 = models.字段类型(字段选项)
表名实际为 APP名称+类名称小写
创建列的额外信息
好习惯:字段选项【添加或更改】均要执行
使用Meta类来给**模型(其实就是表的属性)**赋予属性,Meta类下有很多内建的类属性,可对模型类做一些控制。 如改表名:
from django.db import models
class 模型类名(models.Model):
字段名 = models.字段类型(字段选项)
class Meta:
db_table = 'book'
#控制模型类在admin后台显示的名称
verbose_name = '单数名'
#指定复数形态
verbose_name_plural = '复数名'
Django对于数据库操作是惰性的,尽量不对数据库进行积极的修改,如设置的default值将不参与表的字段生成,只会参与实际插值。
增删改查 ORM CRUD核心:模型类.管理器对象
管理器对象 每一个models.Model的模型类,都会有一个objects对象被同样继承下来,这个对象叫做管理器对象。 数据库的增删改查可以通过管理器实现。
创建数据 方案1:
成功:返回创建好的实体对象 失败:抛出异常
方案2:
obj = Mymodel(属性 = 值,属性 = 值)
obj.属性 = 值
obj.save()
需要使用Django Shell
python manage.py shell 代码每次变化,都需要重启Django Shell
通过管理器对象进行 通过MyModel.objects管理器方法调用查询方法 方法
<QuerySet [<Book: Python,20.00>, <Book: jango,50.00>, <Book: JQuery,40.00>, <Book: Linux,30.00>, <Book: HTML5,26.00>]>
可以在模型类中定义__str__方法,自定义QuerySet中的输出格式,则输出时能输出格式化字符串。
Django 同样支持方法的串联,以下方法在返回QuerySet后均可使用方法串联,且最终都会按照SQL顺序对数据库进行操作。
print(QuerySet.query)将取得实际的SQL语句。
<QuerySet [{'title': 'HTML5'}, {'title': 'jango'}, {'title': 'JQuery'}, {'title': 'Linux'}, {'title': 'Python'}]>
<QuerySet [('HTML5',), ('jango',), ('JQuery',), ('Linux',), ('Python',)]>
<QuerySet [<Book: jango,50.00>, <Book: JQuery,40.00>, <Book: Linux,30.00>, <Book: HTML5,26.00>, <Book: Python,20.00>]>
类属性 + ‘__’ + 谓词 定义:做更灵活的条件查询时需要使用查询谓词 说明:每一个查询谓词都是一个独立的查询功能
Author.objects.filter(id_exact=1) <=> SELECT * FROM Author WHERE ID=1
Author.objects.filter(name__contains=’w’) SELECT * FROM Author WHERE name Like ‘%w%’
Author.objects.filter(name__in=[‘中国’,’美国’])
Author.objects.filter(age__range(35,50)) <==> SELECT * FROM Author WHERE age BETWEEN 35 AND 50
1.针对单个数据的修改 查(get())->改:通过对象.属性的方式更改->保存:对象.save() 2.批量更新数据 直接调用QuerySet的update(属性=值实现批量修改) 针对QuerySet来做更改
1.单个数据删除
2.批量数据删除
3.伪删除操作 通过在表里添加一个布尔型字段(is_active),默认是True;执行删除时,将欲删除数据的is_active置为False。 注意:使用伪删除时,确保显示数据的地方,均添加了is_active=True的过滤查询。
F对象(很适合用于点赞) ········································· **F对象实际等价于语句: UPDATE TABLE SET COLUMN=TABLE.VALUE+10 使用单句的数据库查询语句,Mysql的InnoDB引擎使用行锁,因此F对象的本质是使用了数据库中的锁。 ** ·········································
from django.db.models import F
该需求原本只能通过循环取出每一个数据后+10再写入实现。
Query的update方法必须结合F对象方法实现 使用F语句
Book.objects.all().update(market_price=F('market_price')+10)
用于类属性之间的比较:
Book.objects.filter(market_price_gt=F('price')+10)
用于进行逻辑或、逻辑非操作时使用
Book.objects.filter(Q(market_price_lt=35)|Q(price_gt=40))
Q对象能够实现互相间的&与,|或,非,&与非等操作。
聚合查询是指对一个表中的一个字段的数据进行部分或全部进行统计查询。 分为整表聚合和分组聚合。
from django.db.models import *
语法:
MyModel.objects.aggregate(结果变量名(别名)=聚合函数('列'))
返回:字典
QuerySet.annotate(结果变量名(别名)=聚合函数('列'))
返回:QuerySet
1.只用来查询:MyoModel.objects.raw(sql语句,拼接参数)
返回值:RawQuerySet集合对象,不支持方法串联,只支持基本的循环等。
SQL注入问题: 使用原生语句,使用拼接参数的方式进行查询能适当避免SQL注入问题。
2.完全跨过模型类操作数据库
from django.db import connection
with connection.cursor() as cur:
cur.execute('执行SQL语句','拼接参数')
admin后台用于开发过程中调用和调试,django会搜集所有已注册的模型类,并为这些模型类提供数据管理界面。
python manage.py createsuperuser
显示样式是按照models.py中__str__方法显示的。
作用:为后台管理界面添加便于操作的新功能 继承于django.contrib.admin里的ModelAdmin类
class XXXXManager(admin.ModelAdmin):
……
类属性:
class XXXXManager(admin.ModelAdmin):
#表头
list_display = ['id','title','price']
#控制list_display哪些字段超链接进修改页
list_display_links = ['title']
#添加过滤器
list_filter = ['id']
#添加搜索框(模糊查询)
search_fields = ['title']
#添加可在列表页可编辑的字段,与
#list_display_links字段是互斥的
list_editable = ['price']
关系映射:一对一,一对多,多对多。
创建一对一外键: 语法:OneToOneField(类名, on_delete=xxx(级联删除:在存在键的前提下的删除规则)) on_delete:
创建一对一数据 无外键的模型类,和之前相同 有外键的模型类:
wife = Wife.objects.create(name=’王夫人’,author = author1(类属性名称绑实例)) wife = Wife.objects.create(name=’王夫人’,author_id = 1(类属性字段绑值))
一对一查询
核心:正向属性(authors)和反向属性(book_set) 在多表上设置外键,关联一表。
创建一对多数据: 语法:Foreignkey(“一”的模型类, on_delete=xxx(级联删除:在存在键的前提下的删除规则))
添加数据: 先添加“一”,再添加“多”。 无外键的模型类,和之前相同 有外键的模型类: 类似上面
wife = Wife.objects.create(name=’王夫人’,author = author1(类属性名称绑实例)) wife = Wife.objects.create(name=’王夫人’,author_id = 1(类属性字段绑值))
查询数据: 正向查询(有显性属性的):由book查出版社:book.publisher 反向查询(使用反向属性):
books = pub1.book_set.all() 或books = Book.objects.filter(publisher=pub1)
核心:正向属性(authors)和反向属性(book_set) mysql中多对多需要用三张表实现 Django中无需手动创建第三张表,Django自动完成
创建字段语法:属性 = models.ManyToManyField(MyModel)
创建数据:
author1 = Author.objects.create(name=’1’) author2 = Author.objects.create(name=’2’) book1 = author1.book_set.create(title = ‘1’)#创建 author2.book_set.add(book1)#绑定
book = Book.objects.create(title=’p1’) author3 = book.authors.create(name=”3”) book.authors.add(author1)
从打开浏览器访问一个网站,到关闭浏览器结束此次访问,称之为一次会话。 HTTP本身是无状态的,导致会话状态难以保持。
保存在客户端浏览器上的存储空间 特点:
存储 HttpResponse.set_cookie(key,value=’’,max_age=None,expires=None) -key:cookie的名字 -value:cookie的值 -max_age:存活相对时间,秒 -expires:具体过期时间 当不指定max_age和expires时,关闭浏览器时此数据失效。
删除&获取 获取:request.COOKIES 删除:request.delete_cookie(key)
会话保持-登录流程 用户登录->账号密码传至后端,服务器数据库验证,正确则发放cookie->后续浏览器将自动把当前域下的cookie都发送至服务器。但浏览器存储不是十分安全,因此引入了session。
session技术实际将数据存在了服务器里,对于不同的浏览器有不同的存储空间,生成空间后,会将一个sessionID返还给浏览器,浏览器会将sessionID存储在Cookies,之后每次返还给服务器。
session是在服务器上开辟一段空间用于保留浏览器和服务器交互时的重要数据。
session初始配置:
session的使用: session对象是一个类似于字典的SessionStore类型的对象。
干预session时间:settings.py里的SESSION_COOKIE_AGE指定cookies中的保存时间,默认两周 SESSION_EXPIRE_AT_BROWSER_CLOSE = True,关闭浏览器自动清除session,默认False SESSION的数据在Django中保存在数据库中,因此需要保证已经执行过了migrate
Django session的问题:
定义:缓存是一类可以更快的读取数据的介质统称,也指其他可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存。 意义:视图渲染有一定成本,数据库的频繁查询过高;所以对于低频变动的页面可以考虑使用缓存技术,减少实际渲染次数;用户拿到响应的时间成本会更低。 场景:1.博客列表页;2.电商商品详情页 场景特点:数据变动频率较少
配置方法:
CACHES={
'default': {
'BACKEND':'django.core.cache.backends.db.DatabaseCache',#引擎
'LOCATION':'my_cache_table',#指定用于缓存的表
'TIMEOUT':300,#缓存时间
'OPTIONS':{
'MAX_ENTRIES':300,#最大存储条数
'CULL_FREQUENCY':2,#缓存条数达到最大值时,删除1/x的数据
}
}
}
CACHES={
default: {
'BACKEND':'django.core.cache.backends.locmem.LocMemCache',#引擎
'LOCATION':'unique-snowflake',#雪花算法内存寻址
}
}
CACHES={
default: {
'BACKEND':'django.core.cache.backends.filebased.FileBasedCache',#引擎
'LOCATION':'/var/tmp/django_cache',#存储路径
# win'c:\test\cache'
}
}
from django.views.decorators.cache import cache_page
@cache_page(30)# 单位秒
def my_view(request):
from django.views.decorators.cache import cache_page
urlpatterns = [
path('foo/',cache_page(60)(my_view)),
]
使用简单粗暴,但是无法控制。
相较于整体缓存更加灵活,复用性更好。 缓存api的使用:
from django.core.caches import caches
cache1 = caches['myalias']
cache2 = caches['myalias_2']
直接调用CACHE中的default值。相当于1中的
cache = caches['default']
from django.core.caches import cache
缓存api:
不会向服务器发送请求,直接从缓存中读取资源
强缓存的对象是一些静态文件、大图片等,考虑到这类资源比较费带宽且不易变化,强缓存到期后,浏览器会根服务器进行协商,当前缓存是否可用,如果可用,服务器不必返回数据,浏览器继续使用原来缓存的数据,如果文件不可用,则返回最新数据。
上述的两个头仅通过精确到秒的时间来判断缓存是否有效,不是特别精准,后来HTTP又引入了新的缓存头:
继承django.utils.deprecation.MiddlewareMixin类 中间件类须实现下列五个方法中的一个或多个:
中间件中的大部分方法返回None则表示进入下一项时间,返回HttpResponse则被拦截。
中间件的执行顺序 先由上到下,在进入视图后变为由下至上
利用Cookies自动提交功能,同时利用了form表单及一些html控件的跨域提交。
django的防御机制:页面和COOKIE都有一个暗号,只有两个暗号同时发送到服务器并且能够匹配,才允许POST。 配置步骤:
保证django.middleware.csrf.CsrfViewMiddleware打开
模板中,form标签下添加如下标签:
{% csrf_token %}
当个别视图不需要django进行csrf保护可以用装饰器关闭对此视图的检查
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def my_view(request):
return …
分页指在web页面有大量数据需要显示,为了阅读方便在每个页中只显示部分数据。
优点:
Django提供了Paginator类可以方便的实现分页功能 Paginator类位于’django.core.paginator’模块中
负责分页数据整体的管理
pagenator = Paginator(object_list,per_page)
Paginator对象属性
Paginator方法 paginator对象.page(number) -参数number为页码信息(从1开始) -返回当前number页对应的页信息 -如果提供的页码不存在,抛出InvalidPage异常,包含两种异常子类-PageNotInteger页码不是整数和-EmptyPage页码超页
Paginator对象的page()方法返回Page对象 page = paginator.page(页码)
page对象属性:
Page对象方法:
python提供了内建库 -csv;可直接通过该库操作csv文件。 案例:
import csv
with open('eggs.csv','w', newline='') as csvfile:# newline指文件输出时换行符怎么处理,空字符串将不会转义
writer = csv.writer(csvfile)
writer.writerow(['a','b','c'])
在网站中实现下载csv,注意如下:
import csv
from django.http import HttpResponse
from .models import Book
def make_csv_view(request):
response = HttpResponse(content_type = 'text/csv')
response['Content-Disposition'] = 'attachment;filename = "mybook.csv"'
all_book = Book.objects.all()
writer = csv.writer(response)
writer.writerow(['id','title'])
for b in all_book:
writer.writerow([b.id,b.title])
return response
模型类位置 from django.contrib.auth.models import User (mysql中auth_user表) 字段(属性):
命令:
from django.contrib.auth.models import User
user = User.objects.create_user(username="用户名",password="密码",email="邮箱",…)
from django.contrib.auth import authenticate
user = authenticate(username=username, password=password)
如果用户名密码校验成功则返回用户对象,否则返回None
from django.contrib.auth import login
def login_view(request):
user = authenticate(username=username, password=password)
login(request,user)
from django.contrib.auth.decorators import login_required
@login_required
def index_view(request):
login_user = request.user#直接能拿到usert对象
from django.contrib.auth import logout
def logout_view(request):
logout(request)
内建用户表-扩展字段 方案1:通过建立细腻哦啊,和内建表做1对1映射 方案2:继承抽象user模型类 方案2步骤:
!!注意:此操作需要在第一次migrate之前进行!!
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(Abstractuser):
phone = models.CharField(max_length = 11, default = '')
在settings.py里面添加配置: AUTH_USER_MODEL = ‘user.UserInfo’
添加用户 from user.models import UserInfo
UserInfo.objects.create_user(username=……,phone=’’)
定义:用户可以通过浏览器将图片等文件传至网站 场景:
上传必须为POST提交方式 表单’<\form>’中文件上传时必须有带有enctype=’multipart/form-data’时才会包含文件内容数据。 表单中用<input type = ‘files’ name=’xxx’>标签上传文件
视图函数中,需要用request.FILES取文件框的内容 file=request.FILES[‘xxx’] 说明:
配置文件的访问路径和存储路径 在settings.py中设置MEDIA相关配置,Django将用户上传的文件统称为media资源
MEDIA_URL='/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
同时MEDIA_URL和MEDIA_ROOT还需要手动绑定:在主路由添加:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
等价于做了MEDIA_URL开头的路由,Django接到该特征请求后去MEDIA_ROOT路径查找资源
文件写入:
# 在视图函数POST中
a_file = request.FILES['myfile']
fileadd = os.path.join(settings.MEDIA_ROOT,afile.name)
with open(filename,'wb') as f:
data = afile.file.read()
f.write(data)
return HttpResponse
Content.objects.create(desc = title, content = a_file)
该方法若文件名重复则django将自动添加后缀
业务场景:
IMAP VS POP3:
Django中配置邮件功能,主要为SMTP协议,负责发邮件 原理:
授权:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'# 引擎:写死
EMAIL_HOST = 'smtp.qq.com'# 腾讯qq邮箱的SMTP服务器地址
EMAIL_PORT = 25# 默认25
EMAIL_HOST_USER = 'xxxx@qq.com'
EMAIL_HOST_PASSWORD = '*******'# 指的是授权码
EMAIL_USE_TLS = False # 与SMTP服务器通讯时,是否启动TLS连接(安全链接)默认为False,安全协议比较耗时
发送:
from django.core import mail
mail.send_mail(
subject,
message,
from_email,# 发送邮箱
recipient_list = ['xxx@qq.com'],# 接受者邮箱列表
)
返回1则成功发送
通过中间件可以捕获所有视图函数的异常,并发送到指定邮箱 process_exception(self,request,exception) 定位错误位置:异常追溯
import traceback
traceback.format_exc()# 直接获得错误具体位置及出错信息
邮箱里可以直接发送traceback.format_exc()
自定义收件人: 在settings里自定义属性,在调用send_mail位置
from django.conf import settings
recipient_list = settings.自定义属性
在软件开发完毕后,将开发机器上运行的软件实际安装到服务器上进行长期运行
WSGI:Web Server Gateway Interface,Web服务器网关接口,是Pyhton应用程序或框架和Web服务器之间的一种接口。 uWSGI:WSGI的一种,实现了http协议、WSGI协议、uwsgi协议等多种协议。在python web圈热度极高,主要以学习配置为主。
uWSGI安装 pip命令可以安装 [ubuntu验证安装]:sudo pip3 freeze|grep -i ‘uwsgi’ [ubuntu安装]:sudo pip3 install uwsgi==2.0.18 -i https://pypi.tuna.tsinghua.edu.cn/simple/
配置uWSGI:
如mysite1/mysite1/uwsgi.ini 文件以[uwsgi]开头,有如下配置项: