Django项目:图书-英雄管理系统
第三步:项目的数据库模型
1. 创建数据库模型 (2个类)
-
ORM概念
ORM(Object Ralational Mapping,对象关系映射)用来把对象模型表示的对象映射到基于SQL 的关系模型数据库结构中去。这样,我们在具体的操作实体对象的时候,就不需要再去和复杂的 SQL 语句打交道,只需简单的操作实体对象的属性和方法。ORM 技术是在对象和关系之间提供了一条桥梁,前台的对象型数据和数据库中的关系型的数据通过这个桥梁来相互转化 。 -
这里只做简单的本地调试,所以,使用的是
SQLite
-
本示例完成**“图书-英雄”**信息的维护,需要存储两种数据:图书、英雄
- 图书表结构设计: 表名: Book
图书名称: title
图书发布时间: pub_date - 英雄表结构设计: 表名: Hero
英雄姓名: name
英雄性别: gender
英雄简介: hcontent
所属图书: hbook - 图书-英雄的关系为一对多
- 图书表结构设计: 表名: Book
from django.db import models
"""
ORM(Object Ralational Mapping,对象关系映射)用来把对象模型表示的对象映射到基于S Q L 的关系模型数据库结构中去。
这样,我们在具体的操作实体对象的时候,就不需要再去和复杂的 SQ L 语句打交道,只需简单的操作实体对象的属性和方法。
O R M 技术是在对象和关系之间提供了一条桥梁,前台的对象型数据和数据库中的关系型的数据通过这个桥梁来相互转化 。
"""
# Create your models here.
# 类对应数据库表,表名称默认为bookAPP_book (models.Model)
# 数据库表有3列信息: id, title, pub_date
class Book(models.Model):
# 属性对应数据库表的列名,默认会添加id这一列
name = models.CharField(max_length=40, verbose_name='书籍名称')
pub_date = models.DateField(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='性别') # 1,2
content = models.TextField(max_length=1000, verbose_name='人物描述')
# 外键关联,如果删除书籍时,相关hero对应的书籍设置为空
book_id = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True, verbose_name='书籍id')
2. 生成数据库表
2.1 激活模型
- 编辑 BookManage中的 settings.py 文件,将应用加入到INSTALLED_APPS 中
2.2 生成迁移文件
- 根据模型类生成 sql 语句
PS E:\djangoProject\BookManage> python .\manage.py makemigrations
- 产生的迁移文件如下:
2.3 执行迁移(将迁移脚本应用到数据库中)
- 执行SQL语句生成数据表
PS E:\djangoProject\BookManage> python .\manage.py migrate
- 数据库中查看数据库表是否创建成功?
3. 数据库模型的基本操作
3.1 查看元素
- 现在进入交互式的Python shell,并使用 Django 提供的免费 API
- 先安装ipython,方便使用python shell
PS E:\djangoProject\BookManage> pip install ipython
- 进入交互式Python Shell
PS E:\djangoProject\BookManage> python manage.py shell
- 导入数据模型
# 引入需要的包:
>>> from bookApp.models import Book, Hero
- 查看元素
>>> # 1. 查看操作
>>> Book.objects.all() # 查询所有图书信息:
<QuerySet []>
3.2 增加数据信息
- 新建图书信息(结果不符合用户体验)
>>> # 2. 增加数据信息
>>> # 数据库表中的一条记录对应OOP中的一个object
>>> b1 = Book()
>>> b1.name = '西游记'
>>> from datetime import date
>>> d1 = date(2000, 1, 4)
>>> b1.pub_date = d1
>>> b1
<Book: Book object (None)>
>>> Book.objects.all()
<QuerySet []>
>>> b1.save()
>>> Book.objects.all()
<QuerySet [<Book: Book object (1)>]>
# 此时显示的结果是QuerySet格式,不符合用户体验,需要进行调优
- 利用魔术方法,便于调试代码,字符串友好展示,符合用户体验
- 在bookAPP目录中的models.py文件中添加魔术方法
# 魔术方法,便于调试代码
def __str__(self):
return self.name
- 退出之前的Python Shell
>>> exit()
- 再次进入Python Shell
- 此时的结果显示,就符合用户体验
>>> from bookApp.models import Book, Hero
>>> Book.objects.all()
<QuerySet [<Book: 西游记>]>
- 以更快的方法新建数据
>>> # 2. 以更快的方法新建数据
>>> from datetime import date
>>> b2 = Book(name = '红楼梦', pub_date = date(1998, 4, 1))
>>> b2.save()
>>> Book.objects.all()
<QuerySet [<Book: 西游记>, <Book: 红楼梦>]>
3.3 根据条件搜索并查看
>>> # 3. 根据条件搜索并查看
>>> b1 = Book.objects.filter(name = '西游记')
>>> b1
<QuerySet [<Book: 西游记>]>
>>> b1 = Book.objects.filter(name = '西游记').first()
>>> b1
<Book: 西游记>
>>> type(b1)
<class 'bookApp.models.Book'>
>>> b1.pub_date
datetime.date(2000, 1, 4)
3.4 删除
>>> # 4. 删除
>>> b1
<Book: 西游记>
>>> b1.delete()
(1, {'bookApp.Book': 1})
>>> Book.objects.all()
<QuerySet [<Book: 红楼梦>]>
3.5 创建关联对象
>>> # 5. 创建关联对象
>>> book = Book(name = '倚天屠龙记', pub_date = date(2000, 1, 1))
>>> book.save()
>>> hero1 = Hero(name = '周芷若', gender = 2, content = 'info...')
>>> hero1.save()
>>> Hero.objects.all()
<QuerySet [<Hero: 周芷若>]>
>>> hero1.book_id = book
>>> hero1.save()
>>> hero1.book_id
<Book: 倚天屠龙记>
>>> hero1.book_id_id
3
>>> book.hero_set.all()
<QuerySet [<Hero: 周芷若>]>
3.6 查找book名称中包含有“红”的书籍
>>> books = Book.objects.filter(name__contains = '红')
>>> books
<QuerySet [<Book: 红楼梦>]>
3.7 查找发布日期小于今天日期的书籍
>>> books = Book.objects.filter(pub_date__lt = date.today())
>>> books
<QuerySet [<Book: 红楼梦>, <Book: 倚天屠龙记>]>
3.8 查找book名称中不包含有“红”的书籍
>>> books = Book.objects.exclude(name__contains = '红')
>>> books
<QuerySet [<Book: 倚天屠龙记>]>
第四步:启用后台Admin站点管理(补充)
1. 自定义模型加入后台管理
- 打开 bookApp/admin.py 文件,注册模型
(重新启动…)
from django.contrib import admin
from bookApp.models import Book, Hero
# Register your models here.
admin.site.register([Book, Hero])
- 运行基础Django框架
PS E:\djangoProject\BookManage> python .\manage.py runserver 9999
- 导入数据模型
PS E:\djangoProject\BookManage> python .\manage.py shell
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct 5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from bookApp.models import Book, Hero
- 页面访问 http://127.0.0.1:9999/admin,查看设置结果
2. 后台管理时, Book管理显示的是英文, 如何变成中文
- 在bookApp/models.py文件中,添加Meta子类
class Meta:
verbose_name = '图书管理'
verbose_name_plural = verbose_name
class Meta:
verbose_name = '人物管理'
verbose_name_plural = verbose_name
- 页面访问 http://127.0.0.1:9999/admin,查看设置结果
3. 自定义管理页面
- Django 提供了 admin.ModelAdmin 类
- 通过定义 ModelAdmin 的子类,来定义模型在 Admin 界面的显示方式
3.1 列表页属性
- ist_display:显示字段,可以点击列头进行排序
from django.contrib import admin
from bookApp.models import Book, Hero
# Register your models here.
class BookAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'pub_date'] # ist_display:显示字段,可以点击列头进行排序
admin.site.register(Book, BookAdmin)
admin.site.register(Hero)
- list_filter:过滤字段,过滤框会出现在右侧
from django.contrib import admin
from bookApp.models import Book, Hero
# Register your models here.
class BookAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'pub_date'] # ist_display:显示字段,可以点击列头进行排序
list_filter = ['pub_date'] # list_filter:过滤字段,过滤框会出现在右侧
admin.site.register(Book, BookAdmin)
admin.site.register(Hero)
- search_fields:搜索字段,搜索框会出现在上侧
from django.contrib import admin
from bookApp.models import Book, Hero
# Register your models here.
class BookAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'pub_date'] # ist_display:显示字段,可以点击列头进行排序
list_filter = ['pub_date'] # list_filter:过滤字段,过滤框会出现在右侧
search_fields = ['name'] # search_fields:搜索字段,搜索框会出现在上侧
admin.site.register(Book, BookAdmin)
admin.site.register(Hero)
- list_per_page:分页,分页框会出现在下侧
先通过可视化界面增加5个book
再修改bookApp/admin.py文件
from django.contrib import admin
from bookApp.models import Book, Hero
# Register your models here.
class BookAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'pub_date'] # ist_display:显示字段,可以点击列头进行排序
list_filter = ['pub_date'] # list_filter:过滤字段,过滤框会出现在右侧
search_fields = ['name'] # search_fields:搜索字段,搜索框会出现在上侧
list_per_page = 5 # list_per_page:分页,分页框会出现在下侧
admin.site.register(Book, BookAdmin)
admin.site.register(Hero)
访问页面 http://127.0.0.1/admin,查看结果
- list_display_links:链接跳转页面,点击进入编辑页面
from django.contrib import admin
from bookApp.models import Book, Hero
# Register your models here.
class BookAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'pub_date'] # ist_display:显示字段,可以点击列头进行排序
list_filter = ['pub_date'] # list_filter:过滤字段,过滤框会出现在右侧
search_fields = ['name'] # search_fields:搜索字段,搜索框会出现在上侧
list_per_page = 5 # list_per_page:分页,分页框会出现在下侧
list_display_links = ['id', 'name'] # list_display_links:链接跳转页面,点击进入编辑页面
admin.site.register(Book, BookAdmin)
admin.site.register(Hero)
- Hero人物管理的列表页展示设置同上
from django.contrib import admin
from bookApp.models import Book, Hero
# Register your models here.
class BookAdmin(admin.ModelAdmin):
# 列表页展示的设置
list_display = ['id', 'name', 'pub_date'] # ist_display:显示字段,可以点击列头进行排序
list_filter = ['pub_date'] # list_filter:过滤字段,过滤框会出现在右侧
search_fields = ['name'] # search_fields:搜索字段,搜索框会出现在上侧
list_per_page = 5 # list_per_page:分页,分页框会出现在下侧
list_display_links = ['id', 'name'] # list_display_links:链接跳转页面,点击进入编辑页面
class HeroAdmin(admin.ModelAdmin):
# 列表页展示的设置
list_display = ['id', 'name', 'gender'] # ist_display:显示字段,可以点击列头进行排序
list_filter = ['gender'] # list_filter:过滤字段,过滤框会出现在右侧
search_fields = ['name', 'content'] # search_fields:搜索字段,搜索框会出现在上侧
list_per_page = 5 # list_per_page:分页,分页框会出现在下侧
list_display_links = ['name'] # list_display_links:链接跳转页面,点击进入编辑页面
admin.site.register(Book, BookAdmin)
admin.site.register(Hero, HeroAdmin)
3.2 添加、修改页属性
- fields:属性的先后顺序
fields = ['pub_date', 'title']
- fieldsets :属性分组, 注意: fields和fieldsets 只能设置一个
修改之前的编辑页
修改bookApp/admin.py文件
访问页面,检测结果
3.3 关联对象
-
对于 Hero 模型类,有两种注册方式
- 方式一:与 Book 模型类相同
- 方式二:关联注册
- admin.StackedInline : 内嵌关联注册类
- admin.TabularInline : 表格 关联注册类
-
admin.TabularInline : 表格 关联注册类
-
修改bookApp/admin.py文件
-
访问页面,检测结果
在book1中添加2个人物“张三”,“李四”
图书管理中添加的用户,通过人物管理也能查看到
- admin.StackedInline : 内嵌关联注册类
- 修改bookApp/admin.py文件
- 访问页面,检测结果(符合用户体验)
第五步:前台管理
1. URLconf 路由管理
- 在 Django 中,定义 URLconf 包括正则表达式、视图两部分 。
- Django 使用正则表达式匹配请求的URL,一旦匹配成功,则调用应用的视图 。
- 注意:只匹配路径部分,即除去域名、参数后的字符串 。
- 在主配置文件中添加子配置文件,使主 urlconf 配置连接到子模块的 urlconf 配置文件 。
- 修改BookManage目录中的urls.py文件的路由信息
from django.contrib import admin
from django.urls import path, include
from bookApp.views import index
urlpatterns = [
path('admin/', admin.site.urls),
# path('index/', index), # 图书管理系统
# 当用户访问bookApp应用的主页时, 执行视图函数index,反向根据名称获取url地址;
path('book/', include('bookApp.urls')),
# 以book开头,去读某一个子配置文件
# 当用户请求路径为/book/时,访问bookApp/urls.py子路由配置文件
]
- 修改bookApp目录中的urls.py文件的路由信息
from django.urls import path
from bookApp import views
urlpatterns = [
# 当用户访问路径是/book/时,执行views.index视图函数
path(r'', views.index, name='index'),
]
2. 创建index.html页面
- 在Django目录下的templates目录中创建一个新的目录book
- 在book目录下创建一个index.html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 style = 'color: deeppink'>图书管理系统</h1>
<ul>
{% for book in books %}
<li>{{ book.name }}</li>
{% endfor %}
</ul>
</body>
</html>
2. 租用HTML代码模板,渲染页面(views.py)
- 在 Django 中,视图对WEB请求进行回应( response )。
- 视图接收 reqeust 请求对象作为第一个参数,包含了请求的信息 。
- 视图函数就是一个Python函数,被定义在 views.py 中 。
- 定义完成视图后,需要配置 urlconf ,否则无法处理请求
- 渲染: 将上下文content{‘books’:books}填充到book/index.html代码的过程
- 修改bookApp目录中的views.py的视图函数
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
# 通过http格式,封装响应
# 视图: 对用户的请求(request)进行业务逻辑操作,最终返回用户一个响应(response)
from bookApp.models import Book
def index(request):
# print('用户请求的路径:', request.path)
# 返回响应信息
# return HttpResponse('<h1 style="color:green">图书管理系统</h1>')
# 渲染: 将上下文content{'books':books}填充到book/index.html代码的过程
books = Book.objects.all()
return render(request, 'book/index.html', {'books' : books})
- 展示结果
3. 配置子路由,显示书籍详细页信息
- 创建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>
- 修改bookApp/views.py文件
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
# 通过http格式,封装响应
# 视图: 对用户的请求(request)进行业务逻辑操作,最终返回用户一个响应(response)
from bookApp.models import Book
def index(request):
# print('用户请求的路径:', request.path)
# 返回响应信息
# return HttpResponse('<h1 style="color:green">图书管理系统</h1>')
# 渲染: 将上下文content{'books':books}填充到book/index.html代码的过程
books = Book.objects.all()
return render(request, 'book/index.html', {'books' : books})
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})
- 修改bookApp/urls.py文件
from django.urls import path
from bookApp import views
urlpatterns = [
# 当用户访问路径是/book/时,执行views.index视图函数
path(r'', views.index, name='index'),
# 显示书籍的详情页,接收一个int值并赋值给id
path(r'<int:id>/', views.detail, name = 'detail'),
]
- 查看结果