• 【Django】掌握models.py模型文件的使用


    原文作者:我辈李想
    版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。



    前言

    已经有很多人写过相关博客了,我为什么还要写一份呢?这个主要是因为很多文章写的还是很笼统,没法针对使用清晰的进行说明。本博客不是科普如何使用models的,重点关注日常开发中的使用情况,主要介绍类的继承、时间字段、选择字段、文件字段和外键字段。


    一、models类继承

    models类继承主要依赖Meta.abstract参数,以创建一个全局通用BaseModel为例介绍累的继承。

    (一)创建apps文件夹

    (二)settings.py文件配置

    # 项目根目录
    BASE_DIR = Path(__file__).resolve().parent.parent
    sys.path.insert(0, str(BASE_DIR / "apps"))
    
    • 1
    • 2
    • 3

    (三)新建BaseModel

    在app文件夹下新建db.py文件,内容如下:
    在这里插入图片描述

    from django.contrib.gis.db import models
    
    
    class BaseModel(models.Model):
        """模型抽象基类"""
        create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
        update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
        is_delete = models.BooleanField(default=False, verbose_name="删除标记")
    
        class Meta:
            # 说明是一个抽象模型类,此句必须有,否则迁移会失败
            abstract = True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    (四)项目中调用

    from db import BaseModel
    class CartItem(BaseModel):
    	id = models.AutoField(primary_key=True)
    	
        class Meta:
            verbose_name = '购物车'
            verbose_name_plural = '购物车'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    二、时间字段

    之前写过一篇关于python中如何使用时间的一篇博客《【Python】时间标准库处理》,当时就考虑到django在使用时,涉及到时间格式的转化和使用。

    (一)时间字段

    class BaseModel(models.Model):
        """模型抽象基类"""
        create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
        update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    
    • 1
    • 2
    • 3
    • 4

    (二)默认时间

    from django.utils import timezone
    from db import BaseModel
    
    class CartItem(BaseModel):
    	id = models.AutoField(primary_key=True)
        create_time = models.DateTimeField('创建时间(BJ)', default=timezone.now, blank=True)
    	
        class Meta:
            verbose_name = '购物车'
            verbose_name_plural = '购物车'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (三)时间字段允许为空

        transfer_time = models.DateTimeField('星地数传时间', null=True, blank=True, help_text='星地数传时间')
    
    • 1

    三、选择字段(枚举)

    常用的选择字段是models.CharField,还可以使用models.IntegerField。下面我们看看都是如何使用。

    (一)选择的基础

    models.CharField是最常见的,也是使用最多的

    from django.db import models
    
    class Student(models.Model):
        FRESHMAN = "FR"
        SOPHOMORE = "SO"
        JUNIOR = "JR"
        SENIOR = "SR"
        GRADUATE = "GR"
        YEAR_IN_SCHOOL_CHOICES = {
            FRESHMAN: "Freshman",
            SOPHOMORE: "Sophomore",
            JUNIOR: "Junior",
            SENIOR: "Senior",
            GRADUATE: "Graduate",
        }
        year_in_school = models.CharField(
            max_length=2,
            choices=YEAR_IN_SCHOOL_CHOICES,
            default=FRESHMAN,
        )
    
        def is_upperclass(self):
            return self.year_in_school in {self.JUNIOR, self.SENIOR}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    (二)TextChoices枚举

    from django.utils.translation import gettext_lazy as _
    
    
    class Student(models.Model):
        class YearInSchool(models.TextChoices):
            FRESHMAN = "FR", _("Freshman")
            SOPHOMORE = "SO", _("Sophomore")
            JUNIOR = "JR", _("Junior")
            SENIOR = "SR", _("Senior")
            GRADUATE = "GR", _("Graduate")
    
        year_in_school = models.CharField(
            max_length=2,
            choices=YearInSchool,
            default=YearInSchool.FRESHMAN,
        )
    
        def is_upperclass(self):
            return self.year_in_school in {
                self.YearInSchool.JUNIOR,
                self.YearInSchool.SENIOR,
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    如果TextChoices枚举被多次使用,还可以抽象为一个单独的包,供django调用。

    (三)IntegerChoices枚举

    class Card(models.Model):
        class Suit(models.IntegerChoices):
            DIAMOND = 1
            SPADE = 2
            HEART = 3
            CLUB = 4
    
        suit = models.IntegerField(choices=Suit)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (四)选择字段的序列化

    如果使用的是基础的选择方式,django提供了默认的序列化方法 get_year_in_school_dispaly()可供调用。如果选择了TextChoices或者IntegerChoices,需要自己写序列化方法。

    TextChoices示例如下:

    from django.utils.translation import gettext_lazy as _
    
    class Student(models.Model):
        class YearInSchool(models.TextChoices):
            FRESHMAN = "FR", _("Freshman")
            SOPHOMORE = "SO", _("Sophomore")
            JUNIOR = "JR", _("Junior")
            SENIOR = "SR", _("Senior")
            GRADUATE = "GR", _("Graduate")
    
        year_in_school = models.CharField(
            max_length=2,
            choices=YearInSchool,
            default=YearInSchool.FRESHMAN,
        )
        def get_year_in_school_name(self):
            return YearInSchool(self.year_in_school).name
            
        def get_year_in_school_value(self):
            return YearInSchool(self.year_in_school).value
            
        def get_year_in_school_label(self):
            return YearInSchool(self.year_in_school).label
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    以上示例中的name是FRESHMAN ,value是"FR",label是_(“Freshman”),常用的方式为get_year_in_school_label。参考drf序列化

    四、文件字段FileField

    (一)系统默认路径

    class MyModel(models.Model):
        # file will be uploaded to MEDIA_ROOT/uploads
        upload = models.FileField(upload_to="uploads/")
        # or...
        # file will be saved to MEDIA_ROOT/uploads/2015/01/30
        upload = models.FileField(upload_to="uploads/%Y/%m/%d/")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上述示例是系统默认方式,文件最终将被保存至 MEDIA_ROOT 路径下

    (二)自定义路径

    def user_directory_path(instance, filename):
        # file will be uploaded to MEDIA_ROOT/user_/
        return "user_{0}/{1}".format(instance.user.id, filename)
    
    class MyModel(models.Model):
        upload = models.FileField(upload_to=user_directory_path)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    类型描述
    instance模型的实例,其中 FileField 定义。更具体地说,这是附加当前文件的特定实例。
    filename最初提供给文件的文件名。在确定最终目的地路径时,可以考虑,也可以不考虑。

    (三)使用存储服务器

    需要制定storage参数,国内常用的是阿里云、腾讯云、华为云等厂商的存储服务,我们需要在settings.py文件中自定义DEFAULT_FILE_STORAGE 参数。比如django使用阿里云的oss存储需要用django-aliyun-oss2-storage库。

    五、外键字段

    (一)外键的基本使用

    from django.db import models
    
    class Car(models.Model):
        manufacturer = models.ForeignKey(
            "Manufacturer",
            on_delete=models.CASCADE,
        )
    
    class Manufacturer(models.Model):
        # ...
        pass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (二)外键允许为空

    class MissionData(models.Model):
        bill = models.ForeignKey(Bill, verbose_name='消费记录', on_delete=models.SET_NULL, null=True, blank=True)
    
    • 1
    • 2

    (三)自定义中间表

    六、Django用户表扩展

    (一)通过OneToOneField扩展用户表

    (二)通过AbstractUser或AbstractBaseUser扩展用户表

    1.用户app下modles.py文件

    class LoginUser(AbstractUser):
        """用户表"""
        uuid = models.UUIDField(default=uuid.uuid1, unique=True, editable=False)
        name = models.CharField(verbose_name='真实姓名', max_length=30, null=True, blank=True)
        phone = models.CharField(verbose_name='手机号', max_length=11, null=True, blank=True)
        roles = models.ManyToManyField(verbose_name='拥有的所有角色', to='Roles')
    
        class Meta:
            verbose_name = '系统用户'
            verbose_name_plural = '系统用户'
            app_label = 'users'
    
        def __str__(self):
            return self.username
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.修改项目settings文件的AUTH_USER_MODEL 配置参数

    AUTH_USER_MODEL = 'users.LoginUser'
    
    • 1
  • 相关阅读:
    iPaaS中API接口管理平台的作用
    2.1程序的顺序执行与并发执行的特征
    Covalent Network(CQT)构建 Web3 最大的结构化数据集,开拓AI、安全性和数据质量的融合
    Redis源码学习总结一
    [36c3 2019]includer
    WPS ppt怎么设置自动播放?wps ppt如何设置自动放映?
    百度车牌识别AI Linux使用方法-armV7交叉编译
    【Linux】【网络】应用层协议:HTTP
    IDEA创建SparkSQL程序_大数据培训
    细说react源码中的合成事件
  • 原文地址:https://blog.csdn.net/qq_15028721/article/details/132477585