Django框架
核心 orm : 对象关系映射
Django 文档
1 Django框架简介与环境搭建
1-1 MVC
- MVC 施乐公司
Model模型 View视图 Controller控制器 - MVT 遵循 MVC 分工的思想
Model模型 View视图(接收数据) Template模版
1-2 简介
1-3 虚拟环境的创建和使用
cd /usr/local/lib
sudo pip3 install 包名
包安装路径:/usr/local/lib/python3.*/dist-packages
安装同一个包的不同版本,后安装的包会把原来安装的包覆盖掉。这样,如同一台机器上两个项目依赖于相同包的不同版本,则会导致一些项目运行失败。
解决方案就是:虚拟环境。
虚拟环境是真实 python 环境的复制版本。
在虚拟环境中使用的 python 是复制的python,安装 python 包也是安装在复制的 python 中。
安装虚拟环境的命令:
1)sudo pip install virtualenv
2) sudo pip install virtualenvwrapper
3) 编辑家目录下面的.bashrc,添加下面两行
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
4) 使用 source .bashrc 使其生效一下
创建虚拟环境命令:
mkvirtualenv 虚拟环境名称
创建python3虚拟环境:
mkvirtualenv -p python3 bj18_py3
进入虚拟环境:
workon bj18_py3
退出虚拟环境:
deactivate
显示虚拟环境列表:
workon 两个Tab
删除虚拟环境:
rmvirtualenv 虚拟环境的名称
虚拟环境中预装包查看:
pip list
pip freeze
pip install django==1.8.2
注意:在虚拟环境中不要使用 sudo
mac python3安装virtualenv出现的问题
mac 中安装 python 虚拟环境
mac python3安装virtualenv出现的问题
pip3 install virtualenv
pip3 install virtualenvwrapper
安装成功后可能 找不到该命令, 解决办法
1.在 vim ~/.bashrc
export WORKON_HOME=$HOME/.virtualenvs # 这个貌似是存放虚拟环境的位置,可自己设置
export VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3 # 指定python解释器
source /Library/Frameworks/Python.framework/Versions/3.6/bin/virtualenvwrapper.sh # 启动virtualenvwrapper配置,
该配置位置可通过 sudo find / -name 'virtualenvwrapper.sh'查找
2.加载.bashrc配置
source ~/.bashrc
3.执行命令 mkvirtualenv 如果出现以下错误,是因为通过python3安装的virtualenv路径会变化吧?
ERROR: virtualenvwrapper could not find virtualenv in your path
解决办法:软链接 同样通过sudo find / -name 'virtualenv'可查找到路径
sudo ln -s /Library/Frameworks/Python.framework/Versions/3.6/bin/virtualenv /usr/local/bin/virtualenv
然后就没有然后了...
重启终端后居然得重新source .bashrc气得我马上查了下解决方法
vim ~/.bash_profile 加入以下代码,可重启终端后自动加载.bashrc配置
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
1-4 项目和应用创建
- 命令:django-admin startproject 项目名字
注意:创建应用必须先进入虚拟环境
- 1.创建项目
mkdir bj18
项目目录如下:
.
|-- manage.py
|-- test1
|-- __init__.py
|-- setting.py
|-- urls.py
|-- wsgi.py
manage.py : 项目的管理文件
__init__.py : 说明 test1 是一个 python 包
setting.py:项目的配置文件
urls.py:进行 url 路由的配置
wsgi.py:web服务器和 Django 交互的入口
- 2. 创建一个应用
python manage.py startapp 应用名称
应用目录如下:
.
|-- admin.py
|-- __init__.py 说明是一个 python 包
|-- migrations
| |-- __init__.py
|-- models.py 写和数据库项目的内容
|-- tests.py 写测试代码的文件
|-- views.py 接收请求,进行处理,与 M 和 T 交互,返回应答。定义处理函数,视图函数
- 3. 配置一个应用
建立应用和项目之间的联系,需要对应用进行注册。test1/settings.py
INSTALLED_APPS = (
...
...
...
...
'booktest', # 进行应用的注册
)
- 4.启动 Django自带的服务器,运行应用
python manager.py runserver
2 Django的基本使用
2-1 ORM简介
通过类喝对象就可以对数据表进行操作
设计类:模型类
ORM 另外一个作用:根据设计的类生成数据库中的表
2-2 模型_模型类设计和表生成
- test1/models.py
- 生成迁移文件: python manage.py makemigrations
- 执行迁移:python manage.py migrate (生成数据表 默认生成 sqllite3 数据库中)
- 模型类生成表的时候表名: 表名 = 应用名_模型类名小写
from django.db import models
# Create your models here.
# 图书类
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
bpub_date = models.DateField()
bread = models.IntegerField(default=0)
bcomment = models.IntegerField(default=0)
isDelete = models.BooleanField(default=False)
2-3 模型_通过模型类操作数据表
- 进入项目 shell 命令
python manage.py shell
xyhddeMac-mini-2:~ zhangwei$ workon bj18_py3
(bj18_py3) xyhddeMac-mini-2:~ zhangwei$
(bj18_py3) xyhddeMac-mini-2:bj18 zhangwei$ python manage.py shell
>>> from test1.models import BookInfo
>>> b = BookInfo()
>>> from datetime import date
>>> """插入"""
>>> b.btitle = '天龙八部'
>>> b.bpub_date = date(1990,1,1)
>>> b.save()
>>> """查询"""
>>> b2 = BookInfo.objects.get(id=1)
>>> type(b2)
>>> b2.btitle
>>> """更新"""
>>> b2.btitle = "更新-天龙八部"
>>> b2.save()
>>> """删除"""
>>> b2.delete()
2-4 模型_模型类关系和关系查询
/Users/zhangwei/Work/Study/python/bj18/test1
from django.db import models
# Create your models here.
# 图书类
class BookInfo(models.Model):
"""图书模型类"""
btitle = models.CharField(max_length=20)
bpub_date = models.DateField()
# 英雄人物类
# 关系属性: 图书类和英雄人物类之间一对多的关系
class HeroInfo(models.Model):
"""英雄人物模型类"""
hname = models.CharField(max_length=20)
hgender = models.BooleanField(default=False) # default 默认代表男,布尔类型
hcomment = models.CharField(max_length=128)# 备注
hbook = models.ForeignKey('BookInfo') # 关系属性
进入
xyhddeMac-mini-2:~ zhangwei$ workon bj18_py3
(bj18_py3) xyhddeMac-mini-2:~ zhangwei$
(bj18_py3) xyhddeMac-mini-2:bj18 zhangwei$ python manage.py shell
>>> from test1.models import BookInfo,HeroInfo
>>> b = BookInfo()
>>> from datetime import date
>>> b.btitle = '天龙八部'
>>> b.bpub_date = date(1990,1,1)
>>> b.save()
>>> h = HeroInfo()
>>> h.hname = '段誉'
>>> h.hgender = False
>>> h.hcomment = '六脉神剑'
>>> h.hbook = b
>>> h.save()
>>> h2 = HeroInfo()
>>> h2.hname = '乔峰'
>>> h2.hgender = False
>>> h2.hcomment = '降龙十八掌'
>>> h2.hbook = b
>>> h2.save()
>>> """由一查多"""
>>> b.heroinfo_set.all()
>>> """查多条"""
>>> BookInfo.objects.all()
2-5 Django后台管理
admin.py 后台管理相关的文件
开启服务 : python manage.py runserver
- 本地化
语言和时区
修改 settings.py 文件... LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' ...
- 创建管理员
命令:python manage.py createsuperuser - 注册模型类
test1/admin.py
打开服务进入后台:python manager.py runserver
http://127.0.0.1:8000/admin/
from django.contrib import admin
# Register your models here.
from test1.models import BookInfo
admin.site.register(BookInfo)
---------------------------
--- 模型类重写魔法方法 ---
> test1/models.py
# 图书类
class BookInfo(models.Model):
"""图书模型类"""
btitle = models.CharField(max_length=20)
bpub_date = models.DateField()
def __str__(self):
return self.btitle
- 自定义管理页面
自定义模型管理类 test1/admin.py
- 注意:不能写两遍
from django.contrib import admin
# Register your models here.
from test1.models import BookInfo,HeroInfo
# 自定义模型管理类
class BookInfoAdmin(admin.ModelAdmin):
'''图书管理页面模型'''
list_display = ['id','btitle','bpub_date']
class HeroInfoAdmin(admin.ModelAdmin):
'''英雄任务模型页面模型'''
list_display = ['id','hname','hcomment']
admin.site.register(BookInfo,BookInfoAdmin)
admin.site.register(HeroInfo,HeroInfoAdmin)
2-6 视图_使用
在 Django 中,通过浏览器去请求一个页面时,使用视图函数来处理这个请求的,视图函数处理后,要给浏览器返回页面内容。
test1/views.py
- 定义视图
- 进行 url 路由的配置,建立 url 地址和视图的对应关系
- http://127.0.0.1:8000/index
- 应用程序的 urls 文件:test1/urls.py
- 项目的 urls 文件: bj18/urls.py
注意:在应用中 urls 必须严格匹配开头和结尾
- 总结:
配置url时,有两种语法格式
a) url(正则表达式,视图函数名)
b) url(正则表达式,include(应用中的urls文件))
工作中在配置 url 时,首先在项目的 urls.py 文件中添加配置项时,并不写具体的 url 和 视图函数之间的对应关系,而是包含具体应用的 urls.py 文件,在应用的 urls.py 文件中写 url和视图函数的对应关系。
------
URL 匹配过程:
- 在项目的 urls.py 文件中包含具体应用的 urls.py,应用的 urls.py 文件中写 url 和 视图函数的对应关系!
- 在项目中,匹配成功后会把匹配成功的的去掉
案例
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
# 定义视图函数,HttpRequest
# http://127.0.0.1:8000/index
def index(request):
# 进行处理 M 和 T 进行交互...
return HttpResponse('烙铁,没毛病')
def index2(request):
# 进行处理 M 和 T 进行交互...
return HttpResponse('Hello python')
"""bj18 URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Add an import: from blog import urls as blog_urls
2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('test1.urls')), # 包含 test1 应用中的 urls 文件
]
from django.conf.urls import url
from test1 import views
urlpatterns = [
# 通过 url 函数设置 url 路由配置
url(r'^index',views.index), # 建立 /index 和 视图 index 之间的关系
url(r'^index2$',views.index2), # 严格匹配
]
2-7 模板_使用
模版不仅仅是一个 html 文件,可以使用变量,还可以使用编程语言的代码。
- 项目目录下创建一个 templates 文件夹, 在 settings.py 中设置一个模版目录。
settings.py
...
...
...
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
...
...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')], # 设置模版文件目录
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
- 使用模版文件
a) 加载模版文件:去模版目录下获取 html 文件的内容,得到一个模版对象。
b) 定义模版上下文:向模版中传递数据
c) 模版渲染:得到一个标准的html内容
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader
from django.template import RequestContext
def my_render(request, template_path, context_dict):
'''使用模版文件'''
# 1.使用模版文件
temp = loader.get_template(template_path)
# 2.定义模版上下文
context = RequestContext(request,context_dict)
# 3.模版渲染:产生标准的 html 内容
res_html = temp.render(context)
# 4.返回给浏览器
return HttpResponse(res_html)
# Create your views here.
# 定义视图函数,HttpRequest
# http://127.0.0.1:8000/index
def index(request):
# 进行处理 M 和 T 进行交互...
# return HttpResponse('烙铁,没毛病')
return my_render(request,'test1/index.html',{'content':'使用模版 hello world','list':list(range(1,10))})
- 模版变量
{{ content }}
- 列表
{{ list }}
- for 循环
<ul>
{% for i in list %}
{% endfor %}
{% empty %}
2-8 MVT综合案例
完成图书信息展示
'''
a. http://127.0.0.1:8001/books
b. http://127.0.0.1:8001/books/id
c.
test1/urls.py
import test1 from views
urlpatterns = [
url(r'^books$',views.show_books),
url(r'^books/(\d+)$',views.detail),
]
'''
'''
views.py
'''
from test1.models import BookInfo
def show_books(request):
'''图书信息'''
books = BookInfo.objects.all()
return my_render(request, 'test1/show_books.html', {'books':books})
def detail(request, bid):
'''图书关联的英雄信息'''
book = BookInfo.objects.get(id=bid)
heros = book.heroinfo_set.all()
return my_render(request, 'test1/detail.html', {'book':book,'heros':heros})
---
'''
templates/test1/show_books.html
<ul>
{% for book in books %}
<li><a href="">book</a></li>
{% empty %}
<li>暂无信息</li>
{% endfor %}
</ul>
'''
3 Model属性及后端配置
3-1 模型_Django配置使用mysql数据库
默认使用的是 SqlLite 数据库存储数据
pip install pymysql
- 项目/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '数据库名', # 手动创建
'USER':'用户',
'PASSWORD':'密码',
'HOST':'服务器ip',
'PORT':3306
}
}
- 应用/__init__.py
import pymysql
pymysql.install_as_MySQLdb()
3-2 复习案例_1
3-3 复习案例_重定向
两种方式:
from django.http.response import HttpResponseRedirect
from django.shortcuts import redirect, render
3-4 答疑_页面url地址的设置
注意: 新增 href 中如果不用 / 开头的话,就无法是域名为前缀,而是当前路径为前缀
3-5 模型_字段属性和选项
-
模型类属性名的限制
- 1)不能是 python 的保留关键字
- 2)不允许使用连续的下划线,这是由 django 的查询方式决定的。
- 3)定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:属性名=models.字段类型(选项)
-
字段类型:
使用时需要引入 django.db.models 包,字段类型如下:
类型 | 描述 |
---|---|
AutoField | 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性。 |
BooleanField | 布尔类型字段,值为True或False。 |
NullBooleanField | 支持Null、True、False三种值的字段。(一般不用) |
CharField(max_length=最大长度) | 字符串类型,参数max_length表示最大字符个数。 |
TextField | 大文本类型字段,一般超过4000个字符时使用。 |
IntegerField | 整数类型字段。 |
DecimalField(max_digits=…, decimal_places=…) | 十进制浮点数类型字段,参数max_digits表示总位数,decimal_places表示小数位数。(商品价格) |
FloatField | 参数同上; 2*10的几次方,精确度不如 DecimalField |
DateField([auto_now=False, auto_now_add=False])1 | 日期类型字段,其中:(1)auto_now表示每次保存对象时,自动设置该字段为当前时间,用于“最后一次修改”时间戳,默认为False; (2)auto_now_add表示对象第一次被创建时自动设置当前时间,用于创建的时间戳,默认为False。 |
TimeField | 时间类型字段,参数同DateField。 |
DateTimeField | 日期时间类型字段,参数同DateField。 |
FileField | 上传文件字段。 |
ImageField | 继承自FileField,对上传的内容进行校验,确保图片有效。 |
- 字段类型类选项
选项名称 | 选项描述 |
---|---|
default | 默认值,用于设置默认值约束。 |
primary_key | 若为True,则该字段会成为通过模型类创建的数据表的主键字段,默认值时False,一般作为AutoField的选项使用。 |
unique | 若为True,则该字段在数据表中必须有唯一值,默认为False。 |
db_index | 若为True,则在表中会为此字段创建索引,默认值时False。 |
db_column | 字段的名称,如果未指定,则使用类属性的名称作为字段名。 |
null | 若为True,表示该字段允许为空,默认值为False。 |
blank | 若为True,表示该字段允许为空白,默认值为False。 |
需要注意的是,当修改模型类后,如果添加的选项不影响表的结构,则不需要做重新的迁移操作,反之则需要。
-
需要注意的是,auto_now_add和auto_now是相互排斥的,组合使用会发生错误; ↩︎
-
需要注意的是,null是数据库中的范畴,blank是后台管理页面表单验证的范畴;
-
default 和 blank 不影响表的结构,就不需要重新迁移。
Django-model字段类型
from django.db import models#起手式
字段变量V=models.Field()#引用创建
V=models.CharField(max_length=None[, **options])#varchar
V=models.EmailField([max_length=75, **options])#varchar
V=models.URLField([verify_exists=True, max_length=200, **options]) #varchar
V=models.FileField(upload_to=None[, max_length=100, **options]) #varchar
#upload_to指定保存目录可带格式,
V=models.ImageField(upload_to=None[,height_field=None, width_field=None, max_length=100, **options])
V=models.IPAddressField([**options])#varchar
V=models.FilePathField(path=None[, match=None, recursive=False, max_length=100, **options])#varchar
V=models.SlugField([max_length=50, **options])#varchar,标签,内含索引
V=http://www.doczj.com/doc/268382ea856a561252d36fa2.html maSeparatedIntegerField(max_length=None[, **options]) #varchar
V=models.IntegerField([**options])#int
V=models.PositiveIntegerField([**options])#int 正整数
V=models.SmallIntegerField([**options])#smallint
V=models.PositiveSmallIntegerField([**options])#smallint 正整数
V=models.AutoField(**options)#int;在Django代码内是自增
V=models.DecimalField(max_digits=None, decimal_places=None[, **options]) #decimal
V=models.FloatField([**options])#real
V=models.BooleanField(**options)#boolean或bit
V=models.NullBooleanField([**options])#bit字段上可以设置上null 值
V=models.DateField([auto_now=False, auto_now_add=False, **options]) #date
#auto_now最后修改记录的日期;auto_now_add添加记录的日期
V=models.DateTimeField([auto_now=False, auto_now_add=False, **options]) #datetime
V=models.TimeField([auto_now=False, auto_now_add=False, **options]) #time
V=models.TextField([**options])#text
V=models.XMLField(schema_path=None[, **options])#text
V=models.ForeignKey(othermodel[, **options])#外键,关联其它模
型,创建关联索引
V=models.ManyToManyField(othermodel[, **options])#多对多,关联
其它模型,创建关联表
V=models.OneToOneField(othermodel[, parent_link=False, **options])
#一对一,字段关联表属性
3-6 查询_相关函数
from django.db.models import F,Q,Sum,Count,Max,Min,Avg
- 修改 mysql 的日志文件
让其产生 mysql.log,即是 mysql 的日志文件,里面记录的对 mysql 数据库的操作记录。
1)使用下面的命令打开 mysql 的配置文件,去除 68,69 行的注释,然后保存
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
快捷键:68G
general_log_file = /var/log/mysql/mysql.log
general_log = 1
2) 重启 mysql 服务,就会产生 mysql 日志文件。
sudo service mysql restart
3) 打开 MYSQL 的日志文件。
/var/log/mysql/mysql.log 是 mysql 日志文件所在的位置。
使用下面的命令实时查看 mysql 的日志文件
sudo tail -f /var/log/mysql/mysql.log
-
查询函数
通过模型类 objects 属性可以调用如下函数,实现对模型类对应的数据表的查寻。函数名 功能 返回值 说明 get 返回表中满足条件的一条且只能有一条数据。 返回值是一个模型类对象 参数中写查询条件。1)如果查到多条数据,则抛异常MultipleObjectsReturned。2)查询不到数据,则抛异常:DoesNotExist all 返回模型类对应表格中的所有数据。 返回值是QuerySet类型 查询集 filter 返回满足条件的数据。 返回值是QuerySet类型 参数写查询条件。 exclude 返回不满足条件的数据。 返回值是QuerySet类型 参数写查询条件。 order_by 对查询结果进行排序。 返回值是QuerySet类型 参数中写根据哪些字段进行排序。 条件格式:模型类属性名__条件名 = 值 1)判等 条件名:exact 例:查询编号为 1 的图书。 BookInfo.objects.get(id__exact=1/id=1) 2) 模糊查询 例:查询书名包含‘传’的图书:contains BookInfo.objects.filter(btitle__contains = ‘传’) 例:查询书名以‘部’结尾的图书:endswith 开头:startswith BookInfo.objects.filter(btitle__endswith = ‘部’) 3)空查询:isnull BookInfo.objects.filter(btitle__isnull = False) 4)范围查询:in BookInfo.objects.filter(id_in = [1,3,5]) 5) 比较查询:gt(greate than)、lt(less than)、gte、lte 4) 日期查询 __year:BookInfo.objects.filter(bpub_date__year = 1980) __month: __day: 出版日期大于 1980: BookInfo.objects.filter(bpub_date__gt = date(1980,1,1)) ----------------------------- 查询集排序: 注意:所有数据排序 .all 可以省略 BookInfo.objects.all().order_by('id') 升序 BookInfo.objects.all().order_by('-id') 降序 id > 3,阅读量降序排序 BookInfo.objects.filter(id__gt=3).order_by('-bread')
-
Q 对象
作用:用于查询时条件之间的逻辑关系,not and or, 可以对 Q 对象进行 &|~操作 from django.db.models import Q BookInfo.objects.filter(id__gt=3,bread_gt=30) 且 BookInfo.objects.filter(Q(id__gt=3)|Q(bread_gt=30)) 或
-
F 对象
作用:用于类属性之间的比较 from django.db.models import F BookInfo.objects.filter(bread__get=F('bcomment')) BookInfo.objects.filter(bread__get=F('bcomment')*2)
-
聚合函数
作用:对查询结果进行聚合操作 sum、count avg max min aggreate:调用这个函数来使用聚合。返回值是一个字典 使用前先导入聚合类 from django.db.models import Sum,Count,Max,Min,Avg BookInfo.objects.all().aggreate(Count('id')) --------- count 函数:返回值是一个数字 BookInfo.objects.all().count() BookInfo.objects.count()
3-8 查询集
- 查询集特性:
1)惰性查询:只有在实际使用查询集中的数据的时候才会发生对数据库的真正查询
2)缓存:当使用的是同一个查询集时,第一次的时候回发生实际数据库查询,然后把结果缓存起来,之后使用这个查询集时,使用缓存中的结果。 - 限制查询集
可以对一个查询集进行取下标或者切片操作来限制查询集的结果。
对一个查询集进行切片操作回产生一个新的查询集,下标不允许为负数。
取出查询集第一条数据的两种方式:
方式 | 说明 |
---|---|
b[0] | 如果b[0]不存在,会抛出 IndexError 异常 |
b[0:1].get() | 如果 b[0:1].get() 不存在,会抛出 DoesNotExist 异常 |
exists:判断一个查询是否有数据;True False
4 模型关系及相关操作
4-1 模型_模型类关系
- 一对多:models.ForeignKey()
「定义在多的类中」
- 多对多:models.ManyToManyField()
「定义在哪个类里面都可以」
- 一对一:models.OneToOneField()
「定义在哪个类里面都可以」
'''
多对多
'''
# 新闻类型类
class NewsType(models.Model):
type_name = models.CharField(max_length=20)
type_news = models.ManyToManyField('NewsInfo')
# 新闻类
class NewsInfo(models.Model):
title = models.CharField(max_length=128)
pub_date = models.DateTimeField(auto_now_add=True)
content = models.TextField()
# news_type = models.ManyToManyField(NewsType)
4-2 模型_关联查询
注意:通过模型类实现关联查询时,要查哪个表中的数据,就需要通过哪个类来查。写关联查询条件时候,如果类中没有关系属性,条件需要写对应类的名字,如果类中有关系属性,那么直接写关系属性。
-
关联查询
一对多
在一对多关系中,一对应的类我们把它叫做(一类),多对应的那个类我们把它叫做(多类),我们把多类中定义的建立关联的类属性叫做(关联属性)。
‘’‘
通过多类条件查询一类数据
‘’‘
一类名.objects.filter(多类名小写__多类属性名__条件名)
‘’‘
通过一类条件查询多类数据
‘’‘
多类名.objects.filter(关联属性__一类属性名__条件名)b = BookInfo.objects.filter(heroinfo__id__gt=3)
h = HearInfo.objects.filter(hbook__btitle=‘天龙八部’)- 由一查多
b.heroinfo_set.all() - 由多查一
h.hbook()
- 由一查多
4-3 模型_插入和删除
- 插入和更新:调用一个模型类的 save 方法
- 删除:调用一个模型对象的 delete 方法
4-4 模型_自关联
省 市 县
特殊的 一对多
id | title | a_id |
---|
class Area(models.Model):
"""
省市区三级联动
"""
name = models.CharField(max_length=20,verbose_name='名称')
parent = models.ForeignKey('self',on_delete=models.SET_NULL,related_name='subs',null=True,blank=True,verbose_name='上级行政区划'
4-5 模型_模型管理器对象
-
BookInfo.objects.all()->objects是一个什么东西呢?
答:objects 是 Django 帮我们自动生成的管理器对象,通过这个管理器可以实现数据的查询。
objects是models.Manger类的一个对象。自定义管理器之后 Django不再帮我们生成默认的 objects 管理器。- 自定义一个管理器类,这个类继承 models.Manger类。
- 再在具体的模型类里定义一个自定义管理器类的对象。
自定义管理器类的应用场景:
- ) 改变查询的结果集
- ) 添加额外的方法 self.model()
4-6 模型_模型管理器类和模型类关系
'''
一:关系
'''
模型管理器类
BookInfoManger ---继承--- models.Manger
(self.model获取self所在模型类的类名)
BookInfo.objects.create_book()
模型类
BookInfo --- 继承 --- models.Model
联系:objects = BookInfoManager()
'''
二:模型管理器类实现代码
'''
from django.db import models
# Create your models here.
class BookInfoManager(models.Manager):
"""图书模型管理器类"""
# 1. 改变查询的结果集
def all(self):
# 调用父类的all方法,获取所有数据
books = super().all() # 返回值是QuerySet查询集
# 对数据进行过滤
books = books.filter(isDelete=False)
# 返回books
return books
# 2. 封装方法,操作模型类对应的数据表(增删改查)
def create_book(self, btitle, bpub_date, bread=0, bcomment=0, isDelete=False):
# self.model获取self所在的模型类的类名
model_class = self.model
b = model_class()
b.btitle = btitle
b.bpub_date = bpub_date
b.bread = bread
b.bcomment = bcomment
b.isDelete = isDelete
# 保存进数据库
b.save()
# 返回对象
return b
'''
三:模型类实现代码
'''
class BookInfo(models.Model):
"""图书模型类"""
# 图书名称
btitle = models.CharField(max_length=20, db_column="title")
# 图书名字唯一
# btitle = models.CharField(max_length=20, unique=True, db_index=True)
# 价格, 最大位数10,小数位数2
# bprice = models.DecimalField(max_digits=10, decimal_places=2)
# 出版日期
bpub_date = models.DateField()
# auto_now_add 表示创建时间 , auto_now 表示更新时间
# bpub_date = models.DateField(auto_now_add=True)
# bpub_date = models.DateField(auto_now=True)
# 阅读量
bread = models.IntegerField(default=0)
# 评论量
bcomment = models.IntegerField(default=0)
# 删除标记
isDelete = models.BooleanField(default=False)
# 自定义一个Manager类型的对象
# book = models.Manager()
# 自定义一个BookInfoManager类的对象
objects = BookInfoManager() # 一个类的属性可以是另外一个类创建的实例对象
def __str__(self):
return self.btitle
4-7 模型_元选项
Django 默认生成的表名:
应用名小写_模型类名小写。
元选项:需要在模型中定义一个元类 Meta,在里面定义一个类属性 db_table 就可以指定表名。
- 表明对应出错的情况
class BookInfoManager(models.Manager):
class Meta:
db_table = 'bookinfo'
5 登录案例_视图
5-1 视图_url匹配的过程
- 视图的功能
接收请求,进行处理,与 M 和 T 进行交互,返回应答。
返回 html 内容 HttpResponse, 也肯呢个重定向 redirect。 - 视图函数使用
- 使用
- 1)定义视图函数:request 参数必须有,是一个 HttpRequest 类型的对象,参数名可以变化,但不要更改。
- 2)配置 url: 建立 url 和 视图函数之间的对应关系。
- url 配置的过程: 前面的域名和后面的参数都不参与匹配的过程
- 1)在项目的 urls 文件中包含具体应用的 urls 文件,在具体应用的 urls 文件中包含具体 url 和视图的对应关系。
5-2 视图_错误视图
- Page not found(404)
- django 自动调用,在 template 下自定义页面 template/404.html
{{ request_path }}
- django 自动调用,在 template 下自定义页面 template/404.html
- Server Error (500)
- 代码问题,在 template 下自定义页面 template/500.html
- 网站开发完成,需要关闭调试模式
# DEBUG = True(调试模式) DEBUG = False # (发布状态) ALLOWED_HOSTS=['*']
5-3 视图_捕获url参数
进行 url 匹配的时候,把所需要的捕获的部分设置成一个`正则表达式组`,
这样 django 框架就会自动把匹配成功后相应组的内容作为参数传递给视图函数。
- 位置参数:位置参数,参数可以随意指定
- 关键字参数: ?P<组名> ;关键字参数,视图中参数名必须和正则表达式组名一致。
参考链接:Django从 URL获取参数的几种方式
'''
url配置的根节点是 ROOT_URLCONF,这个配置是在项目的settings.py文件里,一般当你创建完项目后这个配置就自动出现在settings文件里而它的值就是项目名.urls, 知道这个配置你就可以任意修改url配置的根路径。上面这是普遍的情况,如果使用了某些中间件,那么请求HttpRequest本身可能会带有urlconf参数,这时候我们设置的urlconf就会被覆盖。
找到ROOT_URLCONF后,django加载这个模块,查找其中的变量urlpatterns,这个变量是一个list数据类型,而list里元素的类型因版本不同会有差异,django版本2.0之前使用的是django.conf.urls.url()对象,2.0及以后使用的是django.urls.path()和 django.urls.re_path(),
'''
# 在1.X时代,只有django.conf.urls.url(),形式如下:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
'''
----------------
这种类型的urlpattern都是使用正则表达式匹配的,如果需要获取参数,可以把对应的正则表达式部分放到括号里,
比如请求/articles/2005/03/,就会匹配到上面第三条,因为有两个括号,所以就会有两个参数,实际调用的视图函数方式为:views.month_archive(request, '2005', '03'),这种类型的参数叫unamed group参数,在写视图函数的时候有两种写法:
'''
#第一种
def month_archive(request,year_p,month_p):
print(year_p,month_p)
...
#第二种
或者第二种可变参数形式:
def month_archive(request,*args):
year=args[0]
month=args[1]
...
'''
这种参数也叫位置参数positional arguments
(注意:/articles/2005/3/ 这种请求不会匹配上面任一种url,因为位数不对)
上面这种叫unamed group,那必然有一种叫named group,这种匹配的参数叫关键字参数keyword arguments.
这种urlpattern写法为:
----
'''
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
'''
可见相比于第一种,第二种在前面增加了?P<year>部分,这就可以给获取到的参数取个名字放在字典里了,
例如:/articles/2005/03/ 这种url调用的函数就是: views.month_archive(request, year='2005', month='03')
视图里获取这种参数的形式为:
'''
#第一种
def month_archive(request,year,month):
print(year,month)
...
**注意这里的参数名year和month必须和url里定义的参数名一致,不然会报错,这和unamed group的位置参数不一样
#第二种
def month_archive(request,**kwargs):
print(kwargs['year'],kwargs['month'])
...
5-4 视图_登录案例1
5-5 视图_登录案例2_request对象属性
- request.POST 保存 post 提交的参数 QueryDict
- request.GET 保存 get 提交的参数 QueryDict
注意:QueryDict 与 Dict 字典的区别?
答:Dict 一个键对应一个值,QueryDict 可以获取多个值, q.getlist(‘key’)
from django.http.request import QueryDict
q = QueryDict('a=1&b=2&c=3')
q['a'] # 异常
q.get('a','default') # 返回 Null
request.POST.get('key')
----
request 属性:
- path
- method
- encoding
- GET
- POST
- FILES
- COOKIES
- session
5-6 视图_ajax请求
- 解决的问题:再不重新加载页面的情况下,对页面进行局部的刷新。
ajax - 异步的 javascript
$.ajax([
'url':请求地址,
'type':请求方式,
'dataType':预期返回数据格式,
'async':false,//同步的ajax请求
'data':参数
]).success(function(data){
// 执行成功后的回调函数
})
-
settings.py
STATIC_URL = ‘/static’
STATICFILES_DIRS = [os.path.join()] -
from django.shortcuts import render, HttpResponse
import json -
return HttpResponse(json_data)
-
from django.http import HttpResponse, JsonResponse
-
return JsonResponse(data)
5-7 视图_ajax同步和异步
默认的是异步的请求
- 同步:‘async’:false,//同步的ajax请求
- 异步:‘async’:true,// 异步的ajax请求
5-8 视图_ajax登录案例
- 自己提交数据
- ajax 请求在后台,不要返回页面或者重定向
6 cookie与session
记录用户的登陆状态;会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
(cookie和session的详解与区别)[https://www.cnblogs.com/l199616j/p/11195667.html]
6-1 状态保持_cookie
-
cookie 服务器生成,交给浏览器保存的信息;存储在客户端
键->值
对的信息; -
cookie 基于域名安全的;需要注意的是,虽然网站images.google.com与网站www.google.com同属于Google,但是域名不一样,二者同样不能互相操作彼此的Cookie。
-
cookie 是有过期时间的,默认的浏览器关闭就会过期;
-
Unicode编码:保存中文
中文与英文字符不同,中文属于Unicode字符,在内存中占4个字符,而英文属于ASCII字符,内存中只占2个字节。Cookie中使用Unicode字符时需要对Unicode字符进行编码,否则会乱码。提示:Cookie中保存中文只能编码。一般使用UTF-8编码即可。不推荐使用GBK等中文编码,因为浏览器不一定支持,而且JavaScript也不支持GBK编码。 -
BASE64编码:保存二进制图片
Cookie不仅可以使用ASCII字符与Unicode字符,还可以使用二进制数据。例如在Cookie中使用数字证书,提供安全度。使用二进制数据时也需要进行编码。
注意:本程序仅用于展示Cookie中可以存储二进制内容,并不实用。由于浏览器每次请求服务器都会携带Cookie,因此Cookie内容不宜过多,否则影响速度。Cookie的内容应该少而精。 -
给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
-
Cookie的有效期
-
HttpResponse 的对象或者 子类的对象
- set_cookie 方法;
response = HttpResponse('设置 cookie') response.set_cookie('num', 1, max_age = 14*24*3600) # response.set_cookie('num', 1, expires=datetime.now()+timedelta(days=14) return response; ''' ---- ---- ---- ---- Headers Response Headers View source Content-Type: text/html; charset=utf-8 Date: Fri, 26 Nov 2021 03:36:55 GMT Server: WSGIServer/0.2 CPython/3.9.5 Set-Cookie: num=1; Path=/ X-Frame-Options: SAMEORIGIN '''
- 浏览器发给服务器的 cookie 保存在 HttpRequest 的对像里面
num = request.COOKIES['num'] return HttpResponse(num);
6-2 状态保持_cookie记住用户名
6-3 状态保持_session
- sessionid 唯一的标识码
- session 的特点
- session 是以键值对存储
- session 依赖于 cookie
- session 也是有过期时间,如果不指定,默认两周就会过期
- Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。
- Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。 - Session对象是在客户端第一次请求服务器的时候创建的。
- Session也是一种key-value的属性对
- Session的生命周期
Session保存在服务器端。为了获得更高的存取速度,服务器一般把Session放在内存里。每个用户都会有一个独立的Session。如果Session内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session里的信息应该尽量精简。
Session在用户第一次访问服务器的时候自动创建。需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session。如果尚未生成Session,也可以使用request.getSession(true)强制生成Session。
Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session“活跃(active)”了一次。
- Session的有效期
由于会有越来越多的用户访问服务器,因此Session也会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。
Session的超时时间为maxInactiveInterval属性,可以通过对应的getMaxInactiveInterval()获取,通过setMaxInactiveInterval(longinterval)修改。
Session的超时时间也可以在web.xml中修改。另外,通过调用Session的invalidate()方法可以使Session失效。
- session 的读取
- request.session[‘username’] = ‘啦啦啦’
- request.session[‘username’]
- 保存在 django_session 表里面;
6-4 状态保存_session记住登录状态
6-5 状态保持_cookie和session应用场景
- cookie:记住用户名。安全性要求不高
- 涉及到安全性要求比较高的数据,银行卡账户密码
总结:cookie和session的区别
1、cookie数据存放在客户的浏览器上,session数据放在服务器上.
简单的说,当你登录一个网站的时候,如果web服务器端使用的是session,那么所有的数据都保存在服务器上面,
客户端每次请求服务器的时候会发送 当前会话的session_id,服务器根据当前session_id判断相应的用户数据标志,以确定用户是否登录,或具有某种权限。
由于数据是存储在服务器 上面,所以你不能伪造,但是如果你能够获取某个登录用户的session_id,用特殊的浏览器伪造该用户的请求也是能够成功的。
session_id是服务器和客户端链接时候随机分配的,一般来说是不会有重复,但如果有大量的并发请求,也不是没有重复的可能性。
Session是由应用服务器维持的一个服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的SessionID,用该SessionID 为标识符来存取服务器端的Session存储空间。而SessionID这一数据则是保存到客户端,用Cookie保存的,用户提交页面时,会将这一 SessionID提交到服务器端,来存取Session数据。这一过程,是不用开发人员干预的。所以一旦客户端禁用Cookie,那么Session也会失效。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。
3、设置cookie时间可以使cookie过期。但是使用session-destory(),我们将会销毁会话。
4、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用cookie。
5、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。(Session对象没有对存储的数据量的限制,其中可以保存更为复杂的数据类型)
注意:
session很容易失效,用户体验很差;
虽然cookie不安全,但是可以加密 ;
cookie也分为永久和暂时存在的;
浏览器 有禁止cookie功能 ,但一般用户都不会设置;
一定要设置失效时间,要不然浏览器关闭就消失了;
例如:
记住密码功能就是使用永久cookie写在客户端电脑,下次登录时,自动将cookie信息附加发送给服务端。
application是全局性信息,是所有用户共享的信息,如可以记录有多少用户现在登录过本网站,并把该信息展示个所有用户。
两者最大的区别在于生存周期,一个是IE启动到IE关闭.(浏览器页面一关 ,session就消失了),一个是预先设置的生存周期,或永久的保存于本地的文件。(cookie)
Session信息是存放在server端,但session id是存放在client cookie的,当然php的session存放方法是多样化的,这样就算禁用cookie一样可以跟踪
Cookie是完全保持在客户端的如:IE firefox 当客户端禁止cookie时将不能再使用
7 模板templates
7-1 模板_模板文件使用
- 模版的功能
产生html,控制页面上展示的内容。模版文件不仅仅是一个html文件。模版文件包含两部分内容:-
- 静态内容: css,js,html
-
- 动态内容: 用于动态去生产一些网页内容,通过模版语言来产生
-
- 模版文件的使用
通常是在视图函数中使用模版产生 html 内容返回给客户端。
from django.template import loader,RequestContext
-
- 加载模版文件 loader.get_template
获取模版文件的内容,产生一个模版对象
- 加载模版文件 loader.get_template
-
- 定义模版上下文 RequestContext
给模版文件传递数据
- 定义模版上下文 RequestContext
-
- 模版渲染产生 html 页面内容 render
用传递的数据替换相应的变量,产生一个替换后的标准的 html 内容
- 模版渲染产生 html 页面内容 render
from django.template import loader,RequestContext from django.http import HttpResponse def index(request): #1 temp = loader.get_template('test1/index.html') #2 context = RequestContext(request,{}) #3 res_html = temp.render(context) # 4 # return HttpResponse(res_html) ''' 上面4步的总和和下面的 render 函数的功能相同 ''' return render(request, 'test1/index.html')
-
7-2 模板_模板文件加载顺序
- 首先去配置的模版目录的文件下找 settings.py
TEMPLATES
- 去 INSTALL_APPS 下面的每个应用去找模版文件,前提是应用中必须有 templates 文件夹
settings.py
INSTALLED_APPS
注册的所有应用
7-3 模板语言_模板变量
模版语言:简称 DTL (Django Template Language)
模版变量名是由数字,字母,下划线和点组成,不能以下划线开头。使用模版变量:{{ 模版变量名 }}
模版变量的解析顺序:
例如:{{ book.btitle }}
1)首先把 book 当成一个字典,把 btitle 当成键名,进行取值 book[‘btitle’]
2)把 book 当成一个对象,把 btitle 当成属性,进行取值 book.btitle
3)把 book 当成一个对象,把 btitle 当成对象的方法,进行取值 book.btitle
例如:{{book.0}}
1)首先把 book 当成一个字典,把 0 当成键名,进行取值 book[‘0’]
2)把 book 当成一个列表,把 0 当成下标,进行取值 book[0]
如果解析失败,则产生内容时用空字符串
填充模版变量。
7-4 模板语言_模板标签和过滤器
------
{% 代码段 %}
for 循环:
{% for x in 列表%}
# 列表不为空的时候执行
{% empty %}
# 列表为空的时候执行
{% endfor %}
可以通过 {{ forloop.counter }} 得到 for 循环遍历了几次。
-----
{% if 条件 %}
{% elif 条件 %}
{% else %}
{% endif %}
-----
关系比较操作符:> < >= <= == !=
注意:进行比较操作时,比较操作符两边必须有空格。
-----
逻辑运算:not and or
7-5 模板语言_自定义过滤器
过滤器用于对模版变量进行操作
date:
length:
default:
格式: 模版变量 | 过滤器:参数
自定义过滤器:
参考资料:(模版标签和内置过滤器)
http://python.usyiyi.cn/documents/django_182/ref/templates/builtins.html
7-6 模板语言_模板注释
模版注释的内容,浏览器源码是看不到的
html的注释,浏览器源码是可以看到的
单行注释: {%# 模版注释 %}
多行注释:
{% comment %}
注释内容
{% endcomment %}
7-7 模板语言_小结
- 模版变量
字典、对象、列表 + . - 模版标签
模版标签实现一些逻辑运算 - 过滤器
模版变量|过滤器:参数
可以自定义:
自定义过滤器最少一个参数,最多两个
7-8 模板_模板继承
页面不同的内容,需要在父模版中预留位置:预留块
在父模版中可以定义块,使用标签:
{% block 块名%}
块中间可以写内容可以不写内容
{% endblock 块名%}
子模版去继承父模版之后,可以重写父模版中的某一块内容。
继承格式 :{% extends ‘模版文件的路径’ %}
{% block 块名%}
{% block.super %} # 获取父模版中默认的内容
{% block 块名%}
重写内容
{% endblock 块名%}
把所有页面相同的内容放到父模版中,不需要放在块中,有些位置页面内容不痛,需要在父模版中预留块。
7-9 模板_html转义
在模版上下文中
的html标记默认是会被转义的。
小于号 < | <
大于号 < | >
单引号 ’ | '
双引号 " | &cuot
与 & | &
要关闭模版上下文字符串转义,可以使用 {{ 模版变量| safe }}
也可以使用
{% autoescape off%}
模版语言代码
{% endautoescape %}
模版硬编码中的字符串默认不会经过转译,如果需要转移,那需要手动进行转义
8 基于模板登录案例
8-1 模板_登录装饰器
def login_required(view_func):
‘’‘登陆装饰器’‘’
def wrapper(request, *view_args, **view_kwargs):
if request.session.has_key('is_login'):
return view_func(request, *view_args, **view_kwargs)
else:
return redirect('/login')
return wrapper
8-2 模板_csrf伪造
默认开启
8-3 模板_django_csrf防护
django防止csrf的方式:
1)默认打开 csrf 中间件。
2)表单post
提交数据时加上{% csrf_token %}标签。
防御原理:
1)渲染模版文件时子页面生成一个名字叫做 csrfmiddlewaretoken 的隐藏域。
2)服务器交给浏览器保存一个名字为 csrftoken 的 cookie 信息。
3)提交表单时,两个值都会发给服务器,服务器进行比对,如果一样,则csrf验证通过,否则失败。
8-4 模板_验证码
在用户注册、登陆页面,为了防止暴力请求,可以加入验证码功能。
如果验证码错误,则不需要继续处理,可以减轻业务服务器、数据库服务器的压力。
下面是处理图片的一个包
pip install Pillow
from PIL import Image,ImageDraw,ImageFont
8-5 模板_url反向解析
当某个url配置的地址发生变化时,页面上使用反响解析生成的位置不需要发生变化。
根据 url 正则表达式的配置动态生成 url。
项目:urls.py
urlpatterns = [
url(r’^',include(‘test.urls’,namespace=‘test’))
]
应用:urls.py
urlpatterns = [
url(r’^indexKaTeX parse error: Expected 'EOF', got '#' at position 32: …me='index'), #̲ url反向解析页面 …',views.show_args,name=‘show_args’), # 捕获位置参数
# 关键字参数
]
url_reverse.html
/shwo_args/1/2
- 模板中–通过URL标签实现地址的反向解析
{% url ‘别名’%}
{% url ‘别名’% ‘参数值1’ ‘参数值2’}
eg:
{% url ‘pagen’ ‘100’ %}
{% url ‘person’ age=‘18’ name=‘xixi’%} - 视图函数中 – 可调用Django中的reverse方法进行反向解析
from django.urls import reverse
reverse(‘别名’,args=[],kwargs={})
eg:
reverse(‘pagen’,args=[100])
reverse(‘person’,kwargs={‘age’:18,‘name’:‘xixi’})
from django.urls import reverse
url = reverse(‘base_index’)
return HttpResponseRedirect(url)
9 django功能-静态文件、中间件、后台
9-1 静态文件
静态文件:图片、css、js、音频、视频等都属于静态文件
- 目录:
/static
- /css
- /js
- /image
- 项目目录下 settings.py:
1)在setting.py 中配置静态文件的访问路径
''' STATIC_URL用于配置指定通过那个URL地址访问静态文件'''
STATIC_URL = '/statics/' # http://127.0.0.1:8000/statics/
''' STATICFILES_DIRS 用于配置静态文件的存储路径,即静态文件在服务器端的存储位置'''
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),) # 元组
2)模板中静态文件访问
方案1 --直接拼接访问路径
<img src="http://127.0.0.1:8000/static/image/django.jpg" width="200px" height="200px">
<img src="/static/image/django.jpg" width="200px" height="200px">
方案2 --img标签为例
通过 {%static%} 标签访问静态文件
步骤:
① 加载static —》{%load static%}
② 使用静态资源 —》 {%static ’静态资源路径‘ %}
<!--方案2访问静态文件 image/cloud.jpeg 前面不需要加/,只要指出static下那个文件夹即可-->
<!--推荐使用2 动态获取-->
{% load static %}
<img src="{% static 'image/cloud.jpeg' %}" width="200px" height="200px">
9-2 中间件_概念
- 在应用的目录下创建
middleware.py
文件
获取浏览器端的IP地址 : request.META[‘REMOTE_ADDR’]
touch middleware.py
class BlockIPMiddleware(object):
EXCLUDE_IPS = ['172.16.144.152']
def process_view( self, request,view_func, *view_args,**view_kwargs):
"""视图函数调用之前会调用"""
user_ip = request.META['REMOTE_ADDR']
if user_ip in BlockIPMiddleware.EXCLUDE_IPS:
return HttpResponse('<h1>Forbidden</h1>')
- 在 settings.py 注册中间件类
MIDDLEWARE_CLASSES = [
…,
…,
应用名称.middleware.BlockIPMiddleware
]
9-3 中间件_执行流程
在类中定义中间件预留函数:
init: 服务器响应第一个请求的时候调用。
process_request: 是在产生 request 对象,进行 url 匹配之前调用。
process_view: 是 url 匹配之后,调用试图之前。
process_response: 试图函数调用之后,内容返回给浏览器之前。
process_exception: 视图函数出现异常,会调用这个函数。
注:如果注册的多个中间件类中包含 process_exception 函数的时候,调用的顺序跟注册的顺序是相反的。
9-4 中间件_小结
中间件就是django预留的函数
9-5 后台管理_列表页选项|编辑页选项
项目应用的 admin.py
from django.contrib import admin
# Register your models here.
from test1.models import BookInfo
# 自定义模型管理类
class BookInfoAdmin(admin.ModelAdmin):
'''图书管理页面模型'''
# 列表页的选项
list_display = ['id','btitle','bpub_date']
list_per_page = 10 # 每页展示多少也
actions_on_bottom = True
actions_on_top = False
list_filter = ['btitle'] # 过滤栏
search_fields = ['btitle'] # 列表页上方的搜索框
# 编辑页的选项
fieldsets = (
('基本',{'fields':['btitle']}),
('高级',{'fields':['btitle']})
)
admin.site.register(BookInfo,BookInfoAdmin)
9-7 后台管理_自定义页面
找到后台管理页面重写
Admin站点
10 图片上传及分页
上传文件 class UploadeFile
10-1 上传图片_后台管理
页面上传
- 配置上传文件的保存目录:setting.py
MEDIA_URL = ‘/media/’
MEDIA_ROOT = os.path.join(BASE_DIR, ‘media’)
文件上传之后都会存储在该路径下,直接copy就好
1. models.py中新建包含FileField的model
class PicTest(models.Model):
gpic = model.ImageFiled(upload_to='booktest') # 指定上传目录
2. 生成迁移表
id|gpic
3. 注册模型
10-2 上传图片_自定义页面上传
1. 定义用户上传图片的页面
<form method="post" action="/upload_action/" enctype=“multipart/form-data”>
<% csrf_token %>
<input name="file_name" type="file">
<button type="submit">上传</button>
</form>
2. 定义接收上传文件的处理文件
request对象有一个FILES的属性,类似于字典,通过 request.FILES 可以获取上传文件的处理对象
FILE_UPLOAD_HANDLERS = (
"django.core.files.uploadhandler.MemoryFileUploadHandler",
"django.core.files.uploadhandler.TemporaryFileUploadHandler"
)
图片大小 < 2.5M,图片放在内存中: django.core.files.uploadhandler.MemoryFileUploadHandler
上传文件 >= 2.5 , 文件内容写到临时文件中: django.core.files.uploadhandler.TemporaryFileUploadHandler
10-3 分页
# urls.py
urlpatterns = [
# 通过 url 函数设置 url 路由配置
url(r'^index(\d+)$',views.index),
]
# model.py
from django.core.paginator import Paginator
def show_area(request):
"""分页"""
areas = AreaInfo.objects.filter(aParent__isnull=True)
paginator = Paginator(areas,10)
if pindex == '':
pindex = 1
else:
pindex = int(pindex)
page = paginator.page(pindex) # page 是 Page 的对象
return render(request,'test1/show_area.html',{'page':page})
# view.html
<ul>
{% for area in page.object_list %}
<li>{% area.atitle %}</li>
{% endfor %}
<ul>
{% for pindex in page.paginator.page_range %}
{% if pindex == page.number %}
{{ pindex }}
{% else %}
<a href="/index{{pindex}}">{{ pindex }}</a>
{% endif %}
{% endfor %}
小结
-
图片处理包:
pip install Pillow
from PIL import Image,ImageDraw,ImageFont -
settings.py 本地化/时间设置
- 升级Python和pip (ubuntu 16.04)
-
sudo apt-get install python3.5 # 安装python
sudo apt-get install python3-pip # 安装python 3-pip
sudo rm /usr/bin/python # 删除python 2.7版本
sudo ln -s /usr/bin/python3.5 /usr/bin/python # 将python链接到最新3.5版的
pip3 install upgrade -- pip # 升级pip
pip3 -- version #查看pip版本
- 创建虚拟环境
•sudo pip install virtualenv virtualenvwrapper
•echo"export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3" >> ~/.bashrc
•echo"export WORKON_HOME=~/Env" >> ~/.bashrc
•echo"source /usr/local/bin/virtualenvwrapper.sh">> ~/.bashrc
•source ~/.bashrc
我们不仅安装了virtualenv,还安装了virtualenvwrapper,并将配置信息输入到.bashrc文件里了。这里.bashrc隐藏文件是用来存储并加载你的终端配置和环境变量的。现在你可以使用如下命令创建,终止和切换虚拟环境了,这样比使用virtualenv的source /bin/venv/activate等命令来激活和管理一个虚拟环境方便多了。
•mkvirtualenv myproject #创建一个myproject的虚拟环境
•deactivate #退出虚拟环境
•workon myproject1 #切换到myproject1的虚拟环境
- 安装Django
使用mkvirtualenv myproject命令创建一个叫myproject的虚拟环境后,你就可以把Django安装在这个虚拟环境里了。
• pip install django #安装django
Django安装好后,cd进入/home/enka目录使用sudo mkdir myproject命令创建一个叫myproject的文件夹(建议与虚拟环境名保持一致,与本地Django项目名保持一致)。这个项目文件夹地址是/home/enka/myproject, 里面将存放django代码,此时可以通过git clone在线获取项目代码,也可以通过FileZilla将本地项目代码上传到这里。(注: 如果你没有现成项目代码,你还可以通过使用django-admin.py startproject myproject在线创建一个项目。)
项目代码到位后,连续输入以下命令,然后访问公网ip地址:8080,你应该就可以看到你的django项目已经上线啦。
• pip install -r requirements.txt #安装依赖文件
• python manage.py createsuperuser #创建超级用户
• python manage.py makemigrations
• python manage.py migrate #生产数据表
• python manage.py collectstatic #搜集静态文件
• python manage.py runserver 0.0.0.0:8080
注意, 运行项目前请确保你已经在settings.py里设置STATIC_ROOT= os.path.join(BASE_DIR, "static/")和ALLOWED_HOSTS= ['your_server_domain_or_IP']。