Model(模型): 用来与数据做交互(读取和写入数据)
ORM: 对象关系映射 Object Relational Mapping; Python中的Model对象和数据库的表做映射
一、 字段类型
1.1 字段类型介绍
CharField IntegerField 数值类型; choice:枚举类型的数据,元祖的元祖 BooleanField NullBooleanField AutoField int自增列,必须填入参数primary_key=True; auto_create,自动创建 FloatField DecimalField 同Python的Decimal类型;参数:max_digits最大总位数 decimal_places小数点后的位数 TextField UUIDField FileField 字符串,路径保存在数据库,文件上传到指定目录 参数: upload_to=""; storage=None 存储组件,默认django.core.files.storage.FileSystem ImageField 字符串,路径保存在数据库,文件上传到指定目录 upload_to=""; storage=None 默认django.core.files.storage.FileSystem width_field=None 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateField 日期类型; 格式:YYYY-MM-DD 参数: auto_now; auto_now_add DateTimeField 日期时间类型datetime.datetime 日期+时间格式 YYYY-MM-DD HH:MM:ss.uuuuuu[TZ]
1.2 StoreEntity 模型类
1.2.1 编写 mainapp/models.py, 创建 StoreEntity
class StoreEntity(models.Model):
# 默认,模型自动创建主键id, 也可以显式声明主键
id = models.UUIDField(primary_key=True, verbose_name='店号', defaults=uuid.uuid4().hex)
name = models.CharField(max_length=50, verbose_name='店名', unique=True)
store_type = models.IntegerField(choices=((0, '自营'), (1, '第三方')), verbose_name='类型', db_column='type_')
address = models.CharField(max_length=100, verbose_name='地址')
city = models.CharField(max_length=50, verbose_name='城市', db_index=True)
create_time = models.DateField(verbose_name='成立时间', auto_now_add=True, null=True)
last_time = models.DateField(verbose_name='最后变更时间', auto_now=True, null=True)
def __str__(self):
return self.name + '-' + self.city
class Meta:
db_table = 't_store'
verbose_name = '店铺管理'
verbose_name_plural = verbose_name
unique_together = (('name', 'city'), )
1.2.2 查看数据库的表结构
create table t_store
(
id char(32) not null primary key,
name varchar(50) not null unique,
type_ INTEGER not null,
address varchar(100) not null,
city varchar(50) not null,
create_time date,
last_time date
);
create index t_store_city_64bd4797 on t_store (city);
create unique index t_store_name_city_1218e539_uniq on t_store (name, city);
1.2.3 django_migrations 表数据
1.2.4 编写 mainapp/admin.py, 后台管理配置
class StoreAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'city', 'address', 'store_type')
fields = ('name', 'city', 'address', 'store_type') # 指定表单修改的字段
admin.site.register(StoreEntity, StoreAdmin)
1.2.5 后台管理类配置 fieldsets实现分栏显示
ERRORS: # fields 和 fieldsets 不能同时配置 <class 'mainapp.admin.StoreAdmin'>: (admin.E005) Both 'fieldsets' and 'fields' are specified.
class StoreAdmin(admin.ModelAdmin): list_display = ('id_', 'name', 'city', 'address', 'store_type', 'logo', 'summary') # fields = ('name', 'city', 'address', 'store_type', 'logo', 'summary') fieldsets = (['Main', {'fields': ('name',)}], ['Advance', {'fields': ('address',), 'classes': ('collapse',)}])
1.3 UUID类型字段
ModelAdmin 和 ModelForm提供了对UUID格式的验证
1.3.1 使用save()保存 UUID类型的 id字段
id = models.UUIDField(primary_key=True, verbose_name='店号')
# 调用模型保存方法时被调用
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
# 判断是否为新增
if not self.id:
self.id = uuid.uuid4().hex
super().save()
1.3.2 UUID类型字段显示带中划线问题
uuid.uuid4() e5b33241-dd89-4689-8a17-612631cd41be
uuid.uuid4().hex 74a41463c54c4b619d90e597dbbb5b36
class StoreEntity(models.Model): @property def id_(self): # return str(self.id).replace('-', '') # 方法一 return self.id.hex # 方法二 class StoreAdmin(admin.ModelAdmin):
list_display = ('id_', 'name', 'city', 'address', 'store_type') # 展示字段改成 id_
1.4 FileField 和 ImageField
# 模型类中使用上传文件的字段, 文件访问路径是相对MEDIA
MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
1.4.1 编写 helloDjango/urls.py
from django.conf.urls.static import static
urlpatterns = [ ...... ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
1.4.2 编写 heloDjango/mainapp/models.py
logo = models.ImageField(verbose_name='LOGO', upload_to='store',
width_field='logo_width', height_field='logo_height',
null=True, blank=True)
logo_width = models.IntegerField(verbose_name='LOGO宽', null=True)
logo_height = models.IntegerField(verbose_name='LOGO高', null=True)
summary = models.TextField(verbose_name='介绍', blank=True, null=True)
opened = models.BooleanField(verbose_name='是否开业', default=False)
1.4.3 安装Pillow
ERRORS: mainapp.StoreEntity.logo: (fields.E210) Cannot use ImageField because Pillow is not installed. HINT: Get Pillow at https://pypi.org/project/Pillow/ or run command "pip install Pillow".
(venv) E:\PythonLearn\djangoDemo\helloDjango>pip install Pillow
1.5 字段约束
max_legth 最大长度 / default 默认值 / unique 唯一 / primary_key / null / blank /
db_index 索引 / db_column / verbose_name / choices
二、Meta元信息
在模型类中, 声明内部类Meta, 类成员变量包括:
- db_table / ordering / verbose_name / verbose_name_plural / unique_together
- abstract: 布尔类型, 表示当前的模型类是否为抽象类, 如果是抽象类, 则不会创建表
2.1 编写 mainapp/apps.py
from django.apps import AppConfig class MainappConfig(AppConfig): name = 'mainapp' app_label = '主模块'
2.2 在Model模型类定义Meta信息
class CategoryEntity(models.Model): class Meta: app_label = 'mainapp' db_table = 't_category' ordering = ['-order_num'] # 排序字段,- 表示降序 verbose_name = '水果分类' verbose_name_plural = verbose_name