引言
在 Django模型设计 中我们只设计了一个BookInfo模型类,内容好单调,接下来我们初步完善一下BMSTes图书管理系统。
模型设计
我们写项目写东西的时候都要养成良好的习惯,不要一来就上手写代码,我们先要进行初步分析和设计,让大脑有整体的概念,需要用到什么技术实现什么效果。这个习惯也不能学的太死,我们要活学活用,学会变通。有时候只是简单的学习一下,或者简单的实现一个小功能。大脑已经可以大概掌握,就无须设计与分析。
初步分析、设计
我们图书管理系统主要实现的是 图书与图书英雄的关联、图书与图书类型的关联管理 ,因此分为图书信息模型、英雄信息模型、图书类型模型,三个模型。对应关系设计如下
一种图书类型,对应多本图书,例如:小说类型的图书,有射雕英雄传、神雕侠侣、倚天屠龙记小说图书等。
一本图书,对应多个英雄,例如:射雕英雄传图书,对应有着郭靖、黄蓉、洪七公等、射雕侠侣则对应杨过、小龙女等。
- 图书类型模型与图书信息模型关联的是1对多的关系
- 图书信息模型与英雄信息模型关联的是1对多的关系
实体模型1 | 实体模型2 | 对应关系 |
---|---|---|
图书类型(BookType) | 图书信息(BookInfo) | 1 : N |
图书信息(BookInfo) | 英雄信息(HeroInfo) | 1 : N |
具体实现设计
BookType图书类型模型类
类属性 | 数据类型 | 备注 |
---|---|---|
id | IntegerField(整型) | 主键、自增 |
type_name | CharField(字符型) | 图书类型 |
BookInfo图书模型类
类属性 | 数据类型 | 备注 |
---|---|---|
id | IntegerField(整型) | 主键、自增 |
book_type | IntegerField(整型)ForeignKey | 图书类型,外键 |
title | CharField(字符型) | 图书名称 |
author | CharField(字符型) | 图书作者 |
pub_date | CharField(字符型) | 图书出版日期 |
isbn | CharField(字符型) | 图书ISBN |
book_desc | CharField(字符型) | 图书描述 |
book_detail | TextField(文本类型) | 图书详情 |
book_price | DecimalField (数值类型) | 图书价格 |
book_like_num | IntegerField(整型) | 图书喜欢数 |
book_collect_num | IntegerField(整型) | 图书收藏数 |
HeroInfo图书英雄模型类
类属性 | 数据类型 | 备注 |
---|---|---|
id | IntegerField(整型) | 主键自增 |
name | CharField(字符型) | 英雄名称 |
gender | CharField(字符型) | 英雄性别 |
skill | CharField(字符型) | 英雄技能(武功) |
book | InterField(整型)Foreignkey | 英雄所属图书,外键 |
Django模型代码
代码语言:javascript复制# -*- coding:utf-8 -*-
"""
@Author :Hui
@Desc :{模型设计模块}
"""
from django.db import models
class BookType(models.Model):
"""图书类别类"""
type_name = models.CharField(verbose_name=u'图书类型', max_length=20)
def __str__(self):
return self.type_name
class Meta:
db_table = 'BookType' # 表名称
verbose_name = '图书类型' # 表备注
# 表名复数形式,如果不设置末尾会多一个s
verbose_name_plural = verbose_name
ordering = ['id'] # 排序字段
class BookInfo(models.Model):
"""图书模型类"""
title = models.CharField(verbose_name=u'图书名称', max_length=20)
author = models.CharField(verbose_name=u'图书作者', max_length=20)
pub_date = models.DateField(verbose_name=u'出版日期')
book_type = models.ForeignKey(BookType, on_delete=models.CASCADE, verbose_name=u'图书类型')
isbn = models.CharField(verbose_name='ISBN', max_length=20)
book_desc = models.CharField(verbose_name=u'图书描述', max_length=128)
book_detail = models.TextField(verbose_name=u'图书详情')
book_price = models.DecimalField(verbose_name=u'图书价钱', max_digits=5, decimal_places=2)
book_like_num = models.IntegerField(verbose_name=u'图书喜欢量')
book_collect_num = models.IntegerField(verbose_name=u'图书收藏量')
def __str__(self):
return self.title
class Meta:
db_table = 'BookInfo'
verbose_name = u'图书信息'
verbose_name_plural = verbose_name
ordering = ['id']
class HeroInfo(models.Model):
"""英雄模型类"""
name = models.CharField(verbose_name=u'英雄姓名', max_length=20)
# 英雄性别
gender = models.CharField(verbose_name=u'英雄性别', max_length=3)
# 英雄技能(武功)
skill = models.CharField(verbose_name=u'英雄武功', max_length=128)
# 英雄所属图书
book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name=u'图书')
def __str__(self):
return self.name
class Meta:
db_table = 'HeroInfo'
verbose_name = u'人物信息'
verbose_name_plural = verbose_name
ordering = ['id']
设计模型的时候出现了几个之前没用过的字段类型,在这里简单介绍一下。
- TextField: 大文本字段,一般超过4000个字符时使用。
- IntegerField: 整数。
- DecimalField(max_digits=None, decimal_places=None): 十进制浮点数。
- 参数max_digits表示总位数。
- 参数decimal_places表示小数位数。
Meta类中的属性
- db_table: 设置创建数据库表的名称,默认的是
应用名_模型类名
- verbose_name: 设置数据库表的详细信息(表备注)
- verbose_name_plural: 设置数据表的复数显示形式
- ordering: 设置数据表的排序字段
字段、和Meta类中属性,以后再做详细介绍。
自定义后台管理
模型设计好了,接下来就是在 admin.py
下注册模型了,在注册模型中,我新增了 inlines
、list_per_page
、search_fields
属性
- inlines: 用于嵌入编辑关联的对象,属性设置在
一对多
模型(表)关系中的一
中。 - admin.TabularInline: 嵌入编辑关联的对象的编辑样式为表格式类
- admin.StackedInline: 嵌入编辑关联的对象的编辑样式为堆放式类
- model: 关联的子对象
- extra: 嵌入编辑子对象的个数
- list_per_page: 数据分页,每页的数据个数
- search_fields: 查询字段
# -*- coding:utf-8 -*-
"""
@Author :Hui
@Desc :{后台管理模块}
"""
from django.contrib import admin
from book.models import BookType, BookInfo, HeroInfo
class BookTypeInline(admin.StackedInline):
model = BookInfo # 关联的子对象
extra = 1 # 嵌入编辑子对象的个数
class BookInfoInline(admin.TabularInline):
model = HeroInfo
extra = 2
class BookTypeAdmin(admin.ModelAdmin):
"""图书类型模型管理类"""
# 数据分页,每页10条
list_per_page = 10
# 后台显示的属性(字段)
list_display = ['id', 'type_name']
# 查询字段
search_fields = ['type_name']
# 嵌入编辑关联的对象(表格式)
inlines = [BookTypeInline]
class BookInfoAdmin(admin.ModelAdmin):
"""图书信息模型管理类"""
list_per_page = 20
list_display = [
'id', 'title', 'author', 'pub_date', 'book_desc', 'book_like_num', 'book_collect_num', 'book_type'
]
search_fields = ['id', 'title', 'author', 'book_desc']
# 设置图书作者、类型为过滤字段
list_filter = ['author', 'book_type']
# 嵌入编辑关联的对象(堆放式)
inlines = [BookInfoInline]
class HeroInfoAdmin(admin.ModelAdmin):
"""英雄信息模型管理类"""
list_display = ['id', 'name', 'skill', 'book']
# 设置图书查询字段
search_fields = ['name', 'skill', 'book']
# 设置英雄图书过滤字段
list_filter = ['book']
# 注册模型类
admin.site.register(BookType, BookTypeAdmin)
admin.site.register(BookInfo, BookInfoAdmin)
admin.site.register(HeroInfo, HeroInfoAdmin)
配置MySQL数据库
注册完了模型类,接下来就配置数据库,之前用的是 Django
自带的 sqlite3
数据库,现在我们换成 MySQL
数据库。
首先在 PyCharm
的 Terminal
中输入命令安装 pymysql
驱动
pip install pymysql
然后在项目的 settings.py
文件中找到 DATABASES
配置项,将其信息修改为:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # MySQL数据库
# 'NAME': BASE_DIR / 'db.sqlite3', # sqlite3数据库
'NAME': 'BMSTest', # 数据库名称
'HOST': '127.0.0.1', # 数据库地址,本机 ip 地址 127.0.0.1
'PORT': 3306, # 数据库端口
'USER': 'root', # 数据库用户名
'PASSWORD': '123456', # 数据库密码
}
}
最后在与 settings.py
同级目录下的 __init__.py
中引入模块和进行配置
import pymysql
pymysql.version_info = (1, 4, 13, "final", 0)
pymysql.install_as_MySQLdb()
pymysql.version_info = (1, 4, 13, "final", 0)
这行代码
解决 django.core.exceptions.ImproperlyConfigured: mysqlclient 1.4.0 or newer is required; you have 0.10.1.
这个错 搜索了下网上的解决办法要么升级要么降级 但是都觉得麻烦于是到处找能不能用几行代码解决的方法 最后成功在stackflow上找到一个办法在 settings.py
同级目录下的 __init__.py
插入这行代码就可以了。
运行服务器
- 创建数据库迁移文件
python manage.py makemigrations
- 执行数据库迁移文件
python manage.py migrate
- 运行服务器
python manage.py runserver
如果在运行 python manage.py makemigrations
命令时出现了如下类似的情况
(py_django) D:HuiCodePythonDjangoProjectBMSTest>python manage.py makemigrations
You are trying to add a non-nullable field 'book_type' to bookinfo without a default; we can't do that (the database needs something to populate ex
isting rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option:
说明表结构与之前的表结构发生了变化,之前 BookInfo
的只有 title
、author
、pub_date
,现在的则多了 book_type
、isbn
、book_desc
、book_detail
等属性。且这些属性没有 default
默认值,存在 null
值。
解决方案:
数据库结构
注意:如果切换了数据库,数据不会迁移过来,记得自己手动添加或者导入。
图书类型的分页效果图
图书信息的过滤效果图
嵌入编辑关联的对象(堆放式)
在编辑图书类型的时候,会在下面根据 extra
属性值内嵌入关联的对象(图书信息)的个数
嵌入编辑关联的对象(表格式)
建议:
- 如果关联的模型(表)属性较多,建议使用 堆放式(admin.StackedInline),且不要放置太多,建议1个或者不设置。
- 如果关联的模型(表)属性较少,放置多些时建议 表格式(admin.TabularInline),少些时任意格式都无伤大雅。
这样就不会导致网页,从上到下滑动的太长、或者是从左到右滑动的太长,而不好编辑,不太美观。
公众号
新建文件夹X
大自然用数百亿年创造出我们现实世界,而程序员用几百年创造出一个完全不同的虚拟世界。我们用键盘敲出一砖一瓦,用大脑构建一切。人们把1000视为权威,我们反其道行之,捍卫1024的地位。我们不是键盘侠,我们只是平凡世界中不凡的缔造者 。