Appearance
表单字段配置
后端模型
定义模型类
模型类与数据库关系
- 每一个模型类(继承类django.db.models.Model)都映射一张数据库表
- 模型类的每个属性都相当于一个数据库的字段。
以下是Django常用字段类型及其描述:
字段类型 | 描述 |
---|---|
AutoField | 一个自增的整数类型字段,通常用于主键。如果不指定,Django会自动创建一个名为id 的AutoField字段。 |
BooleanField | 布尔值字段,表示True或False。 |
CharField | 字符串字段,用于较短的文本。必须指定max_length参数。 |
TextField | 大文本字段,用于存储较长的文本。 |
IntegerField | 整数字段。 |
BigIntegerField | 大整数字段,适用于整数范围超过IntegerField上限的场景。 |
SmallIntegerField | 小整数字段,适用于整数范围较小的场景。 |
PositiveIntegerField | 正整数字段。 |
PositiveSmallIntegerField | 正小整数字段。 |
FloatField | 浮点数字段。 |
DecimalField | 用于精确表示小数,指定小数位数。必须指定max_digits和decimal_places参数。 |
DateTimeField | 日期和时间字段,对应Python的datetime.datetime实例。 |
DateField | 日期字段,对应Python的datetime.date实例。 |
TimeField | 时间字段,对应Python的datetime.time实例。 |
DurationField | 时间间隔字段,用于表示时间段,对应Python的timedelta。 |
EmailField | 电子邮件字段,使用CharField进行验证。 |
FileField | 文件上传字段。 |
ImageField | 图像上传字段,继承自FileField,但会对上传的文件进行验证,确保其为有效的图像。 |
URLField | URL字段,使用CharField进行验证。 |
UUIDField | UUID字段,用于存储全局唯一标识符。 |
ForeignKey | 外键字段,用于表示一对多关系。 |
ManyToManyField | 多对多字段,用于表示多对多关系。 |
OneToOneField | 一对一字段,用于表示一对一关系。 |
示例:进入目录django-vue3-admin\backend\my_demo
,文件models.py
。
- CrudDemoModel是一个模型类,将在数据库中创建对应的一张数据库表
goods
- goods、inventory、goods_price、purchase_goods_date属性,分别对应数据库一个字段
python
from django.db import models
from dvadmin.utils.models import CoreModel
class CrudDemoModel(CoreModel):
goods = models.CharField(max_length=255, verbose_name="商品")
inventory = models.IntegerField(verbose_name="库存量")
goods_price = models.FloatField(verbose_name="商品价格")
# 日期类型为DateField,时间类型为DateTimeField
purchase_goods_date = models.DateField(verbose_name="进货日期")
class Meta:
db_table = "goods"
verbose_name = "商品表"
verbose_name_plural = verbose_name
ordering = ("-create_datetime",)
使用模型
一旦你定义了你的模型,你需要告诉 Django 你准备 使用 这些模型。你需要修改设置文件中的 INSTALLED_APPS
,在这个设置中添加包含 models.py
文件的模块名称。
python
INSTALLED_APPS = [
# ...
"my_demo",
# ...
]
当你向 INSTALLED_APPS
添加新的应用的时候,使用以下命令进行迁移
python
python manage.py makemigrations
python manage.py migrate
迁移
迁移是 Django 将你对模型的修改(例如增加一个字段,删除一个模型)应用至数据库架构中的方式。将迁移看作是数据库架构的版本控制系统。 makemigrations
负责将模型修改打包进独立的迁移文件中——类似提交修改,而 migrate
负责将其应用至数据库。以下是几个常用的与迁移交互的命令:
migrate
,负责应用和撤销迁移。makemigrations
,基于模型的修改创建迁移。sqlmigrate
,展示迁移使用的 SQL 语句。showmigrations
,列出项目的迁移和迁移的状态。
每执行一次makemigrations命令,会生成迁移文件myapp/migrations/xxxx_initial.py
。迁移文件中的dependencies指定了它们所依赖的其他哪些迁移。
sh
python manage.py makemigrations
#执行示例1
PS E:\python_workspace\django\dvadmin\django-vue3-admin\backend> python .\manage.py makemigrations
<class 'list'>
No changes detected #模型没有修改,所以不会产生迁移文件
#执行示例2
PS E:\python_workspace\django\dvadmin\django-vue3-admin\backend> python .\manage.py makemigrations
<class 'list'>
Migrations for 'my_demo':
my_demo\migrations\0002_cruddemomodel_brand.py #生成迁移文件
- Add field brand to cruddemomodel
生成的迁移文件示例
python
# 0001_initial.py迁移文件
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
# 0002_cruddemomodel_brand.py迁移文件
dependencies = [
('my_demo', '0001_initial'),
]
每执行一次migrate命令,会在数据库中的django_migrations表创建一条记录,并将迁移文件应用到数据库。
sh
python manage.py migrate
撤销迁移
撤销迁移并还原数据库参考步骤:
登录数据库,查看表django_migrations,查看目前已执行的迁移文件
根据app、name字段,找到对应的迁移文件,并查看其内容
根据迁移文件内容,手动还原数据库相应操作。
删除表django_migrations相应的记录。
前端表单
表单配置文件
配置表单界面对应文件django-vue3-admin\web\src\views\MyDemo\CrudDemoModelViewSet\crud.tsx
ts和tsx文件区别
在TypeScript中,.ts 和.tsx 文件扩展名代表两种不同的文件类型:.ts:这是一个标准的TypeScript文件,它可以包含TypeScript代码,该代码最终会被编译成 JavaScript。.ts 文件通常不包含JSX代码,JSX是一种JavaScript的语法扩展,允许你在JavaScript代码中写类似HTML的标记。.tsx:这是一个包含JSX语法的TypeScript文件。
表单类型input/number/text/date
表单类型
- input:短文本输入
- number:整数选择
- text:长文件输入
- date:日期选择
typescript
columns: {
goods: {
title: '商品',
type: 'input',
search: { show: true },
column: {
minWidth: 120,
sortable: 'custom',
},
form: {
helper: {
render() {
return <div style={'color:blue'}>商品是必需要填写的</div>;
},
},
rules: [{ required: true, message: '商品名称必填' }],
component: {
placeholder: '请输入商品名称',
},
},
},
inventory: {
title: '库存量',
type: 'number',
search: { show: false },
column: {
minWidth: 120,
sortable: 'custom',
},
form: {
rules: [{ required: true, message: '库存量必填' }],
component: {
placeholder: '请输入库存量',
},
},
},
goods_price: {
title: '商品定价',
type: 'text',
search: { show: false },
column: {
minWidth: 120,
sortable: 'custom',
},
form: {
rules: [{ required: true, message: '商品定价必填' }],
component: {
placeholder: '请输入商品定价',
},
},
},
purchase_goods_date: {
title: '进货时间',
type: 'date',
search: { show: false },
form: {
// rules: [{ required: true, message: '进货时间必填' }],
component: {
//显示格式化
format: 'YYYY-MM-DD',
//输入值格式
valueFormat: 'YYYY-MM-DD',
placeholder: '请输入进货时间',
},
},
column: {
align: 'center',
width: 120,
component: { name: 'fs-date-format', format: 'YYYY-MM-DD' },
},
},
},
表单类型dict-radio
表单类型dict-radio:单选按钮
ts
is_shelves: {
title: '是否上架',
search: { show: false },
type: 'dict-radio',
dict: dict({
data: [
{
label: '是',
value: true,
color: 'success',
},
{
label: '否',
value: false,
color: 'danger',
},
],
}),
column: {
width: 130,
sortable: 'custom',
},
form: {
rules: [{ required: true, message: '是否上架必填' }],
value: false,
},
},
后端models.py配置
python
# 是否上架,默认为True
is_shelves = models.BooleanField(verbose_name="是否上架", default=True)
查看效果
表单类型dict-select
表单类型dict-select:下拉选择
ts
import { dictionary } from '/@/utils/dictionary';
goods_status: {
title: '商品状态',
type: 'dict-select',
dict: dict({
value: 'label',
label: 'label',
data: dictionary('goods_status'),
}),
form: {
component: {
span: 12,
},
},
component: { props: { color: 'auto' } }, // 自动染色
},
后端models.py配置
python
# 商品状态(Status):商品的状态(在售、下架、缺货、其它)
goods_status = models.CharField(
max_length=255, verbose_name="商品状态", blank=True, null=True
)
启动项目,登录--常规配置--字典管理,添加
刚才添加的字典右侧--字典配置,依次添加
按ctrl+F5强制刷新网页,查看效果
表单类型dict-select一对一关联
表单类型dict-select一对一关联:下拉选择时,只显示未被引用的对象。
配置后端
python
# 配置模型层:文件models.py
class TraceabilityModel(CoreModel):
supplier = models.CharField(max_length=255, verbose_name="供应商")
batch_number = models.CharField(max_length=255, verbose_name="批次号")
class Meta:
db_table = "traceability"
verbose_name = "商品溯源表"
verbose_name_plural = verbose_name
ordering = ("-create_datetime",)
class CrudDemoModel(CoreModel):
#一对一关联字段,对应数据库字段名称为 traceability_id :增加这句
traceability = models.OneToOneField(
TraceabilityModel,
on_delete=models.PROTECT,
verbose_name="商品溯源",
blank=True,
null=True,
)
# 配置序列化器:文件serializers.py
class TraceabilityModelSerializer(CustomModelSerializer):
"""TraceabilityModel的序列化器"""
class Meta:
model = TraceabilityModel
fields = "__all__"
# 配置视图:文件views.py
class TraceabilityModelViewSet(CustomModelViewSet):
queryset = TraceabilityModel.objects.all()
serializer_class = TraceabilityModelSerializer
# 改写get_queryset方法,返回未关联的TraceabilityModel对象
def get_queryset(self):
return TraceabilityModel.objects.filter(cruddemomodel=None)
# 配置URL路由:文件urls.py
from django.urls import path
from rest_framework import routers
from .views import (
CrudDemoModelViewSet,
BookViewSet,
TraceabilityModelViewSet,
StudentListCreate,
StudentRetrieveUpdateDestroy,
)
router = routers.SimpleRouter()
router.register("api/CrudDemoModelViewSet", CrudDemoModelViewSet)
router.register("api/traceability", TraceabilityModelViewSet) #增加这句
router.register("api/books", BookViewSet)
urlpatterns = [
path("api/students/", StudentListCreate.as_view()),
path("api/students/<int:pk>/", StudentRetrieveUpdateDestroy.as_view()),
]
urlpatterns = urlpatterns + router.urls
执行数据迁移
python
python manage.py makemigrations
python manage.py migrate
前端配置
进入目录django-vue3-admin\web\src\views\MyDemo\CrudDemoModelViewSet\
,编辑文件crud.tsx
,添加如下代码。
tsx
traceability_id: {
title: '商品溯源',
search: {
// disabled: true,
show: true,
},
type: 'dict-select',
column: {
minWidth: 150, //最小列宽
component: {
dict: dict({
isTree: true,
url: '/api/traceability/',
value: 'id',
label: 'supplier',
getData: async ({ url }: { url: string }) => {
return request({
url: url,
}).then((ret: any) => {
return ret.data;
});
},
}),
},
},
form: {
/* 功能说明:这里添加了一个按钮做跳转至相应的对象,以便随时方便预览、新增、编辑、对象*/
suffixRender({ value }) {
//这里把当前的value传进去
function goto({ value }: { value: any }) {
if (!value) {
// 这里判断当选项没有值是,用户又点了跳转按钮,那说明是需要新增对象
// value = 0;
value = 1;
}
// 这里是跳转至相应的路由,把value给到id
//这里整个配置主要name:'FormNewPageEdit'便可
router.push({ name: 'FormNewPageEdit', params: { id: value } });
}
return (
// 这里配置一个跳转的按钮及引用函数
<el-button-group style={'padding-left:5px'}>
<fs-button onClick={() => goto({ value })}>跳转</fs-button>
</el-button-group>
);
},
component: {
filterable: true,
placeholder: '请选择',
props: {
props: {
value: 'id',
label: 'licence_num',
},
},
dict: dict({
prototype: true,
isTree: true,
url: '/api/traceability/',
value: 'id',
label: 'supplier',
getData: async ({ url, form }: { url: string; form: any }) => {
// 这里专门传了当前的form进来,是为了拿到他的值form.soft_licence然后再进行拼接路由,这样后端就可以拿到当前form的某个值进行筛选了。
// 注意这里要想拿到form.soft_licence字段是根据自己的model表解决了,要根本使用情况而修改
let pkid = 1; //这时初始设置为0,配置拿不到值的情况
if (form.soft_licence) {
pkid = form.soft_licence; //这是配置拿到值的情况
}
return request({
url: url + pkid + '/', //这是做了一个拼接路由URL地址
}).then((ret: any) => {
return ret.data;
});
},
}),
},
},
},
测试效果:(待补充)
排错指南
makemigrations时提示需要提供默认值
错误描述
执行命令python manager.py makemigrations
时提示如下
sh
PS E:\python_workspace\django\dvadmin\django-vue3-admin\backend> python .\manage.py makemigrations
<class 'list'>
It is impossible to add a non-nullable field 'brand' to cruddemomodel without specifying a default. This is because the database needs something to populate existing 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 manually define a default value in models.py.
Select an option:
原因分析
因为在models.py中增加也字段brand,但没有指定默认值或允许为空。在数据库增加字段时,数据库会检查每一条数据的完整性。要么指定该数据库字段的默认值,要么设置允许为空。
解决方法
选择1表示为现有数据指定一个默认值,选择2表示退出本次makemigrations并自行去修改models.py。建议选择2。
提示请求地址出错: /api/traceability/a/0/
错误描述:登录系统--商品管理--商品信息,提示【请求地址出错: /api/traceability/a/0/】
解决方法:
访问对应后端地址:http://127.0.0.1:8000/api/traceability/a/0/,提示【Page not found (404)】
检查并更正前端请求地址
提示接口地址不正确: /api/traceability/0/
错误描述:登录系统--商品管理--商品信息,提示【接口地址不正确: /api/traceability/0/】
解决方法:
访问对应后端地址:http://127.0.0.1:8000/api/traceability/0/,返回JSON数据为:
json
{
"code": 400,
"data": null,
"msg": "接口地址不正确"
}
检查并更正前端请求地址
参考资料
有任何疑问,欢迎在技术交流区留下您的见解,一起交流成长!