4. 虚拟环境
4.1 概念
之前安装python包的命令: sudo pip3 install 包名
包的安装路径:/usr/local/lib/python3.5/dist-packages
在同一个python环境中安装同一个包的不同版本,后安装的包会把原来安装的包覆盖掉。这样,如果同一台机器上两个项目依赖于相同包的不同版本,则会导致一些项目运行失败。
解决的方案就是:虚拟环境。
虚拟环境是真实python环境的复制版本。
在虚拟环境中使用的python是复制的python,安装python包也是安装在复制的python中。
4.2 安装和配置
安装虚拟环境的命令:
- 1)sudo pip install virtualenv #安装虚拟环境
- 2)sudo pip install virtualenvwrapper #安装虚拟环境扩展包
- 3)编辑/home目录下面的.bashrc文件,添加下面两行。
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
- 4)使用source .bashrc使其生效一下。
4.3 使用
- 创建虚拟环境命令:mkvirtualenv 虚拟环境名
- 创建python3虚拟环境:mkvirtualenv -p python3 evn_py3
- 创建python3虚拟环境名,# 在创建虚拟环境时,必须保证有网
- 进入虚拟环境工作:workon 虚拟环境名
- 查看机器上有多少个虚拟环境:workon 空格 + 两个tab键
- 退出虚拟环境:deactivate
- 删除虚拟环境:rmvirtualenv 虚拟环境名
- 虚拟环境下安装包的命令:pip install 包名
注意:不能使用sudo pip install 包名,这个命令会把包安装到真实的主机环境上而不是安装到虚拟环境中。 - 查看虚拟环境中安装了哪些python包:
pip list
pip freeze
- 安装django环境:pip install django==3.0.3
- 如果网不好,会报错:在python中安装包出现Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None))
-- 参考链接1
pip install django==3.0.3 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
拓展:
apt-get install 软件
pip install python包名
5. 项目创建
5.1 创建Django项目
-
命令:django-admin startproject 项目名(test1)
注意:创建应用必须先进入虚拟环境。
-
tree可查看项目目录
-
项目目录如下:
- __init__.py: 说明test1是一个python包。
- settings.py: 项目的配置文件。
- urls.py: 进行url路由的配置。
- wsgi.py: web服务器和Django交互的入口。
- manage.py: 项目的管理文件。
5.2 创建Django应用
一个项目由很多个应用组成的,每一个应用完成一个功能模块。
- 创建应用的命令如下:python manage.py startapp 应用名(booktest)
注意:创建应用时需要先进入项目目录。 - 应用目录如下:
- __init__.py: 说明目录是一个Python模块。
- models.py: 写和数据库项目的内容, 设计模型类。
- views.py: 接收请求,进行处理,与M和T进行交互,返回应答。定义处理函数,视图函数。
- 定义处理函数,视图函数---相对于mini-web中的处理函数 def def add_focus(ret): # 1. 获取股票代码
- tests.py: 写测试代码的文件。
- admin.py: 网站后台管理相关的文件。
5.3 应用注册
建立应用和项目之间的联系,需要对应用进行注册,修改settings.py中的INSTALLED_APPS配置项。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'booktest' #加入'booktest', # 进行应用的注册
]
5.4 启动项目
- 运行开发web服务器命令:python manage.py runserver
- 使用Django中内置的服务器:python manage.py runserver
- 复制文件中的http://127.0.0.1:8000/到浏览器并打开(或192.168.x.xx:xxxx)
- 如果是虚拟机中,可能出现:主机无法访问虚拟机中运行的Django项目
- 运行Django的命令,要写成: python3 manage.py runserver 0.0.0.0:8000 ,重点就是这个0.0.0.0,这样才能让外部访问到
- 参考链接2
- 如果出现:Invalid HTTP_HOST header: '192.168.1.111:8000'. You may need to add '192.168.1.111' to ALLOWED_HOSTS
- 在我们创建的项目里修改setting.py文件 ALLOWED_HOSTS = ['*'] #在这里请求的host添加了*
- 参考链接3
- 复制文件中的http://127.0.0.1:8000/到浏览器并打开(或192.168.x.xx:xxxx)
6. 模型类
6.1 ORM
django中内嵌了ORM框架,ORM框架可以将类和数据表进行对应起来,只需要通过类和对象就可以对数据表进行操作。
- 在Django中主要是 设计类:模型类。
- 在models.py文件中填写
ORM另外一个作用:根据设计的类生成数据库中的表。
- 在models.py文件中填写
6.2 模型类设计
在应用models.py中设计模型类,必须继承于models.Model类。
- 1) 设计BookInfo类。
- 2) 设计HeroInfo类。
Models.ForeignKey可以建立两个模型类之间一对多的关系,django在生成表的时候,就会在多端的表中创建一列作为外键,建立两个表之间一对多的关系。
6.3 模型类生成表
-
- 生成迁移文件
- 命令:python manage.py makemigrations
迁移文件是根据模型类生成的。
-
- 执行迁移生成表
- 命令:python mange.py migrate
根据迁移文件生成表。
生成表名的默认格式:
应用名_模型类名小写
- 3)安装sqliteman:sudo apt-get install sqliteman 安装失败,更换源
- 根据迁移文件生成表,生成表名的默认格式: 应用名_模型类名小写
6.4 通过模型类操作数据表
- 进入项目shell的命令: python manage.py shell
以下为在相互shell终端中演示的例子: - 首先导入模型类:
> from booktest.models import BookInfo,HeroInfo
#1) 向booktest_bookinfo表中插入一条数据。
b = BookInfo() #定义一个BookInfo类的对象
b.btitle ='天龙八部' #定义b对象的属性并赋值
b.bpub_date = date(1990,10,11)
b.save() #才会将数据保存进数据库
#2) 查询出booktest_bookinfo表中id为1的数据。
b = BookInfo.objects.get(id=1)
#3) 在上一步的基础上改变b对应图书的出版日期。
b.bpub_date = date(1989,10,21)
b.save() #才会更新表格中的数据
#4) 紧接上一步,删除b对应的图书的数据。
b.delete() #才会删除
#5) 向booktest_heroInfo表中插入一条数据。
h = HeroInfo()
h.hname = '郭靖'
h.hgender = False
h.hcomment = ‘降龙十八掌’
b2 = BookInfo.objects.get(id=2)
h.hbook = b2 #给关系属性赋值,英雄对象所属的图书对象
h.save()
#6) 查询图书表里面的所有内容。
BookInfo.objects.all()
HeroInfo.objects.all()
6.4.1. models.py中:
from django.db import models
# 设计和表对应的类,模型类
# Create your models here.
# 一类
# 图书类
class BookInfo(models.Model): # 要继承models.Model以后,才是一个模型类
# '''图书模型类'''
# 图书名称,Charfield说明是一个字符串,max_length指定字符串的最大长度
btitle = models.CharField(max_length=20)
# 出版日期,DateField说明是一个日期类型
bpub_date = models.DateField()
# 生成的db.sqlite3可以用sudo apt-get install sqliteman后,打开
# django默认sqlite小型数据库,要替换成mysql
# 多类
# 英雄人物类
# 英雄名 name
# 性别 hgender
# 年龄 hage
# 备注 hcomment
# 关系属性 hbook,建立图书类和英雄人物类之间的一对多关系
class HeroInfo(models.Model):
# '''英雄人物模型类'''
hname = models.CharField(max_length=20) # 英雄名称
# 性别,BooleanField说明是bool类型,default指定默认值,False代表男
hgender = models.BooleanField(default=False)
# 备注
hcomment = models.CharField(max_length=128)
# 关系属性 hbook,建立图书类和英雄人物类之间的一对多关系
# 关系属性对应的表的字段名格式: 关系属性名_id
hbook = models.ForeignKey('BookInfo', on_delete=models.CASCADE,)
# ForeignKey外键
# 通过模型类操作数据表
# 进入项目shell的命令:python manage.py shell
#
# 增加实例属性要和类属性名称一样
6.5 关联操作
1) 查询出id为2的图书中所有英雄人物的信息。
b = BookInfo.objects.get(id=2)
b.heroinfo_set.all() #查询出b图书中所有英雄人物的信息
7. 后台管理
1) 本地化
- 语言和时区的本地化。
- 修改settings.py文件。
# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans' # 使用中文
# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai' # 中国时间
2) 创建管理员
- 命令:python manage.py createsuperuser
- 执行时,可能会报错:Django项目出现: 禁止访问(403),CSRF验证失败,相应中断
- 解决办法:在app的views.py 文件中可以添加一个 from django.template import RequestContext 然后,渲染函数render 添加即可。
- 如: return render(request, ‘users/register.html’,context={‘form’:form})
- 参考链接7.2
3) 注册模型类
在应用下的admin.py中注册模型类,告诉djang框架根据注册的模型类来生成对应表管理页面。
from booktest.models import BookInfo, HeroInfo
admin.site.register(BookInfo)
admin.site.register(HeroInfo)
- __str__:如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值
- models.py中:重写一个__str__方法
class BookInfo(models.Model):
"""图书模型类"""
...
def \_\_str__(self):
# 返回英雄名
return self.hname
4) 自定义管理页面
自定义模型管理类:模型管理类就是告诉django在生成的管理页面上显示哪些内容。
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)
8. 视图
在Django中,通过浏览器去请求一个页面时,使用视图函数来处理这个请求的,视图函数处理之后,要给浏览器返回页面内容。
8.1视图函数的使用
1) 定义视图函数
视图函数定义在views.py中。
- 例:
def index(request):
#进行处理。。。
return HttpResponse('hello python')
视图函数必须有一个参数request,进行处理之后,需要返回一个HttpResponse的类对象,hello python就是返回给浏览器显示的内容。
2) 进行url配置---项目文件夹(test1)下的urls.py
url配置的目的是让建立url和视图函数的对应关系。url配置项定义在urlpatterns的列表中,每一个配置项都调用url函数。
url函数有两个参数,第一个参数是一个正则表达式,第二个是对应的处理动作。
- 配置url时,有两种语法格式:
- a) url(正则表达式,视图函数名)
- b) url(正则表达式,include(应用中的urls文件))
- 工作中在配置url时,首先在项目的urls.py文件中添加配置项,
- 但并不写具体的url和视图函数之间的对应关系,而是写包含具体应用的urls.py文件,
- 然后,在应用的urls.py文件中写url和视图函数的对应关系。
8.2 url匹配的过程
在项目的/test1/urls.py文件中包含具体应用的urls.py文件,应用的/booktest/urls.py文件中写url和视图函数的对应关系。
urlpatterns = [
url(r'^admin/', admin.site.urls), # 配置项目
url(r'^',include('booktest.urls')), # 包含booktest应用中urls
# path('admin/', admin.site.urls),
]
- 可能会报错:include()函数报错'provide the namespace argument to include() instead.' % len(arg)
- 解决方案:url(r'^', include(('booktest.urls', 'booktest'), namespace='booktest')),
- 参考链接8.2
# 建议直接将项目test1/urls.py文件的内容,直接复制到应用booktest/urls.py文件中,再将不需要的地方修改掉,这样就不会错了。
"""test/urls.py"""
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include(('booktest.urls', 'booktest'), namespace='booktest')),
]
# ---------------------------------------------------------------------------------
"""booktest/urls.py"""
from django.conf.urls import url
from booktest import views
# 创建列表urlpatterns,视图调用就是从这个列表中调用,
# 需要通过导入from django.conf.urls import url 来调用项目的urls文件
# 在应用的urls文件中进行url配置的时候:
# 1.严格匹配开头和结尾
urlpatterns = [
# 通过url函数设置url路由配置项
url(r'^index$', views.index), # 写入对应的index名字,建立/index和视图index之间的关系
# url(r'^index2', views.index2), # 此时的输入还是“老铁,没毛病”不对,因为在上一项匹配成功后,就不再匹配下一项了
url(r'^index2$', views.index2), # 故,为了解决这个问题,需严格匹配开头和结尾,加上^与$
url(r'^books$', views.show_books), # 显示图书信息,即/boos页面显示的内容
url(r'^books/(d+)$', views.detail), # 显示英雄信息,报错,需要一个bid的位置参数,这时要将d+作为一个组()
]
8.2.1. 当用户输入如http://127.0.0.1:8000/aindex时,去除域名和最前面的/,剩下aindex,拿aindex字符串
8.2.2. 先到项目的urls文件中进行匹配,配置成功后,去除匹配的a字符,拿剩下的index字符串继续到项目的urls
8.2.3. 文件中进行正则匹配,匹配成功之后执行视图函数index,index视图函数返回内容hello python给浏览器显示
9. 模板
模板不仅仅是一个html文件。
9.1 模板文件的使用
- 1 创建模板文件夹:项目test1/下面创建templates文件夹---/test1/templates/
- 2 配置模板目录
- settings.py文件中有TEMPLATES 选项,这个配置就是让我们去设置模板目录的。
- 在'DIRS': []中设置模板文件的目录,设置路径,但是路径不能随便设置,而应该根据BASE_DIR来设置
- 项目目录的绝对路径,pwd,/home/huang/bj18/test1得到的就是项目目录
- 设置时,将BASE_DIR和模板目录进行拼接
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',
],
},
},
]
-
设置完模板目录后,即可使用,为了给多个应用(booktest等)使用,不混淆,会在模板文件夹(templates)下,再新建同名文件夹booktest,
-
新建模板文件index.html,写好内容后,即可使用模板文件;
-
在mini_frame框架中,手动打开一个文件读取出来,Django中不能这样做,使用模板文件应该遵循以下步骤:
-
3 使用模板文件
- 1.定义视图函数,HttpRequest
- 在booktest下新建一个urls.py
- 视图函数的作用是: 调用模板,处理数据并返回给浏览器。
- 如果需要操作数据库,需要和M、T进行交互
- 2.进行url配置,建立url地址和视图的对应关系,和Flask相似
- 浏览器中输入http:127.0.0.1:8000/index # 用户要显示该url,需要在应用app中的urls列表中,添加该url
- 1.定义视图函数,HttpRequest
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader, RequestContext
from booktest.models import BookInfo, HeroInfo # 导入模型类
def index(request):
···
return render(request, 'booktest/index.html',
{'content': 'hello world', 'list':list(range(1, 10))}, )
urlpatterns = [
url(r'^index$', views.index), # 写入对应的index名字,建立/index和视图index之间的关系
]
以下a)-c)为视图函数调用模板文件的分析过程,可省略:
- 发现除get_template('booktest/index.html')中的'booktest/index.html'、context中的字典不同外,其余的部分都相同,
- 故,重新定义一个函数my_render(),但此方法是多余的,因为已经导入了render,所以可以直接使用
```
def my_render(request, template_path, context_dict):
"""使用模板文件"""
# 直接将index中的模板文件拿过来使用
# 1.加载模板文件
temp = loader.get_template(template_path) # 写上目录,该目录是相对templetes的目录---改为template_path
# 2.定义模板文件上下文:给模板文件传递数据,request,和要传递的数据,通过{}的键值对来传减去
# 导入from django.template import loader, RequestContext
# context = RequestContext(request, {''}) # Django1.11以后,就是直接传入{}即可,不再传入RequestContext(request, {''})---{}字典也改为通过context_dict来改变
# context = {}
context = context_dict
# 3.模板渲染(目的是把使用的变量,还有一些语句给替换掉):产生标准的html内容,temp中有一个render方法,将context放进去
res_html = temp.render(context)
# 4.返回给浏览器
return HttpResponse(res_html)
```
- a)加载模板文件----views.py中,使用模板文件 # 1.加载模板文件
- 导入包 from django.template import loader
- temp = loader.get_template('booktest/index.html') # 写上目录,该目录是相对templetes的目录
- b) 定义目标上下文---给模板文件传递定义的变量的值
- 给**模板文件传递数据**:request和要传递的数据,通过{}的键值对来传进去
- 导入from django.template import loader, RequestContext
- context = RequestContext(request, {''}) # Django1.11以后,就是直接传入{}即可,不再传入RequestContext(request, {''})
- # context = {}
- c) 模板渲染(目的是把使用的变量,还有一些语句给替换掉):产生标准的html内容,temp中有一个render方法,将context放进去
- res_html = temp.render(context)
- d) 返回给浏览器
- return HttpResponse(res_html)
9.2 给模板文件传递数据
- 模板变量使用:{{ 模板变量名 }}
- 模板代码段:{%代码段%}
- for循环:
{% for i in list %}
list不为空时执行的逻辑
{% empty %}
list为空时执行的逻辑
{% endfor %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板文件</title>
<style type="text/css">
</style>
</head>
<body>
<h1>这是一个模板文件</h1>
使用模板变量:<br/>
{{ content }}<br/>
使用列表:<br/>
{{ list }}<br/> # 这是直接显示列表的内容,py中还可以遍历出列表中的每一个文件
for循环:<br/>
<ul>
{% for i in list %}
<li>{{ i }}</li>
{% endfor %}
</ul>
</body>
</html>
9.3:小结:
- 我们需要做的事情:
- 1)定义视图函数
- 视图函数定义在views.py中。
- 2)进行url配置,项目视图+应用视图,两个。
- """test/urls.py"""
- """booktest/urls.py"""
- 1)定义视图函数
10. 案例完成
编码之前的准备工作:
-
1 设计出访问页面的url和对应的视图函数的名字,确定视图函数的功能。
- def show_books()、detail()
-
2 设计模板文件的名字。
- area.html、index.html
以下为案例中的简单设计过程:
-
1 完成图书信息的展示:
- 1.1 设计url,通过浏览器访问 http://127.0.0.1:8000/books 时显示图书信息页面。
# /test1/urls.py: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include(('booktest.urls', 'booktest'), namespace='booktest')), ]
#/booktest/urls.py: urlpatterns = [ # 通过url函数设置url路由配置项 url(r'^index$', views.index), url(r'^books$', views.show_books), # 显示图书信息,即/books页面显示的内容 url(r'^books/(d+)$', views.detail), # 显示英雄信息,报错,需要一个bid的位置参数,这时要将d+作为一个组() ]
- 1.1 设计url,通过浏览器访问 http://127.0.0.1:8000/books 时显示图书信息页面。
-
1.2 设计url对应的视图函数show_books。
- 查询出所有图书的信息,将这些信息传递给模板文件。
# views.py: import sys from django.shortcuts import render from django.http import HttpResponse from django.template import loader, from booktest.models import BookInfo, HeroInfo # 导入模型类 def show_books(request): """显示图书的信息""" # 1. 通过M查找图书表中的数据 books = BookInfo.objects.all() # 2. 使用模板 return render(request, 'booktest/show_books.html', {'books': books})
- 查询出所有图书的信息,将这些信息传递给模板文件。
-
1.3 编写模板文件show_books.html。
- 遍历显示出每一本图书的信息。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>显示图书信息</title>
<style type="text/css">
</style>
</head>
<body>
图书信息如下:
{% for book in books %}
<li><a href="/books/{{ book.id }}">{{ book.btitle}}</a></li>
{% endfor %}
</body>
</html>
- 2 完成点击某本图书时,显示出图书里所有英雄信息的页面。
- 2.1 设计url,通过访问http://127.0.0.1:8000/books/数字时显示对应的英雄信息页面。
- 这里数字指点击的图书的id。
url(r'^books/(d+)$', views.detail), # 显示英雄信息,报错,需要一个bid的位置参数,这时要将d+作为一个组()
- 这里数字指点击的图书的id。
- 2.2 设计对应的视图函数detail。
- 接收图书的id,根据id查询出相应的图书信息,然后查询出图书中的所有英雄信息。
def detail(request, bid): '''查询图书关联英雄信息''' # 1. 根据bid查询图书信息 book = BookInfo.objects.get(id=bid) # 2. 查询和book关联的信息---要分析1对多(由1查多b.heroinfo_set.all())还是多对1(h.hbook) # HeroInfo.objects.fliter(hbook__id=1) heros = book.heroinfo_set.all() # 需要显示图书的名字,和关联的英雄名字和备注 # 3. 使用模板detail,创建templates/bootest/detail.html return render(request, 'booktest/detail.html', {'book': book, 'heros': heros}) # 注意,此处是heros,不是hero,不然图书信息就无法显示 # 去应用booktest/urls中设置地址。
- 接收图书的id,根据id查询出相应的图书信息,然后查询出图书中的所有英雄信息。
- 2.3 编写模板文件detail.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>显示图书关联的英雄信息</title> <style type="text/css"> </style> </head> <body> <h1>{{ book.btitle }}</h1> 英雄信息如下:<br/> <ul> {% for hero in heros %} <li>{{ hero.hname }}--{{ hero.hcomment }}</li> {% empty %} <li>没有英雄信息</li> {% endfor %} </ul> </body> </html>
- 2.1 设计url,通过访问http://127.0.0.1:8000/books/数字时显示对应的英雄信息页面。