创建图书管理项目
在django中,项目的组织结构为一个项目包含多个应用,一个应用对应一个业务模块
示例:创建项目的名称为test1,完成“图书-英雄”信息的维护,创建应用名称为booktest
创建项目
在当前用户的某个目录下创建项目,这样不会发生权限问题
此处在/home/Desktop/pytest/目录下创建项目
cd /home/Desktop/
mkdir pytest
cd pytest
创建项目的命令如下:
django-admin startproject 项目名称
例:
django-admin startproject test1
接下来可以使用IDE打开此目录,开发项目了,此处使用pycharm打开pytest目录
项目默认目录说明
进入test1目录,查看目录树形结构
cd test1
tree
manage.py是项目运行的入口,指定配置文件路径
与项目同名的目录,此处为test1,包含项目的配置文件
init.py是一个空文件,作用是这个目录test1可以被当作包使用
settings.py是项目的整体配置文件
urls.py是项目的URL配置文件
wsgi.py是项目与WSGI兼容的Web服务器入口,详细内容会在part6的布署中讲到
创建应用
使用一个应用开发一个业务模块,此处创建应用名称为booktest,完成图书英雄的信息维护
创建应用的命令如下:
python manage.py startapp booktest
init.py是一个空文件,表示当前目录booktest可以当作一个python包使用
tests.py文件用于开发测试用例,在实际开发中会有专门的测试人员,这个事情不需要我们来做
其它文件和目录会在稍后的开发中使用到,会逐个讲解
安装应用
应用创建成功后,需要安装才可以使用
在test1/settings.py中INSTALLED_APPS下添加应用的名称就可以完成安装
初始项目的INSTALLED_APPS如下图:
安装前
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
)
在元组中添加一个新的项,当前示例为booktest
‘bootest’,
安装后
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'booktest',
)
开发服务器
在开发阶段,为了能够快速预览到开发的效果,django提供了一个纯python编写的轻量级web服务器,仅在开发阶段使用
运行服务器命令如下:
python manage.py runserver ip:端口
例:
python manage.py runserver
可以不写ip
默认端口为8000
在浏览器中输入网址“127.0.0.1:8000”,或者按着ctrl键点击上图中标示出来的地址,可以查看当前站点开发效果
如果增加、修改、删除文件,服务器会自动重启
按ctrl+c停止服务器
模型设计
当前项目的开发,都是数据驱动的,即分析出项目中所需要存储的数据,然后设计数据表及表结构,接下来再使用设计好的页面对表完成数据的crud
django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的crud
使用django进行数据库开发的步骤如下:
1.在models.py中定义模型类
2.迁移
3.通过类和对象完成数据crud
1.定义模型类
模型类定义在models.py文件中,继承自models.Model类
说明:不需要定义主键列,在生成时会自动添加,并且值为自动增长
图书表结构设计:
表名:BookInfo
图书名称:btitle
图书发布日期:bpub_date
英雄表结构设计:
表名:HeroInfo
英雄姓名:hname
英雄性别:hgender
英雄简介:hcontent
所属图书:hbook
图书-英雄的关系为一对多
根据设计,在models.py中定义模型类如下
from django.db import models
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
bpub_date = models.DateField()
def str(self):
return “%d” % self.pk
class HeroInfo(models.Model):
hname = models.CharField(max_length=20)
hgender = models.BooleanField()
hcontent = models.CharField(max_length=100)
hBook = models.ForeignKey(‘BookInfo’)
def str(self):
return “%d” % self.pk
2.迁移
默认采用sqlite3数据库
迁移前目录结构如下图:
迁移前
迁移由两步完成
1.生成迁移文件:根据模型类生成创建表的语句
2.执行迁移:根据第一步生成的语句在数据库中创建表
生成迁移文件命令如下:
python manage.py makemigrations
生成迁移文件
执行迁移命令如下:
python manage.py migrate
执行迁移
迁移后目录结构如下图:
迁移后
3.数据操作
进入项目的shell,进行简单的API操作
按ctrl+d或输入quit()可以退出shell
python manage.py shell
shell
首先引入booktest/models中的类:
from booktest.models import BookInfo,HeroInfo
查询所有图书信息:
BookInfo.objects.all()
因为当前并没有数据,所以返回空列表
查询
新建图书对象:
b=BookInfo()
b.btitle=“射雕英雄传”
from datetime import date
b.bpub_date=date(1990,1,10)
b.save()
添加
再次查询所有图书信息:
BookInfo.objects.all()
查询2
查找图书信息并查看值:
b=BookInfo.objects.get(pk=1)
b
b.id
b.btitle
b.bpub_date
查找
修改图书信息:
b.bpub_date=date(2017,1,1)
b.save()
b.bpub_date
修改
删除图书信息:
b.delete()
删除
对象的关联操作
对于HeroInfo可以按照上面的方式进行crud操作
创建一个BookInfo对象
b=BookInfo()
b.btitle=‘abc’
b.bpub_date=date(2017,1,1)
b.save()
创建一个HeroInfo对象
h=HeroInfo()
h.htitle=‘a1’
h.hgender=True
h.hcontent=‘he is a boy’
h.hBook=b
h.save()
图书与英雄是一对多的关系,django中提供了关联的操作方式
获得关联集合:返回当前book对象的所有hero
b.heroinfo_set.all()
关联集合
后台管理
站点分为内容发布和公共访问两部分
内容发布的部分由网站的管理员负责查看、添加、修改、删除数据,开发这些重复的功能是一件单调乏味、缺乏创造力的工作,为此,Django能够根据定义的模型类自动地生成管理模块
使用Django的管理模块,需要按照如下步骤操作
1.管理界面本地化
2.创建管理员
3.注册模型类
4.自定义管理页面
1.管理界面本地化
本地化是将显示的语言、时间等使用本地的习惯,这里的本地化就是进行中国化,中国大陆地区使用简体中文,时区使用亚洲/上海时区,注意这里不使用北京时区表示
打开test1/settings.py文件,找到语言编码、时区的设置项,将内容改为如下
LANGUAGE_CODE = ‘zh-Hans’
TIME_ZONE = ‘Asia/Shanghai’
2.创建管理员
创建管理员的代码如下,按提示输入用户名、邮箱、密码
python manage.py createsuperuser
创建管理员
启动服务器
python manage.py runserver
启动服务器
打开浏览器,在地址栏中输入如下地址后回车
http://127.0.0.1:8000/admin
打开浏览器
输入前面创建的用户名、密码完成登录
登录
登录成功后界面如下,但是并没有图书、英雄的管理入口,接下来进行第三步操作
登录成功
3.注册模型类
登录后台管理后,默认没有我们创建的应用中定义的模型类,需要在自己应用中的admin.py文件中注册,才可以在后台管理中看到,并进行crud操作
打开booktest/admin.py文件,编写如下代码
from django.contrib import admin
from models import BookInfo,HeroInfo
admin.site.register(BookInfo)
admin.site.register(HeroInfo)
到浏览器中刷新页面,可以看到模型类BookInfo和HeroInfo的管理了
注册成功
点击类名称“BookInfo”可以进入列表页,默认只有一列,显示的是str方法返回的值
列表页
在列表页中点击“增加”可以进入增加页,Django会根据模型类的不同,生成不同的表单控件,按提示填写表单内容后点击"保存",完成数据创建,创建成功后返回列表页
添加页
在列表页中点击某行的第一列可以进入修改页
修改页1
按照提示进行内容的修改,修改成功后进入列表页
在修改页点击“删除”可以删除一项
修改页2
删除:在列表页勾选想要删除的复选框,可以删除多项
删除1
点击执行后进入确认页面,删除后回来列表页面
删除2
数据都删除了,接下来手动造一些数据出来
4.自定义管理页面
在列表页只列出了str方法的返回值,对象的其它属性并没有列出来,查看非常不方便
Django提供了自定义管理页面的功能,比如列表页要显示哪些值
打开booktest/admin.py文件,自定义类,继承自admin.ModelAdmin类
属性list_display表示要显示哪些属性
class BookInfoAdmin(admin.ModelAdmin):
list_display = [‘pk’, ‘btitle’, ‘bpub_date’]
修改模型类BookInfo的注册代码如下
admin.site.register(BookInfo, BookInfoAdmin)
刷新BookInfo的列表页,所有属性都显示出来了
自定义列表页
最终booktest/admin.py文件代码如下
from django.contrib import admin
from models import BookInfo,HeroInfo
class BookInfoAdmin(admin.ModelAdmin):
list_display = [‘pk’, ‘btitle’, ‘bpub_date’]
class HeroInfoAdmin(admin.ModelAdmin):
list_display = [‘pk’, ‘hname’,‘hgender’,‘hcontent’]
admin.site.register(BookInfo,BookInfoAdmin)
admin.site.register(HeroInfo,HeroInfoAdmin)
视图
后台管理页面做好了,接下来就要做公共访问的页面了
对于django的设计框架MVT,用户在URL中请求的是视图,视图接收请求后进行处理,并将处理的结果返回给请求者
使用视图时需要进行两步操作
1.定义视图
2.配置URLconf
1.定义视图
视图就是一个Python函数,被定义在views.py中
视图的第一个参数是HttpRequest类型的对象reqeust,包含了所有请求的信息
视图必须返回HttpResponse对象,包含返回给请求者的响应信息
打开booktest/views.py文件,定义视图index如下
#coding:utf-8
from django.http import HttpResponse
def index(request):
return HttpResponse(“index”)
2.配置URLconf
查找视图的过程:请求者在浏览器地址栏中输入url,请求到网站后,获取url信息,然后与编写好的URLconf逐条匹配,如果匹配成功则调用对应的视图,如果所有的URLconf都没有匹配成功,则返回404错误
一条URLconf包括url规则、视图两部分
url规则使用正则表达式定义
视图就是在views.py中定义的视图
需要两步完成URLconf配置
1.在应用中定义URLconf
2.包含到项目的URLconf中
1.在booktest/应用下创建urls.py文件,定义代码如下
from django.conf.urls import url
from . import views
urlpatterns = [
url(r’^$’, views.index),
]
2.包含到项目中:打开test1/urls.py文件,为urlpatterns列表增加项如下
url(r’^’, include(‘booktest.urls’)),
test1/urls.py文件完整代码如下
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r’^admin/’, include(admin.site.urls)),
url(r’^’, include(‘booktest.urls’)),
]
请求访问
视图和URLconf都定义好了,接下来在浏览器地址栏中输入网址
http://127.0.0.1:8000/
网页显示效果如下图,视图被成功执行了
请求视图
模板
如何向请求者返回一个漂亮的页面呢?肯定需要用到html、css,如果想要更炫的效果还要加入js,问题来了,这么一堆字段串全都写到视图中,作为HttpResponse()的参数吗?这样定义就太麻烦了吧,因为定义字符串是不会出任何效果和错误的,如果有一个专门定义前端页面的地方就好了
解决问题的技术来了:模板
在Django中,将前端的内容定义在模板中,然后再把模板交给视图调用,各种漂亮、炫酷的效果就出现了
创建模板
为应用booktest下的视图index创建模板index.html,目录结构如下图:
模板目录
设置查找模板的路径:打开test1/settings.py文件,设置TEMPLATES的DIRS值
‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)],
查找模板目录
定义模板
打开templtes/booktest/index.html文件,定义代码如下
在模板中输出变量语法如下,变量可能是从视图中传递过来的,也可能是在模板中定义的
{{变量名}}
在模板中编写代码段语法如下
{%代码段%}
定义模板内容如下
{{title}}
{%for i in list%} {{i}}{%endfor%} 视图调用模板 调用模板分为三步骤 1.找到模板 2.定义上下文 3.渲染模板 打开booktst/views.py文件,调用上面定义的模板文件 #coding:utf-8
from django.http import HttpResponse
from django.template import loader,RequestContext
def index(request):
# 1.获取模板
template=loader.get_template(‘booktest/index.html’)
# 2.定义上下文
context=RequestContext(request,{‘title’:‘图书列表’,‘list’:range(10)})
# 3.渲染模板
return HttpResponse(template.render(context))
打开浏览器刷新页面,显示效果如下图
查找模板目录
视图调用模板简写
视图调用模板都要执行以上三部分,于是Django提供了一个函数render封装了以上代码
方法render包含3个参数
第一个参数为request对象
第二个参数为模板文件路径
第三个参数为字典,表示向模板中传递的上下文数据
打开booktst/views.py文件,调用render的代码如下
#coding:utf-8
from django.shortcuts import render
def index(request):
context={‘title’:‘图书列表’,‘list’:range(10)}
return render(request,‘booktest/index.html’,context)
项目完成
基本知识点都学完了,接下来完成示例项目
现在还需要的代码包括三个方面,三个方面顺序不分先后
1.定义视图
2.定义URLconf
3.定义模板
定义视图
编写booktest/views.py文件如下
from django.shortcuts import render
from models import BookInfo
#首页,展示所有图书
def index(reqeust):
#查询所有图书
booklist = BookInfo.objects.all()
#将图书列表传递到模板中,然后渲染模板
return render(reqeust, ‘booktest/index.html’, {‘booklist’: booklist})
#详细页,接收图书的编号,根据编号查询,再通过关系找到本图书的所有英雄并展示
def detail(reqeust, id):
#根据图书编号对应图书
book = BookInfo.objects.get(pk=id)
#将图书信息传递到模板中,然后渲染模板
return render(reqeust, ‘booktest/detail.html’, {‘book’: book})
定义URLconf
编写booktest/urls.py文件如下
from django.conf.urls import url
#引入视图模块
from . import views
urlpatterns = [
#配置首页url
url(r’^KaTeX parse error: Expected 'EOF', got '#' at position 22: …ws.index), #̲配置详细页url,\d+表示多…’,views.detail),
]
定义模板
编写templates/booktest/index.html文件如下
图书列表
- {#遍历图书列表#} {%for book in booklist%}
- {#输出图书名称,并设置超链接,链接地址是一个数字#} {{book.btitle}}
- {%endfor%}
{{book.btitle}}
- {#通过关系找到本图书的所有英雄,并遍历#} {%for hero in book.heroinfo_set.all%} {#输出英雄的姓名及描述#}
- {{hero.hname}}---{{hero.hcontent}}
- {%endfor%}