django系列6 - 涉及模型的所有知识点汇总

模型

模型准确且唯一的描述了数据,每一个模型映射一张数据库表,包含了数据的表名、字段、每行数据,
(1)每个模型是一个py类,继承 django.db.models.Model
(2)类属性,映射数据库表字段

1、快速上手定义模型

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

上面 person 模型创建如下数据库表,创建一张数据库表,表名:app名_person,字段是 id、first_name、last_name,并且对字段做了限制,其中id是自动创建的主键,

creat table myapp_persion (
    'id' seial NOT NULL PRIMARY KEY,
    'first_name' varchar(30) NOT NUL,
    'last_name' varchar(30) NOT NULL
);

2、使用模型

你在自己的app中定义了这个模型,要使用它,
(1)需要将app注册到 django 框架中,在settings文件 install_app 字段列表内添加app
(2)使用manage.py工具生成 数据库迁移文件,这个文件用于在数据库创建表格:py manage.py makemigrations
(3)使用manage.py工具将生成的迁移文件转换成数据库表:py manage.py migrate

3、字段

字段在类属性中定义,帝国一字段时应小心避免与模型api的名称冲突,如clean、save、delete

from django.db import models

class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

class Album(models.Model):
    artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    release_date = models.DateField()
    num_stars = models.IntegerField()

4、字段类型

模型中每一个字段都是某个 Field 类的实例,django利用这些字段类实现以下功能:字段类型用以指定数据库数据类型,

  • django 内置了数十种字段类型,常见的字段类型:
  • autofield:主键,一般不需要设置
  • charfield:存储字符串,必须指定长度
  • intergerfild:存在整型
  • booleanfield:存在布尔型
  • foreignkey:1对多
  • datatimefield:存储时间日期
  • manytomanyfield:多对多
from django.db import models

class Project(models.Model):
    # 产品类型列表
    PROJECT_TYPE_CHOICE = (
        (1, "web"),
        (2, "App"),
        (3, "微服务"),
    )
    id = models.AutoField(primary_key=True)  # 自增字段:主键
    name = models.CharField(max_length=200, verbose_name="测试项目名称")  # 项目名称
    version = models.CharField(max_length=20, verbose_name="版本")
    type = models.IntegerField(verbose_name="产品类型", choices=PROJECT_TYPE_CHOICE)  # 32bit
    description = models.CharField(max_length=200, verbose_name="项目描述", blank=True, null=True)
    status = models.BooleanField(default=True, verbose_name="状态")
    created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="创建人", db_column="created_by")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="最近更新时间")
    members = models.ManyToManyField(User, related_name="project_members",
                                   through="ProjectMember",
                                   through_fields=('project', 'user'))

5、字段参数

每种字段都需要指定一些特定的参数,如charfield需要指定 max_length 的值,用以指定数据库存 varchar 数据时用的字节数,一些可选的参数是通用的,如:

  • blank:设置为 null,表示字段输入允许为空,默认false
  • null:设置为 true,当字段输入为空时,django在数据库中将字段设置为NULL
  • choices:对用户而言该字段是可供选择的下拉框,并将限制下拉框的值,用法如上代码。每个二元组的第一个值会储存在数据库中,而第二个值将只会用于在表单中显示。
  • default:是个单选框,单选框默认是选择的,如:status = models.BooleanField(default=True, verbose_name=“状态”),
  • help_text:是个文本提示,在界面上跟控件一起展示
  • primary_key:设置为 true,则将该字段设置该模型的主键,如:id = models.AutoField(primary_key=True),模型中如果没有设置 primary_key,
    则django自动添加一个 integerfield 字段并设为主键。
  • unique:设置为 true,这个字段的值必须在整个表保持唯一
    其他通用字段,参考:https://docs.djangoproject.com/zh-hans/4.0/ref/models/fields/#common-model-field-options

6、自动设置主键

默认情况下,django给每个模型一个自动递增的主键,这个主键类型在应用的apps.py中的 AppConfig.default_auto_field 中指定,在老版本中,这个字段类型是 autofield,新版本如下:

# apps.py
from django.apps import AppConfig
class PollsConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'

7、字段备注名

除了字段foreignkey、 mangtomangfield、onetoonefield,其他字段类型都接受可选参数 verbose_name,如果不指定该值,django默认将字段的属性名,作为该参数值展示在网页上,并把属性名的下划线转换为空格,field类第一个参数为 verbose_name,所以可以省略参数名字,如下:

from django.db import models
# 网页上展示为:个人名字
first_name = models.CharField("个人名字", max_length=30) 
# 网页展示:first name
first_name = models.CharField(max_length=30)

foreignkey、 mangtomangfield、onetoonefield 因为接收的第一个参数为类名,所以可以在后面添加 verbose_name 参数,如:

from django.db import models

class Project(models.Model):
    name = models.CharField("测试项目名称", max_length=200)
    version = models.CharField("版本", max_length=20, verbose_name="版本")
    description = models.CharField("项目描述", max_length=200, blank=True, null=True)
    
class ProjectEnv(models.Model):
    project = models.ForeignKey(Project, on_delete=models.PROTECT, verbose_name="测试项目")

8、关联关系

django提供了定义三种最常见的数据库关联关系:多对一,多对多,一对一

多对一关联

多对一关系使用 django.db.models.ForeignKey类,需要添加一个位置参数,值为要关联的模型类名。建议设置 foreignkey 的字段名一般为 关联的模型名。
场景如下:界面展示为一个下拉框,下拉框关联出 所有我们创建的用户。 我们在管理后台创建了4个用户。我们输入测试项目的信息_创建人时候,会有一个下拉框,关联出我们在用户界面创建的用户

from django.contrib.auth.models import User
from django.db import models

class Project(models.Model):
    # 删除某个user,项目里的这个成员显示为空。意思就是不显示这个成员了
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="创建人", db_column="created_by")
    
class ProjectMember(models.Model):
    # 删除某个项目,项目如果有成员则禁止删除
    project = models.ForeignKey(Project,  on_delete=models.PROTECT, verbose_name="测试项目")
    # 删除某个项目,项目如果有成员可以强制删除项目,并把这个项目的成员信息页删除了。
    project1 = models.ForeignKey(Project,  on_delete=models.CASCADE, verbose_name="测试项目")

更多例子:https://docs.djangoproject.com/zh-hans/4.0/topics/db/examples/many_to_one/

多对多关联

(1)使用 django.db.models.ManyToManyField 类,就和其他 Field 字段类型一样,只需要在你模型中添加一个值为该类的属性。一个披萨中有多个配料,一个配料存在多个披萨中,
对于多对多的模型,可以在任何一个模型中添加manytomanyfield字段,不能同时设置2个,一般情况下,需要将 manytomangfield放到披萨中,因为需要在披萨中编辑它的配料。
如果是测试平台的话,那就是1个项目中可以包含多个成员,1个成员也可以存在多个项目中。为了实现这种多对多的使用功能,我们使用manytomany处理
如下处理:

from django.db import models

class Topping(models.Model):
    # ...
    pass

class Pizza(models.Model):
    # ...
    toppings = models.ManyToManyField(Topping)

(2)多对多中添加额外的属性字段啊
Django 允许你指定用于控制多对多关系的模型。你可以在中间模型当中添加额外的字段。
在实例化 ManyToManyField 的时候使用 through 参数指定多对多关系使用哪个中间模型,
Django 会自动生成一个表来管理多对多关系。但是,如果你想手动指定中间表,你可以使用 through 选项来指定代表你要使用的中间表的 Django 模型。

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__(self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

一对一关联

from django.db import models

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

    def __str__(self):
        return "%s the place" % self.name

class Restaurant(models.Model):
    place = models.OneToOneField(
        Place,
        on_delete=models.CASCADE,
        primary_key=True,
    )
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

    def __str__(self):
        return "%s the restaurant" % self.place.name

class Waiter(models.Model):
    restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
    name = models.CharField(max_length=50)

    def __str__(self):
        return "%s the waiter at %s" % (self.name, self.restaurant)

9、跨文件模型

关联另一个应用中的模型也是可以的,在定义模型的文件开头导入需要被关联的模型。接着就可以在其他有需要的模型类当中关联它了。比如:

from django.db import models
from geography.models import ZipCode

class Restaurant(models.Model):
    zip_code = models.ForeignKey(ZipCode, on_delete=models.SET_NULL, blank=True, null=True,)

10、字段命名限制

  • 模型的字段名不能是py的关键字
  • 字段名不能包含双下划线
  • 字段名不能以下划线开头、结尾
  • sql关键字是可以应用在字段名中

11、meta类

使用内部 meta类 来给模型赋予元数据,模型的元数据就是“所有非字段的内容”,比如:排序、数据库表名、界面名称,这些都不是必须得,在meta类中可选
以下是meta类的可选参数:https://docs.djangoproject.com/zh-hans/4.0/ref/models/options/

from django.db import models


class Base(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()
    m2m = models.ManyToManyField(OtherModel,
        related_name="%(app_label)s_%(class)s_related",
        related_query_name="%(app_label)s_%(class)ss",
    )
    class Meta:
        verbose_name = "pizza"
        verbose_name_plural = "stories"
        index_together = ["pub_date", "deadline"]
        unique_together = [['driver', 'restaurant']]
        proxy = True
        permissions = [('can_deliver_pizzas', 'Can deliver pizzas')]
        get_latest_by = ['-priority', 'order_date']
        db_tablespace = "tables"
        indexes = [models.Index(fields=['shortcut'], db_tablespace='other_indexes')]
        db_table = 'music_album'
        abstract = True
        ordering = ["horn_length"]
class Student(Base):
    home_group = models.CharField(max_length=5)

    
class Question(models.Model):
    text = models.TextField()
class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    class Meta:
        order_with_respect_to = 'question'

class Customer(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    class Meta:
        indexes = [
            models.Index(fields=['last_name', 'first_name']),
            models.Index(fields=['first_name'], name='first_name_idx'),
        ]

class Customer1(models.Model):
    age = models.IntegerField()
    class Meta:
        constraints = [models.CheckConstraint(check=models.Q(age__gte=18), name='age_gte_18'),]

meta类的其他可选参数:

  • default_manager_name
  • default_related_name
  • managed
  • order_with_respect_to
  • default_permissions
  • required_db_features

12、模型属性

objects是 manager的默认名称,manager是django模型和数据库查询操作之间的捷库,并且它被应用于从数据库获取实例。

13、模型方法

__str__()
__eq__()
__hash__()
get_absolute_url()
其他额外的实例方法
我们经常会复写的方法:__str__()、get_absolute_url()

14、模型继承

(1)抽象基类:仅将父类用于子类公共信息的载体,因为你不会想在每个子类中把这些代码都敲一遍

from django.db import models

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

(2)多表继承:若你继承了一个模型(可能来源其它应用),且想要每个模型都有对应的数据表,客官这边请 多表继承。

from django.db import models

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

(3)代理模型:只想修改模型的 Python 级行为,而不是以任何形式修改模型字段

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

class MyPerson(Person):
    class Meta:
        proxy = True

    def do_something(self):
        # ...
        pass

15、如何 管理模型

如果你有很多的models.py文件,如下处理:
创建一个 models 包。删除 models.py,创建一个 myapp/models 目录,包含一个 init.py 文件和存储模型的文件。你必须在 init.py 文件中导入这些模块,比如,若你在 models 目录下有 organic.py 和 synthetic.py:

# myapp/models/__init__.py
from .organic import Person
from .synthetic import Robot
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿_焦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值