Django中的M——模型

模型Models

数据模型

模型的字段类型

  • CharField(max_length=):字符串类型,参数为长度
  • Boolean field():布尔类型
  • DateField():日期类型,年月日
  • DateTimeField():时间类型,年月日时分秒
    • auto_now_add:第一次创建的时候赋值
    • auto_now:每次修改时候赋值
  • AutoField():自增类型
  • IntegerField():整数类型
  • FloatField():浮点数类型
  • FileField():文件类型
  • ImageField(upload_to=)图片类型,存储路径,参数是路径
    • 依赖于pillow模块
    • 设置MEDIA_ROOT
  • TextField():文本类型
  • DecimalField():固定精度小数
    • max_digits:总位数
    • decimal_places:小数后几位

MEEDIA_ROOT的设置,例如存储用户头像icon,在settings.py中添加其路径:

MEDIA_ROOT = os.path.join(BASE_DIR, 'static/icons')

在模型中定义字段类型和限制为image文件:

class UserModel(models.Model):
    username = models.CharField(max_length=32)
    # upload_to=后面是根据时间生成的路径,在静态文件文件夹里面
    icon = models.ImageField(upload_to="%Y-%M-%D")

当然,我们也可以不用ImageField()属性,自定义存储的位置,然后将路径存储到数据库中

模型参数

  • default:默认值
  • null:是否为空,存储有关,创建记录时可以不传值,用NULL填充
  • blank:是否为空,校验有关,创建记录时可以为空字符串,不允许前端传空字符串,否则400
  • primary_key:主键,有自增属性
  • unique:唯一约束,可以有多个null

属性

数据模型的属性分为显性属性和隐形属性

显性属性包括开发主动声明的模型的属性和方法,还有从父类中继承来的属性和方法。

隐性属性是开发这未声明,自动生成的属性,开发者声明了就不自动生成了

例如模型的objects属性,是一个隐性属性,不需要开发者声明,自动生成,直接调用进行查询过滤,是一个manager实例,用来创建管理模型。

重写这个实例,实现对数据库数据的过滤,使返回的结果只包含没有被逻辑删除的结果。首先创建一个新的manager类,继承自Manager,重写他的get_queryset()方法,实现过滤功能。

class LearnManager(Manager):
    # 重写查询结果集,对数据进行过滤
    def get_queryset(self):
        queryset = super().get_queryset().filter(is_delete=Flase)
        return queryset
    def create_goods(self, g_name, g_price=10):
        goods = self.model()
        goods.g_name = g_name
        goods.g_price = g_price
        goods.save()
        return goods

针对数据的逻辑删除,需要在模型中定义一个删除的属性is_delete,删除是直接操作这个属性,我们在模型中定义这个删除的方法:

class Goods(model.Model):
    is_delte = models.BooleanField(default=False)
    def delete(self, using=None, keeo_parents=False):
        self.is_delete = True
        self.save()
    # 重新定义objects为我盟的模型管理器的实例
    goods_manager = LearnManager()

这样我们的模型就有了一个新的模型管理器goods_manager

在views中使用管理器

# 查询所有没有被逻辑删除的数据
goods = Goods.goods_manager.all()

数据关系

数据之间的管理是认为定义的,分为一对一,一对多,多对多,一对一可以通过数据表中唯一的外键来实现,一对多可以使用不唯一的外键实现,多对对则需要创建一个新的关系表,来表示两个表之间数据的关系

一对一

使用场景,业务拆分时,对现有的表进行拆分,或者对项目扩充,增加字段,直接操作现有表,可能会出现错误,造成无法晚会的损失,创建一个扩展的表是理想的解决方案,可以通过给外键添加唯一约束来实现一对一的关系,例如g_foo = models.ForeignKey(User, unique=True),Django里面自带一个OneToOneField属性用来实现一对一的关系映射。

当操作数据库时,删除主表的内容,从表的数据也会被级联删除,删除从表数据,主表不会受影响。谁声明的一对一关系,谁就是从表

我们假定有两张表,一张用户表UserModel,一张用户权限表VipModel,用户表是主表,权限表是从表。声明关系语句为v_user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)。SET_NULL可以为空。

一对一中的属性:主表获取从表的值,是隐形属性,获取要用模型名,根据用户表获取最后一个用户在权限表中的数据

user = UserModel.objects.last()
# 对象.关联模型(模型名要小写)获取到一条vip数据
vip = user.vipmodel

根据从表获取主表信息是显性属性,直接按字段名就可以获取。如果要获取第一个vip的用户名,则通过权限表,获取用户表的字段

vip = VipModel.objects.first()
# 对象.字段(字段是vip表中的,获取到用户对象)
user = vip.v_user

一对多

一对多的关系和一对一基本一致,使用ForeignKey来实现,默认删除主表数据,从表的数据会被级联删除,可以设置保护模式,使其不被删除。SET_PROTECT

假定我们有一个人的表,一个爱好的表,人的表是主表,定义模型

# 人
class Person(models.Model):
    p_name = models.CharField(max_length=30)
    p_age = models.IntegerField(default=1)

# 爱好
class Hobby(models.Model):
    h_name = models.CharField(max_length=30)
    h_cost = models.FloatField(default=1000)
    # 一对多
    h_person = models.ForeignKey(Person, on_delete=models.PROTECT)

获取级联数据,Django会自动生成一个从表的模型_set管理器,获取从表数据通过它来获取

# 从获取主,显性属性, 对象.字段名
hobby = Hobby.objects.last()
person = hobby.h_person     # 爱好对应的人
# 主获取从,隐性属性, 对象.关联模型_set  [与objects同源,所以用法也是一致]
person = Person.objects.last()
# hobby_set与objects同源,all表示所有数据
hobbies = person.hobby_set.all()  # 人对应的爱好
# 按条件获取
hobbies = person.hobby_set.filter(id=2)

多对多

表现出来的是两个数据表之间的映射,通过第三张表来体现,用ManyToManyField来实现,Django会自动创建第三张表关系表,关系表中会存储两张关联表的id,同样,声明关系的表是从表,并且从表不需要人为干涉。

删除数据时,会自动删除关系表中的级联关系数据

我们以用户和商品的关系,来展示级联数据的获取

class UserModel(models.Model):
    u_name = models.CharField(max_length=32)
class Goods(models.Model):
    g_name = models.CharField(max_length=64)
    g_users = models.ManyToManyField(UserModel)

数据的操作,查询时获取的数据都是复数:

# 数据查询
# 从表获取主表,是显性属性:对象.字段名
goods = Goods.object.last()
user = goods.g_user.all()
# 主表获取从表,是隐形属性:对象.从表_set
user = UserModel.objects.first()
goods = user.Goods_set.all()
# 数据改动
goods = Goods.objects.first()
user = UserModel.objects.last()
user.goods_set.add(goods)  # goods_set是自动生成的模型管理器
goods.g_user.remove(user)
goods.g_user.clear()  # 清楚所有关系数据

删除模式

在声明级联关系的字段中增加’on_delete=xxx’属性,包含以下几个值
写法例如(多对多的关系中没有on_delete属性)

v_user = models.OneToOneField(UserModel, on_deletr=models.SET_NULL, null=True)
  • models.CASECADE:默认模式,默认删除级联数据
  • models.DO_NOTHING:删除关联数据,什么都不做
  • models.PROTECT:保护模式,存在级联数据时,删除会报异常
  • models.SET_XXX
    • SET_NULL:主表级联数据被删时置空(需要指定允许为空)
    • SET_DEFAULT:主表级联数据被删设为默认值(指定默认值)
    • SET():删除时重新指向一个实体对象元素
      • SET(value):删除关联的数据设为指定的值
      • SET(可执行对象):关联值设置为可执行对象的返回值

模型继承

我们所创建的models模型,本身就是继承自models.Model,同样,我们也可以自己定义一个model作为基础父类,把通用的数据存储在父类的模型中。

如果直接迁移,数据库中也会直接生成父类的表,可以在基础模型中定义一个属性class Meta:,来抽象化基础模型。

class BaseModel(models.Model):
    id = models.IntegerField(primary_key=True, unique=True, autoincrement=True)
    class Meta:
        abstract = True

定义abstract属性之后,基础模型就不会在数据库中生成映射

模型和库转换

models --> db

迁移模型生成数据表

db --> models

把数据表映射到模型文件中

python manage.py insectdb > models.py

环境转移:

  1. 导出所有依赖

pip freeze > requirements.txt

  1. 安装所有依赖

pip install -r requirements.txt

猜你喜欢

转载自blog.csdn.net/qq_27114273/article/details/92397401