标签:Book 进阶 管理 Python 数据库 models book date name
文章目录
本文暂时用SQLite,方便调试,后期更换为Mysql
1.项目数据库的管理
1.1 创建数据库模型
- 数据库选择SQLite,基于OR面向对象的方式映射,进行增删改查
- 本示例完成“图书-英雄”信息的维护,需要存储两种数据:图书、英雄
- 图书表结构设计: 表名: Book
- 图书名称: title
- 图书发布时间: pub_date
- 英雄表结构设计: 表名: Hero
- 英雄姓名: name
- 英雄性别: gender
- 英雄简介: hcontent
- 所属图书: hbook
图书-英雄的关系为一对多
在bookApp下的models.py中编辑:
定义数据库模型
在设置中添加要实现的app,设置子应用:
为新应用设置迁移脚本:python manage.py makemigrations
将迁移脚本应用至数据库中:python manage.py migrate
刷新上一篇中建好的数据库:
设置一对多:
将迁移脚本应用至数据库中:python manage.py migrate
将迁移脚本应用至数据库中:python manage.py migrate
刷新数据库出现刚才新建的表:
总结:对项目的数据库模型操作
- 若是Mysql数据库,安装完Mysql后还需要更改配置文件,暂时不需要更改;
- 创建对应的数据库模型,在models.py中编写。通过ORM映射的关系实现,通过面向对象的方式进行增删改查;
- 具体就是创建数据库模型,将生成的子应用加到配置文件中,然后生成迁移脚本,以及应用到数据库中,再进行检查是否成功添加
1.2 数据库模型基本操作(增删改查)
- 本节针对书籍做增删改查的操作,下一节对书中的人物做操作;
- 首先在terminal中安装一个界面更友好的解释器(不装也行):
pip install ipython
- 进入交互式的Python shell,并使用 Django 提供的免费 API:
python manage.py shell
1.2.1 导入数据库
In [1]: from bookApp.models import Book ,Hero
In [2]: # 查看操作
In [3]: Book.objects.all() #查看数据集,此时还未添加,所以返回为空
Out[3]: <QuerySet []>
In [4]: Hero.objects.all() #与上同理
Out[4]: <QuerySet []>
1.2.2 增加数据信息
在数据库中增加一本书叫西游记,并且包含发布日期:
In [2]: # 查看操作
In [3]: Book.objects.all()
Out[3]: <QuerySet []>
In [4]: Hero.objects.all()
Out[4]: <QuerySet []>
In [5]: # 2.增加数据信息
In [6]: # 数据库表中的一条记录对应OOP里面的一个object
In [7]: b1 = Book()
In [8]: b1.name = "西游记"
In [9]: from datetime import date
In [10]: d1 = date(2000,1,4)
In [11]: b1.pub_date = d1
In [12]: b1.save()
In [13]: Book.objects.all()
Out[13]: <QuerySet [<Book: Book object (1)>]>
最后的结果查看中虽然能看到包含有一本书,但是不能看到书名,在此调整应用models.py文件:
from django.db import models
# Create your models here.
#类对应数据库表,表名称默认为bookApp_book.
class Book(models.Model):
#属性对应数据库表的列名,默认会添加id这一列
name = models.CharField(max_length=40,verbose_name="书籍名称")
pub_date = models.DateField(verbose_name="出版日期")
#魔术方法,字符串友好展示,便于调试代码
def __str__(self):
return self.name
#类对应数据库表,表名称默认为bookApp_hero
class Hero(models.Model):
# 属性对应数据库表的列名,默认会添加id这一列
gender_choice = [
(1,'男'),
(2,'女')
]
name = models.CharField(max_length=20, verbose_name="人物名称")
#性别只能选择男(1)或者女(2)
gender = models.IntegerField(choices=gender_choice, verbose_name="性别")
content = models.TextField(max_length=1000, verbose_name="人物描述")
# 外键关联,如果删除书籍时,相关hero对应的书籍设置为空
Book = models.ForeignKey(Book,on_delete=models.SET_NULL,null=True, verbose_name="书籍id")
# 魔术方法,字符串友好展示,便于调试代码
def __str__(self):
return self.name
此处因为新加了功能,所以需要重新启动shell:
In [1]: from bookApp.models import Book,Hero
In [2]: Book.objects.all()
Out[2]: <QuerySet [<Book: 西游记>]>
再增加一个:
from bookApp.models import Book,Hero
In [2]: Book.objects.all()
Out[2]: <QuerySet [<Book: 西游记>]>
In [3]: from datetime import date
In [5]: b2 = Book(name="红楼梦",pub_date=date(1998,4,1))
In [6]: b2.save()
In [7]: Book.objects.all()
Out[7]: <QuerySet [<Book: 西游记>, <Book: 红楼梦>]>
步骤:
- 在terminal中进入Django的交互式shell:
python manage.py shell
- 导入时间模块(需要添加书籍的导入时间):
from datetime import date
- 按照models中定义的格式增加新的书籍信息:
b2 = Book(name="红楼梦",pub_date=date(1998,4,1))
- 保存
b2.save()
- 查看:
Book.objects.all()
1.2.3 查看数据库信息
# 3.根据条件搜索并查看
In [9]: Book.objects.filter(name="西游记")
Out[9]: <QuerySet [<Book: 西游记>]>
In [11]: b1 = Book.objects.filter(name="西游记")
In [12]: b1
Out[12]: <QuerySet [<Book: 西游记>]>
In [13]: b1 = Book.objects.filter(name="西游记").first()
In [14]: b1
Out[14]: <Book: 西游记>
In [15]: type(b1)
Out[15]: bookApp.models.Book
In [16]: b1.pub_date
Out[16]: datetime.date(2000, 1, 4)
注:b1 = Book.objects.filter(name="西游记")
该命令返回的是QuerySet,是一个结果集,若要返回一个对象,则b1 = Book.objects.filter(name="西游记").first()
1.2.4 删除
In [17]: # 4.删除
In [18]: b1
Out[18]: <Book: 西游记>
In [19]: b1.delete()
Out[19]: (1, {'bookApp.Book': 1})
In [20]: Book.objects.all()
Out[20]: <QuerySet [<Book: 红楼梦>]>
1.3 添加关联对象
# 创建关联对象
In [23]: book = Book(name="倚天屠龙记",pub_date=date(2000,1,1))
In [24]: book.save()
In [25]: hero1 = Hero(name="周芷若",gender=2,content="info...")
In [26]: hero1.save()
In [27]: Hero.objects.all()
Out[27]: <QuerySet [<Hero: 周芷若>]>
In [29]: hero1.Book = book
In [31]: hero1.save()
In [33]: hero1.book_id
Out[33]: <Book: 倚天屠龙记>
In [41]: book.hero_set.all()
Out[41]: <QuerySet [<Hero: 周芷若>]>
总结:
- 利用Book类创建book实例,创建完进行保存:
book.save()
; - 利用Hero类创建hero1实例,创建完保存
hero1.save()
; - 关联:
hero1.Book=book
,关联完成后保存hero1.save()
; - 获得关联集合:返回当前book对象的所有hero:
book.hero_set.all()
注:另一种办法
有一个 Hero 存在,必须要有一个 Book 对象,提供了创建关联的数据:
book.hero_set.create(name="张无忌",
gender=1,
content="...")
查询:
对书名的查找:
In [52]: books = Book.objects.filter(name__contains="夏")
In [53]: books
Out[53]: <QuerySet [<Book: 夏洛特烦恼>]>
按发布日期查找(查询今天之前发布的书籍):
In [54]: books = Book.objects.filter(pub_date__lt=date.today())
In [55]: books
Out[55]: <QuerySet [<Book: 红楼梦>, <Book: 倚天屠龙记>, <Book: 夏洛特烦恼>]>
更多查询参考官方文档:
Django3.1官方文档查询部分
2. 自定义模型加入后台管理
上一节已经介绍过管理员对于用户的管理,在此添加对书籍的管理
2.1 自定义模型(Book类和Hero类)加入后台管理
打开 bookApp/admin.py 文件,注册模型:
from django.contrib import admin
from bookApp.models import Book,Hero
# Register your models here.
admin.site.register([Book,Hero])
网页图形化管理会更加直观简单
2.2 界面内容汉化
首先修改应用的models.py文件:
from django.db import models
# Create your models here.
#类对应数据库表,表名称默认为bookApp_book.
class Book(models.Model):
#属性对应数据库表的列名,默认会添加id这一列
name = models.CharField(max_length=40,verbose_name="书籍名称")
pub_date = models.DateField(verbose_name="出版日期")
#魔术方法,字符串友好展示,便于调试代码
def __str__(self):
return self.name
class Meta:
#verbose_name即为后台管理名称
verbose_name = "图书管理"
#复数时名称
verbose_name_plural = verbose_name
#类对应数据库表,表名称默认为bookApp_hero
class Hero(models.Model):
# 属性对应数据库表的列名,默认会添加id这一列
gender_choice = [
(1,'男'),
(2,'女')
]
name = models.CharField(max_length=20, verbose_name="人物名称")
#性别只能选择男(1)或者女(2)
gender = models.IntegerField(choices=gender_choice, verbose_name="性别")
content = models.TextField(max_length=1000, verbose_name="人物描述")
# 外键关联,如果删除书籍时,相关hero对应的书籍设置为空
Book = models.ForeignKey(Book,on_delete=models.SET_NULL,null=True, verbose_name="书籍id")
# 魔术方法,字符串友好展示,便于调试代码
def __str__(self):
return self.name
class Meta:
#verbose_name即为后台管理名称
verbose_name = "人物管理"
#复数时名称
verbose_name_plural = verbose_name
浏览器中观察效果:
更多模型Meta选项参考官方文档:模型 Meta 选项
2.3 自定义管理页面
2.3.1 列表页展示
- Django 提供了 admin.ModelAdmin 类
- 通过定义 ModelAdmin 的子类,来定义模型在 Admin 界面的显示方式
首先在图书管理里添加发布日期,修改admin.py文件:
class BookAdmin(admin.ModelAdmin):
list_display = ('id','name','pub_date')
admin.site.register(Book, BookAdmin)
admin.site.register(Hero)
注:此处class类定义中使用元组括号,否则报错
结果如下:
同理再添加一个筛选器,按发布日期筛选:
class BookAdmin(admin.ModelAdmin):
list_display = ('id','name','pub_date')
list_filter = ['pub_date']
同理,添加搜索功能,和每页显示最多5条功能:
class BookAdmin(admin.ModelAdmin):
list_display = ('id','name','pub_date')
list_filter = ['pub_date']
search_fields = ['title']
list_per_page = 5
此外,进一步设置点击可以自动链接功能:
class BookAdmin(admin.ModelAdmin):
list_display = ('id','name','pub_date')
list_filter = ['pub_date']
search_fields = ['title']
list_display_links = ['id','name']
list_per_page = 5
2.3.2 修改添加页属性
给Hero添加选项
class HeroAdmin(admin.ModelAdmin):
list_display = ('id','name','gender')
list_filter = ['gender']
search_fields = ['name','content']
list_display_links = ['name']
list_per_page = 5
admin.site.register(Book, BookAdmin)
admin.site.register(Hero,HeroAdmin)
增加和编辑页的设置:
class HeroAdmin(admin.ModelAdmin):
list_display = ('id','name','gender')
list_filter = ['gender']
search_fields = ['name','content']
list_display_links = ['name']
list_per_page = 5
#增加和编辑页的设置
fieldsets = [('必填信息', {'fields': ['name', 'book_id']}),
('选填信息', {'fields': ['gender', 'content']}), ]
生效前:
生效后:
关联对象:
from django.contrib import admin
from bookApp.models import Book,Hero
# Register your models here.
class HeroInline(admin.StackedInline):
model = Hero
extra = 3
class BookAdmin(admin.ModelAdmin):
list_display = ('id','name','pub_date')
list_filter = ['pub_date']
search_fields = ['title']
list_display_links = ['id','name']
list_per_page = 5
inlines = [HeroInline]
class HeroAdmin(admin.ModelAdmin):
list_display = ('id','name','gender')
list_filter = ['gender']
search_fields = ['name','content']
list_display_links = ['name']
list_per_page = 5
# #增加和编辑页的设置
# fieldsets = [('必填信息', {'fields': ['name', 'book_id']}),
# ('选填信息', {'fields': ['gender', 'content']}), ]
admin.site.register(Book, BookAdmin)
admin.site.register(Hero,HeroAdmin)
关于更多站点管理操作,参考官方文档
3. 前台管理
3.1 URLconf路由管理
- 在 Django 中,定义 URLconf 包括正则表达式、视图两部分 。
- Django 使用正则表达式匹配请求的URL,一旦匹配成功,则调用应用的视图 。
- 注意:只匹配路径部分,即除去域名、参数后的字符串 。
- 在主配置文件中添加子配置文件,使主 urlconf 配置连接到子模块的 urlconf 配置文件 。
主配置文件配置如下, 已经配置过, 可以忽略此步骤
# BookManage/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
# 当用户访问的url地址以book开头, 请访问bookApp.urls这个url配置文件进行匹配并执行对应 的视图函数.
url(r'^book/', include('bookApp.urls')),
]
bookApp 子应用的子配置文件如下:
# bookApp/urls.py
urlpatterns = [
# 当用户访问bookApp应用的主页时, 执行视图函数index,反向根据名称获取url地址;
url(r'^$', views.index, name='index'),
# 显示书籍的详情页
url(r'^([0-9]+)/$', views.detail, name='detail'),
]
3.2 视图函数处理业务逻辑
- 在 Django 中,视图对WEB请求进行回应( response )。
- 视图接收 reqeust 请求对象作为第一个参数,包含了请求的信息 。
- 视图函数就是一个Python函数,被定义在 views.py 中 。
- 定义完成视图后,需要配置 urlconf ,否则无法处理请求。
测试是否可以显示返回值:
from django.shortcuts import render
from django.http import HttpResponse
#Create your views here.
#视图:对用户的请求(request)进行业务逻辑操作,最终返回给用户一个响应(response)
def index(request):
#print("用户请求的路劲:",request.path)
books = Book.objects.all()
# html:
return HttpResponse(books)
可以显示,但是比较乱
3.2.1 html模板显示
在目录下的templates中新建一个文件夹book,在其中新建一个文件:index.html
修改views文件:
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
#视图:对用户的请求(request)进行业务逻辑操作,最终返回给用户一个响应(response)
from bookApp.models import Book
def index(request):
#print("用户请求的路劲:",request.path)
books = Book.objects.all()
# html:
#return HttpResponse(books)
#return HttpResponse('<h1 style="color:red">首页信息</h1>')
return render(request, 'book/index.html',{'books':books})
刷新后:
为了进一步展示从数据库中查询到的所有书籍,需要在此进一步加入一个模板引擎:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 style="color: blue ">图书管理系统</h1>
<ul>
{% for book in books %}
<li>{{ book.name }}</li>
{% endfor %}
</ul>
</body>
</html>
- ul为无序列表
- 两个{{}}中表示的是变量
总结:
当用户访问时:
- 主路由配置文件urls.py文件中指向子路由配置文件:
- 应用内的子路由配置文件指向views.index文件
- 进入该文件后,index接收用户的请求,从数据库中查询所有的信息,查到之后,租用一个
book/index.html
代码,此处根据查询的数据库信息的不同,显示的内容也不同,此步最后的过程称为渲染,即及那个上下文context{‘books’:books}填充到book/index.html代码的过程
3.2.2 显示书籍的详情页
编辑book下的子urls文件
from django.urls import path
from bookApp import views
urlpatterns = [
#当用户访问路径是book/,执行views.index视图函数,此步是由主路由转发而来
path(r'', views.index, name='index'),
#显示书籍的详情页,接收一个int值并复制给id
path(r'<str:id>',views.detail,name='detail'),
]
对于指定的views文件内编写detail函数:
def detail(request,id):
"""书籍详情页信息"""
book = Book.objects.filter(id=id).first()
pub_date = book.pub_date
heros = book.hero_set.all()
return render(request,'book/detail.html',
{'book': book,'heros': heros})
再编写租借的html函数,地址为:C:\Users\lylup\Desktop\python\day07\test\BookManager\templates\book\detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ book.name }}</h1>
<h1>{{ book.pub_date }}</h1>
<h1>{{ heros }}</h1>
</body>
</html>
在浏览器中测试结果:
3.3 模板管理实现好看的HTML页面(对上两步操作理论总结)
- 作为Web 框架, Django 需要一种很便利的方法以动态地生成HTML。最常见的做法是使用模板。
- 模板包含所需HTML 输出的静态部分,以及一些特殊的语法,描述如何将动态内容插入。
3.3.1 模板引擎配置
- 创建模板的目录如下图:
- 修改 BookManage/settings.py 文件,设置 TEMPLATES 的 DIRS 值
TEMPLATES = [
{ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 修改的部分,指定模板路径
'DIRS': [os.path.join(BASE_DIR, 'templates')],
# ..................
},
]
3.3.2 模板语法: 变量
- 变量输出语法
{ { var } }
- 当模版引擎遇到一个变量,将计算这个变量,然后将结果输出。
- 变量名必须由字母、数字、下划线(不能以下划线开头)和点组成。
- 当模版引擎遇到点("."),会按照下列顺序查询:
字典查询,例如: foo[“bar”]
属性或方法查询,例如: foo.bar
数字索引查询,例如: foo[bar] - 如果变量不存在, 模版系统将插入’’ (空字符串)。
3.3.4 模板语法: 常用标签
- 语法
{ % tag % }
- 作用
- 在输出中创建文本。
- 控制循环或逻辑。
- 加载外部信息到模板中。
for标签
{% for ... in ... %}
循环逻辑
{% endfor %}
if标签
{% if ... %}
逻辑1
{% elif ... %}
逻辑2
{% else %}
逻辑3
{% endif %}
comment标签
{% comment %}
多行注释
{% endcomment %}
include标签
加载模板并以标签内的参数渲染
{% include "base/left.html" %}
url :反向解析
{% url 'name' p1 p2 %}
csrf_token 标签
用于跨站请求伪造保护
{% csrf_token %}
3.4 常用html
3.4.1 标题标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>标题</h1>
<h2>标题</h2>
<h3>标题</h3>
<h4>标题</h4>
<h5>标题</h5>
<h6>标题</h6>
</body>
</html>
3.4.2 列表标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
/* 无序列表 */
<ul>
<li>book1</li>
<li>book2</li>
<li>book3</li>
<li>book4</li>
</ul>
/* 有序列表 */
<ol>
<li>book1</li>
<li>book2</li>
<li>book3</li>
<li>book4</li>
</ol>
</body>
</html>
3.4.3 图片标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img src="earth.JPG">
</body>
</html>
此处图像实际显示会保持原分辨率,此处结果进行了大幅缩放
3.4.4 链接标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="https://www.baidu.com">百度一下</a>
</body>
</html>
点击后跳转到百度
若要实现点击图片实现跳转,则改写为:
<a href="https://www.baidu.com">百度一下</a>
<a href="https://www.baidu.com"><img src="earth.JPG"></a>
3.4.5 表格标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<tr>
<td>主机名</td>
<td>IP</td>
</tr>
<tr>
<td>localhost</td>
<td>127.0.0.1</td>
</tr>
<tr>
<td>server1</td>
<td>127.0.0.1</td>
</tr>
</body>
</html>
3.4.6 表单标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form>
用户名:<input type="text" placeholder="username">
密码:<input type="password" placeholder="password">
<input type="submit" value="登录">
</form>>
</body>
</html>
3.5 改进index界面
在进入书籍首页时,可以点击书籍进入详情页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 style="color: blue ">图书管理系统</h1>
<ul>
{% for book in books %}
<li><a href="/book/{{ book.id }}/">{{ book.name }}</a>></li>
{% endfor %}
</ul>
</body>
</html>
4.Django的生命周期
- wsgi : 封装请求后交给后端的web框架( Flask、Django )。
- 请求中间件: 对请求进行校验或在请求对象中添加其他相关数据,例如: csrf、 request.session 。
- 路由匹配: 根据浏览器发送的不同 url 去匹配不同的视图函数。
- 视图函数: 在视图函数中进行业务逻辑的处理,可能涉及到: ORM、Templates 。
- 响应中间件: 对响应的数据进行处理。
- wsgi : 将响应的内容发送给浏览器。
过程回顾:
- 浏览器接收到用户输入的网址:http://127.0.0.1:800/book/,wsgi将该网址请求封装后发送给Django处理;
- Django接收到该处理请求后首先交给路由配置文件,即URL Conf,该文件有主文件也有子文件
- 路由配置文件会将请求转发给对应的,符合条件的视图函数文件(view)
a. 此处若业务逻辑较简单,则会直接将i俄国返回给用户;
b. 若有美观话需求,则会调用html文件模板,并且传入信息进行渲染,最后将结果再返回给用户;
c. 最后一种,若在渲染之前需要调用数据库查询,则先通过Model对数据库进行操作,再将结果经过Model传回给View视图函数文件,View将查询的结果作为Context变量(上下文)传给Template模板,最后再将结果传给用户; - 具体流程选择需要结合业务模式分析;
- 此外,还有中间键功能,在不同阶段可以进一步细化功能
标签:Book,进阶,管理,Python,数据库,models,book,date,name 来源: https://blog.csdn.net/Fancyll_Lee/article/details/114379792
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。