12.3 APP
12.31 创建APP
一个Django项目可以分为很多个APP,用来隔离不同功能模块的代码
用命令行创建一个APP:
python3 manage.py startapp app01
创建好APP,记得告诉Django,app的名字,在settings.py中添加:
INSTALLED_APPS =
[
'
django.contrib.admin
'
,
'
django.contrib.auth
'
,
'
django.contrib.contenttypes
'
,
'
django.contrib.sessions
'
,
'
django.contrib.messages
'
,
'
django.contrib.staticfiles
'
,
'
app01
'
,
#
或者'app01.apps.App01Config',
]
12.32 Django中的ORM
Django项目使用MySQL数据库
1.在Django项目的 settings.py 文件中,配置数据库连接信息: 告诉Django连接哪个数据库
DATABASES =
{
"
default
"
: {
"
ENGINE
"
:
"
django.db.backends.mysql
"
,
"
NAME
"
:
"
db6
"
,
#
需要自己手动先创建数据库
"
USER
"
:
"
root
"
,
"
PASSWORD
"
:
""
,
"
HOST
"
:
"
127.0.0.1
"
,
"
PORT
"
: 3306
}
}
2.Django默认使用的是 MySQLdb模块 连接数据库,但 MySQLdb在python3中不支持,所以:
在与
Django项目同名的文件夹的
__init__
.py
文件中写如下代码,
告诉Django使用pymysql模块连接MySQL数据库代替MySQLdb:
import
pymysql
pymysql.install_as_MySQLdb()
3.在 app/models.py 文件中定义类,一定要继承 models.Model
from
django.db
import
models
class
User(models.Model):
id
= models.AutoField(primary_key=True)
#
自增主键
name = models.CharField(max_length=16)
#
varchar(16)
pwd = models.CharField(max_length=128)
#
varchar(128)
#
出版社
class
Publisher(models.Model):
id
= models.AutoField(primary_key=True)
#
自增主键
name = models.CharField(max_length=16)
#
varchar(16) # 出版社名称
#
def __str__(self): #定义__str__是在打印表的对象时可以看到每一行的字段
#
return (self.id,self.name)
#
书籍
class
Book(models.Model):
id
= models.AutoField(primary_key=True)
#
自增的主键
title = models.CharField(max_length=32)
#
书籍名称 varchar(32)
publisher = models.ForeignKey(to=
"
Publisher
"
)
#
外键关联Publisher这张表
#
作者
class
Author(models.Model):
id
= models.AutoField(primary_key=
True)
name
= models.CharField(max_length=16
)
books
= models.ManyToManyField(to=
"
Book
"
)
#
ORM创建多对多字段,会自动在数据库中创建第三张表 id Author_id、Book_id
用命令行执行创建表的操作:
1. python3 manage.py makemigrations -->
将models.py的修改登记到小本本上
2. python3 manage.py migrate --> 将修改翻译成SQL语句,去数据库执行
4.在app/views.py文件中写urls.py中 /publisher_list/ 的对应函数 publisher_list ; /add_publisher/ 的对应函数 add_publisher
urls.py中的对应关系:
from
django.conf.urls
import
url
from
django.contrib
import
admin
from
app01
import
views
#
对应关系
urlpatterns =
[
url(r
'
^admin/
'
, admin.site.urls),
url(r
'
^login/
'
, views.login),
url(r
'
^publisher_list/
'
, views.publisher_list),
#
展示出版社列表
url(r
'
^add_publisher/
'
, views.add_publisher),
#
添加出版社
url(r
'
^delete_publisher/
'
, views.delete_publisher),
#
删除出版社
url(r
'
^edit_publisher/
'
, views.edit_publisher),
#
编辑出版社
url(r
'
^book_list/
'
, views.book_list),
#
书籍列表
url(r
'
^add_book/
'
, views.add_book),
#
添加书籍
url(r
'
^delete_book/
'
, views.delete_book
#
删除书籍
url(r
'
^edit_book/
'
, views.edit_book),
#
编辑书籍
url(r
'
^author_list/
'
, views.author_list),
#
作者列表
url(r
'
^add_author/
'
, views.add_author),
#
添加作者
url(r
'
^delete_author/
'
, views.delete_author),
#
删除作者
url(r
'
^edit_author/
'
, views.edit_author),
#
编辑作者
url(r
'
^$
'
, views.publisher_list)
#
以上对应关系都找不到,就匹配出版社页面
]
app/views.py:
12.321 有关出版社的函数逻辑
from
django.shortcuts
import
HttpResponse, render, redirect
from
app01
import
models
#
显示出版社列表
def
publisher_list(request):
ret
= models.Publisher.objects.all()
#
从数据库中取出所有的数据对象列表
#
print(ret)
return
render(request,
"
publisher_list.html
"
, {
"
publisher_list
"
: ret})
#
添加出版社函数
def
add_publisher(request):
#
根据请求方法的不同,要做不同的事情,add_publisher.html使用POST方法
if
request.method ==
"
POST
"
:
#
request.method获取的是请求的方法(GET、POST...必须是大写)
#
request.POST(字典)获取POST提交过来的全部数据
new_publisher_name = request.POST.get(
"
publisher_name
"
)
models.Publisher.objects.create(name
=new_publisher_name)
#
创建对象并封装属性(插入一行数据)
#
或者自己用类实例化一个对象:obj=models.Publisher(name=new_publisher_name) obj.save()
#
让用户跳转到publisher_list.html,显示新增数据后的publisher_list.html页面
return
redirect(
"
/publisher_list/
"
)
return
render(request,
"
add_publisher.html
"
)
#
删除出版社函数
def
delete_publisher(request):
#
print(request.method)
#
print(request.GET)
delete_id = request.GET.get(
"
id
"
)
#
拿到用户要删除的出版社的id值
#
print(delete_id)
obj = models.Publisher.objects.get(id=delete_id)
#
根据id值得到对象
obj.delete()
#
将数据删除
return
redirect(
"
/publisher_list/
"
)
#
让用户重新访问publisher_list.html更新页面
#
编辑出版社的函数
def
edit_publisher(request):
#
edit_id = request.GET.get("id")如果用户提交使用URL拼接id,那么从URL里面取id参数request.GET.get("id")
if
request.method ==
"
POST
"
:
#
如果是post请求,表示用户已经编辑好了,向服务端提交修改后的新数据
edit_id = request.POST.get(
"
edit_id
"
)
#
拿到已经修改的出版社id
new_name = request.POST.get(
"
name
"
)
#
拿到修改之后的出版社的名字
edit_obj = models.Publisher.objects.get(id=edit_id)
#
通过id找到数据行对象
edit_obj.name =
new_name
edit_obj.save()
#
保存修改,提交数据库
return
redirect(
"
/publisher_list/
"
)
#
修改成功,让用户跳转到出版社列表页面,更新页面
#
如果不是post请求,则返回edit_publisher.html页面给用户修改出版社
edit_id = request.GET.get(
"
id
"
)
#
先获取编辑的出版社的ID值
obj = models.Publisher.objects.get(id=edit_id)
#
根据id值去数据库找对应的行数据对象
return
render(request,
"
edit_publisher.html
"
, {
"
publisher
"
: obj})
#
将数据想要编辑的出版社显示出来,等待用户编辑
templates/publisher_list.html:
<
body
>
<
table
border
="1"
>
<
thead
>
<
tr
>
<
th
>
#
th
>
<
th
>
出版社名称
th
>
tr
>
thead
>
<
tbody
>
{% for publisher in publisher_list %}
<
tr
>
<
td
>
{{ publisher.id }}
td
>
#{{ forloop.counter }计数表格中的数据条数,从而删除后更新id
<
td
>
{{ publisher.name }}
td
>
<
td
class
="text-center"
>
<
a
class
="btn btn-info btn-sm"
href
="/edit_publisher/?id={{ publisher.id }}"
>
<
i
class
="fa fa-pencil fa-fw"
aria-hidden
="true"
>
i
>
编辑
a
>
<
a
class
="btn btn-danger btn-sm"
href
="/delete_publisher/?id={{ publisher.id }}"
>
<
i
class
="fa fa-trash-o fa-fw"
aria-hidden
="true"
>
i
>
删除
a
>
td
>
tr
>
{% endfor %}
tbody
>
table
>
body
>
templates/add_publisher.html:
<
body
>
<
h1
>
添加新的出版社
h1
>
<
form
action
="/add_publisher/"
method
="post"
>
<
input
type
="text"
name
="publisher_name"
>
<
input
type
="submit"
value
="提交"
>
form
>
body
>
templates/edit_publisher.html:
#如果#action="/edit_publisher/?id={{ publisher.id }}"那么就从URL中用request.GET.get()取id参数
<
form
class
="form-horizontal"
action
="/edit_publisher/"
method
="post"
>
<
input
type
="text"
name
="edit_id"
value
="{{ publisher.id }}"
class
="hide"
>
#将获取id的input框隐藏
<
div
class
="form-group"
>
<
label
for
="inputEmail3"
class
="col-sm-3 control-label"
>
出版社名称
label
>
<
div
class
="col-sm-9"
>
<
input
type
="text"
class
="form-control"
id
="inputEmail3"
name
="name"
placeholder
="出版社名称"
value
="{{ publisher.name }}"
>
#提交出版社名称
div
>
div
>
<
div
class
="form-group"
>
<
div
class
="col-sm-offset-3 col-sm-9"
>
<
button
type
="submit"
class
="btn btn-default"
>
提交
button
>
div
>
div
>
form
>
12.322 有关书籍的函数逻辑
from
django.shortcuts
import
HttpResponse, render, redirect
from
app01
import
models
#
书籍列表函数
def
book_list(request):
ret
= models.Book.objects.all()
#
去数据库查询所有的书籍对象
return
render(request,
"
book_list.html
"
, {
"
book_list
"
: ret})
#
将数据填充到页面上,发送给客户端
#
添加书籍函数
def
add_book(request):
if
request.method ==
"
POST
"
:
#
如果是POST请求表示用户新添加了一本书籍和关联的出版社
book_name = request.POST.get(
"
book_name
"
)
#
添加新书籍的名称
publisher_id = request.POST.get(
"
publisher_id
"
)
#
添加新书籍关联的出版社id值
models.Book.objects.create(title=book_name, publisher_id=
publisher_id)
#
publisher_obj = models.Publisher.objects.get(id=publisher_id)#根据id值先找到关联的出版社对象
#
models.Book.objects.create(title=book_name, publisher=publisher_obj)
return
redirect(
"
/book_list/
"
)
#
创建成功,让用户跳转到书籍列表页面,刷新数据
#
取到所有的出版社数据,在页面上渲染成select标签,供用户选择
ret =
models.Publisher.objects.all()
return
render(request,
"
add_book.html
"
, {
"
publisher_list
"
: ret})
#
删除书籍的函数
def
delete_book(request):
delete_book_id
= request.GET.get(
"
id
"
)
#
从URL里面取到要删除的书籍的ID
models.Book.objects.get(id=delete_book_id).delete()
#
去数据库中删除
return
redirect(
"
/book_list/
"
)
#
删除成功,跳转到书籍列表页面,刷新数据
#
编辑书籍的函数
def
edit_book(request):
if
request.method ==
"
POST
"
:
#
如果是POST请求 表名是用户修改好了数据,向后端提交了
new_book_title = request.POST.get(
"
book_title
"
)
#
取用户提交过来的数据
new_publisher_id = request.POST.get(
"
publisher_id
"
)
book_id
= request.GET.get(
"
id
"
)
#
获取URL中的当前编辑图书的id
book_obj = models.Book.objects.get(id=book_id)
#
根据id取出要编辑的书籍对象
book_obj.title
=
new_book_title
book_obj.publisher_id
=
new_publisher_id
book_obj.save()
#
将修改保存到数据库
return
redirect(
"
/book_list/
"
)
#
修改完之后让用户跳转回书籍列表页面
#
返回一个让用户编辑数据的页面
edit_book_id = request.GET.get(
"
id
"
)
#
取编辑的书籍的id值
edit_book_obj = models.Book.objects.get(id=edit_book_id)
#
取到要编辑的书籍对象
publisher_list = models.Publisher.objects.all()
#
去数据库查询目前所有的出版社数据
return
render(request,
"
edit_book.html
"
,{
"
book
"
: edit_book_obj,
"
publisher_list
"
:publisher_list})
templates/book_list.html:
<
table
class
="table table-striped table-bordered"
>
<
thead
>
<
tr
>
<
th
>
序号
th
>
<
th
>
书籍名称
th
>
<
th
>
出版社名称
th
>
<
th
>
操作
th
>
tr
>
thead
>
<
tbody
>
{% for book in book_list %}
<
tr
>
<
td
>
{{ forloop.counter }}
td
>
<
td
>
{{ book.title }}
td
>
<
td
>
{{ book.publisher.name}}
td
>
# book.publisher拿到的是外键(id)关联的出版社的行数据对象
<
td
class
="text-center"
>
<
a
class
="btn btn-info btn-sm"
href
="/edit_book/?id={{ book.id }}"
>
<
i
class
="fa fa-pencil fa-fw"
aria-hidden
="true"
>
i
>
编辑
a
>
<
a
class
="btn btn-danger btn-sm"
href
="/delete_book/?id={{ book.id }}"
>
<
i
class
="fa fa-trash-o fa-fw"
aria-hidden
="true"
>
i
>
删除
a
>
td
>
tr
>
{% endfor %}
tbody
>
table
>
templates/add_book.html:
<
form
class
="form-horizontal"
action
="/add_book/"
method
="post"
>
<
div
class
="form-group"
>
<
label
for
="inputEmail3"
class
="col-sm-3 control-label"
>
书籍名称
label
>
<
div
class
="col-sm-9"
><
input
type
="text"
class
="form-control"
id
="inputEmail3"
name
="book_name"
placeholder
="书籍名称"
>
div
>
div
>
<
div
class
="form-group"
>
<
label
for
="inputEmail3"
class
="col-sm-3 control-label"
>
出版社名称
label
>
<
div
class
="col-sm-9"
>
<
select
class
="form-control"
name
="publisher_id"
>
{% for publisher in publisher_list %}
<
option
value
="{{ publisher.id }}"
>
{{ publisher.name }}
option
>
{% endfor %}
select
>
div
>
div
>
<
div
class
="form-group"
>
<
div
class
="col-sm-offset-3 col-sm-9"
><
button
type
="submit"
class
="btn btn-default"
>
提交
button
>
div
>
div
>
form
>
templates/edit_book.html:
#action=""此处使用默认URL,即继承之前的/edit_book/?id={{ book.id }}
#或者#action="/edit_publisher/?id={{ publisher.id }}"那么就从URL中用request.GET.get()取id参数
<
form
class
="form-horizontal"
action
=""
method
="post"
>
#隐藏要编辑的书,发送id到后端,为了在后端找到要修改的图书,方便修改
#
<
input
type
="text"
value
="{{ book.id }}"
name
="book_id"
class
="hide"
>
#预先在输入框和下拉框显示要修改的图书名和出版社名
<
div
class
="form-group"
>
<
label
for
="inputEmail3"
class
="col-sm-3 control-label"
>
书籍名称
label
>
<
div
class
="col-sm-9"
>
<
input
type
="text"
class
="form-control"
id
="inputEmail3"
name
="book_title"
value
="{{ book.title }}"
placeholder
="书籍名称"
>
div
>
div
>
<
div
class
="form-group"
>
<
label
for
="inputEmail3"
class
="col-sm-3 control-label"
>
出版社名称
label
>
<
div
class
="col-sm-9"
>
<
select
class
="form-control"
name
="publisher_id"
>
# 如果当前循环到的出版社和书关联的出版社相等,则添加selected,表示预先选中的
{% for publisher in publisher_list %}
{% if publisher == book.publisher %}
<
option
value
="{{ publisher.id }}"
selected
>
{{ publisher.name }}
option
>
{% else %}
<
option
value
="{{ publisher.id }}"
>
{{ publisher.name }}
option
>
{% endif %}
{% endfor %}
select
>
div
>
div
>
<
div
class
="form-group"
>
<
div
class
="col-sm-offset-3 col-sm-9"
>
<
button
type
="submit"
class
="btn btn-default"
>
提交
button
>
div
>
div
>
form
>
12.323 有关作者的函数逻辑
#
作者列表函数
def
author_list(request):
authors
= models.Author.objects.all()
#
从数据库中查询所有的作者数据,在页面上展示出来
#
author_obj = models.Author.objects.get(id=1)
#
print(author_obj.books.all()) 表示id=1的作者写的所有书的对象
return
render(request,
"
author_list.html
"
, {
"
author_list
"
: authors})
#
添加作者函数
def
add_author(request):
if
request.method ==
"
POST
"
:
new_author_name
= request.POST.get(
"
author_name
"
)
#
拿到新的作者姓名
models.Author.objects.create(name=new_author_name)
#
去数据库中创建一个新的作者记录
return
redirect(
"
/author_list/
"
)
#
创建好作者之后,让用户跳转到作者列表页面
#
返回一个页面,让用户填写新的作者信息
return
render(request,
"
add_author.html
"
)
#
删除作者函数
def
delete_author(request):
delete_author_id
= request.GET.get(
"
id
"
)
#
从URL里面取到要删除的作者的ID
models.Author.objects.get(id=delete_author_id).delete()
#
去数据库中找到该作者并删除
return
redirect(
"
/author_list/
"
)
#
删除成功后 跳转回作者列表页面
#
编辑作者函数
def
edit_author(request):
if
request.method ==
"
POST
"
:
#
如果发送的是POST请求,应该拿到用户提交的数据
edit_author_id = request.POST.get(
"
author_id
"
)
#
编辑的作者id
#
取新名字和新的书籍id
new_author_name = request.POST.get(
"
author_name
"
)
new_book_ids
= request.POST.getlist(
"
book_ids
"
)
#
如果提交过来的数据是多个值(多选的select/多选的checkbox)则使用getlist取列表
#
print(request.POST)
#
print(edit_author_id, new_author_name, new_book_ids)
#
去编辑作者以及对应的书籍
edit_author_obj = models.Author.objects.get(id=edit_author_id)
#
拿到编辑的作者对象
edit_author_obj.name = new_author_name
#
修改作者姓名
edit_author_obj.save()
#
修改作者写的书籍
edit_author_obj.books.set(new_book_ids)
#
通过新书id更换作者对应的书籍,并提交数据库
return
redirect(
"
/author_list/
"
)
#
修改完成之后,跳转到作者列表页面
#
返回一个页面,让用户编辑
edit_author_id = request.GET.get(
"
id
"
)
#
从URL里面取到要编辑作者的id参数
edit_author_obj = models.Author.objects.get(id=edit_author_id)
#
取到要编辑的作者对象
book_list = models.Book.objects.all()
#
获取所有的书籍对象信息
return
render(request,
"
edit_author.html
"
,{
"
author
"
: edit_author_obj,
templates/author_list.html:
<
div
class
="col-md-3 col-sm-6 pull-right add-btn"
>
<
button
data-target
="#myModal"
data-toggle
="modal"
class
="btn btn-success pull-right"
>
新增
button
>
<
a
href
="/add_author/"
class
="btn btn-info pull-right"
>
新页面添加
a
>
div
>
<
table
class
="table table-striped table-bordered"
>
<
thead
>
<
tr
>
<
th
>
序号
th
>
<
th
>
作者姓名
th
>
<
th
>
著作
th
>
<
th
>
操作
th
>
tr
>
thead
>
<
tbody
>
{% for author in author_list %}#{"author_list": authors}
<
tr
>
<
td
>
{{ forloop.counter }}
td
>
<
td
>
{{ author.name }}
td
>
<
td
>
#在这一列展示这个作者关联的所有的书籍
{% for book in author.books.all %}#书籍对象的列表
{% if forloop.last %}
《{{ book.title }}》
{% else %}
《{{ book.title }}》,
{% endif %}
{% empty %}
暂无著作
{% endfor %}
td
>
<
td
class
="text-center"
>
<
a
class
="btn btn-info btn-sm"
href
="/edit_author/?id={{ author.id }}"
>
<
i
class
="fa fa-pencil fa-fw"
aria-hidden
="true"
>
i
>
编辑
a
>
<
a
class
="btn btn-danger btn-sm"
href
="/delete_author/?id={{ author.id }}"
>
<
i
class
="fa fa-trash-o fa-fw"
aria-hidden
="true"
>
i
>
删除
a
>
td
>
tr
>
{% endfor %}
tbody
>
table
>
templates/add_author.html:
<
form
class
="form-horizontal"
action
="/add_author/"
method
="post"
>
<
div
class
="form-group"
>
<
label
for
="inputEmail3"
class
="col-sm-3 control-label"
>
作者姓名
label
>
<
div
class
="col-sm-9"
>
<
input
type
="text"
class
="form-control"
id
="inputEmail3"
name
="author_name"
placeholder
="作者姓名"
>
div
>
div
>
<
div
class
="form-group"
>
<
div
class
="col-sm-offset-3 col-sm-9"
>
<
button
type
="submit"
class
="btn btn-default"
>
提交
button
>
div
>
div
>
form
>
templates/edit_author.html:
<
form
class
="form-horizontal"
action
=""
method
="post"
>
#action=""默认转到当前URL
<
input
type
="text"
value
="{{ author.id }}"
name
="author_id"
class
="hide"
>
<
div
class
="form-group"
>
<
label
for
="inputEmail3"
class
="col-sm-3 control-label"
>
作者姓名
label
>
<
div
class
="col-sm-9"
>
<
input
type
="text"
class
="form-control"
id
="inputEmail3"
name
="author_name"
value
="{{ author.name }}"
placeholder
="作者姓名"
>
div
>
div
>
<
div
class
="form-group"
>
<
label
for
="inputEmail3"
class
="col-sm-3 control-label"
>
著作
label
>
<
div
class
="col-sm-9"
>
<
select
class
="form-control"
name
="book_ids"
multiple
>
{% for book in book_list %} #book_list 所有的书籍对象
#author:要编辑的作者,author.books.all:要编辑的作者的所有书籍对象
{% if book in author.books.all %} # 如果当前这本书在作者写的书里面
<
option
value
="{{ book.id }}"
selected
>
{{ book.title }}
option
>
{% else %}
<
option
value
="{{ book.id }}"
>
{{ book.title }}
option
>
{% endif %}
{% endfor %}
select
>
div
>
div
>
<
div
class
="form-group"
>
<
div
class
="col-sm-offset-3 col-sm-9"
>
<
button
type
="submit"
class
="btn btn-default"
>
提交
button
>
div
>
div
>
form
>

