Django(四):模型

一、模型

模型是有关数据的单一,明确的信息来源。它包含您要存储的数据的基本字段和行为。通常,每个模型都映射到单个数据库表。

1、配置数据库

这里我们先去配置数据库:需要在setting.py 中进行配置,Django默认配置了数据库,默认数据库为sqlte3

# 这是默认的数据库配置 我们可以看到数据库默认是sqlte3,我这里将他改成mysql数据库,
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

配置mysql数据库,修改成下面的代码:

DATABASES = {
    'default': {
        # 使用哪种数据库
        'ENGINE': 'django.db.backends.mysql', 
        # 数据库的名字,数据库必须提前创建好
        'NAME': 'test_django',
        # 数据库登录用户
        'USER':'root',
        # 数据库登录密码
        'PASSWORD':'mysql'
    }
}

在这里插入图片描述

2、创建一个模型类:

book_test/models.py 中编写代码:

from django.db import models # 导入models

class BookInfo(models.Model):
    name = models.CharField(max_length=20)
    gender = models.BooleanField(default=0)
    pub_date = models.DateField()
    is_delete = models.BooleanField(default=False)

执行下面命令生成迁移文件:

python manage.py makemigrations

在这里插入图片描述
生成数据表,执行下面命令:

python manage.py migrate

在这里插入图片描述

数据表字段和model类 属性对比:
在这里插入图片描述

  • 表名book_test_book_info 由Django自动生成,默认格式为‘项目名称(book_test)+下划线+小写类名(book_info)’,这个你可以使用models.Manage 重写表名,我们后面再说
  • Django默认自动创建主键id,当然你也可以指定主键

3、模型的字段fields

字段是模型中最重要的内容之一,也是唯一必须的部分,字段在python中表现为一个类属性,体现了数据表中的一个列,请不要使用clean,save,delete 等Django内置的模型API名字,防止名字冲突

字段命名约束:(不能出现一些命名方法)
  • 与python关键字冲突
  • 字段名中不能用两个以上的下划线,两个下划线是Django的查询语法。
字段的常用类型:
  • 决定数据库中对应类的数据类型(如:int,varchar,text)
  • HTML中对应的表单标签的类型,例如< input type=“text” />
  • 在admin后台和自动生成的表单中最小的数据验证需求

Django内置了许多字段类型,它们都位于django.db.models中,下表列出了所有Django内置的字段类型,但不包括关系字段类型(字段名采用 驼峰命名法 ,初学者请一定要注意)

类型说明
AutoField一个自动增长的整数类型字段,通常你不需要自己编写它,Django会自动帮你添加字段:id = models.AutoField(primary_key=True),这是一个自增字段,从1开始计数。如果你非要自己设置主键,那么请务必将字段设置为primary_key=True。Django在一个模型中只允许有一个自增字段,并且该字段必须为主键!
BooleanField布尔值类型。默认值是None。在HTML表单中体现为CheckboxInput标签。如果要接收null值,请使用NullBooleanField。
CharField字符串类型。必须接收一个max_length参数,表示字符串长度不能超过该值。默认的表单标签是input text。最常用的filed,没有之一!
DateFieldclass DateField(auto_now=False, auto_now_add=False, **options)日期类型。一个Python中的datetime.date的实例。在HTML中表现为TextInput标签。在admin后台中,Django会帮你自动添加一个JS的日历表和一个“Today”快捷方式,以及附加的日期合法性验证。两个重要参数:(参数互斥,不能共存) auto_now:每当对象被保存时将字段设为当前日期,常用于保存最后修改时间。auto_now_add:每当对象被创建时,设为当前日期,常用于保存创建日期(注意,它是不可修改的)。设置上面两个参数就相当于给field添加了editable=False和blank=True属性。如果想具有修改属性,请用default参数。例子:pub_time = models.DateField(auto_now_add=True),自动添加发布时间。
TextField大量文本内容,在HTML中表现为Textarea标签,最常用的字段类型之一!如果你为它设置一个max_length参数,那么在前端页面中会受到输入字符数量限制,然而在模型和数据库层面却不受影响。只有CharField才能同时作用于两者,超过4000字节时使用
FileField上传文件字段(不能设置为主键)。默认情况下,该字段在HTML中表现为一个ClearableFileInput标签。在数据库内,我们实际保存的是一个字符串类型,默认最大长度100,可以通过max_length参数自定义。真实的文件是保存在服务器的文件系统内的。
class FileField(upload_to=None, max_length=100, **options)[source]

4、字段的参数:

所有的模型字段都可以接收一定数量的参数,比如CharField至少需要一个max_length参数。下面的这些参数是所有字段都可以使用的,并且是可选的。

  • null
    该值为True时,Django在数据库用NULL保存空值。默认值为False。对于保存字符串类型数据的字段,请尽量避免将此参数设为True,那样会导致两种‘没有数据’的情况,一种是NULL,另一种是‘空字符串’。
  • blank
    True时,字段可以为空,默认为False。和null参数不同的是,null是纯数据库层面的,而blank是验证相关的,它与表单验证是否允许输入框内为空有关。所以要小心一个null为False,blank为True的字段接收到一个空值可能会出bug或异常。
  • choices
    用于页面上的选择框标签,需要先提供一个二维的二元元组,第一个元素表示存在数据库内真实的值,第二个表示页面上显示的具体内容。在浏览器页面上将显示第二个元素的值。例如:
YEAR_IN_SCHOOL_CHOICES = (
        ('FR', 'Freshman'),
        ('SO', 'Sophomore'),
        ('JR', 'Junior'),
        ('SR', 'Senior'),
        ('GR', 'Graduate'),
    )

最好将选项定义在类里,并取一个直观的名字

from django.db import models

class Student(models.Model):
    FRESHMAN = 'FR'
    SOPHOMORE = 'SO'
    JUNIOR = 'JR'
    SENIOR = 'SR'
    YEAR_IN_SCHOOL_CHOICES = (
        (FRESHMAN, 'Freshman'),
        (SOPHOMORE, 'Sophomore'),
        (JUNIOR, 'Junior'),
        (SENIOR, 'Senior'),
    )
    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)

获取一个choices的第二个元素的值,可以使用get_XXX_display()方法,其中的XXX用字段名代替。

  • db_column
    该参数用于定义当前字段在数据表中的列名。未指定这个参数时,Django将使用字段名为列名。

  • db_index
    该参数接收布尔值。如果为True,数据库将为该字段创建索引。

  • default
    字段的默认值,可以是值也可以是一个可调用对象。若是可调用对象,那么每次创建对象时都会被调用。设置的默认值不能是可变参数。匿名函数也不可用于default调用的对象,匿名函数不能被migrations序列化。
    error_messages
    用于自己定义错误的信息,该参数接收字典类型的值。字典的键可以是null、blank、invalid、invalid_choice、unique或unique_for_date。

  • help_text
    显示在表单部件上的帮助文本。使用时转义成纯文本、以免脚本攻击。

  • primary_key
    如果你没有给模型的任何字段设置这个参数为True,Django将自动创建一个AutoField自增字段,名为‘id’,并设置为主键。也就是id = models.AutoField(primary_key=True)。
    如果你为某个字段设置了primary_key=True,则当前字段变为主键,并关闭Django自动生成id主键的功能。
    primary_key=True隐含null=False和unique=True的意思。一个模型中只能有一个主键字段!

  • unique
    设为True时,在整个数据表内该字段的数据不可重复。
    注意:
    ①对于ManytoManyField 和 OnetoOneField 关系类型,该参数无效。
    ②当unique=True 时,db_index 参数无效设置,因为unique 隐含了索引

  • ③从1.11 版本后,unique参数可用于FileField 字段。

5、模型中的元数据:

模型的元数据,指的是“除了字段外的所有内容”,例如排序方式、数据库表名、人类可读的单数或者复数名等等。所有的这些都是非必须的,甚至元数据本身对模型也是非必须的。定义方式:在模型类中添加子类Meta,必须是Meta类。

from django.db import models

class Employee(models.Model):
	name = models.CharField(max_length=20)
	salary = models.IntegerField(default=0)
	class Meta:
		"""元数据"""
		ordering= ["salary"]	# 排序
		db_table = 'employee' # 给数据表命名

每个模型都可以有自己的元数据类,每个元数据只能对自己的所在模型起作用。下面介绍元数据部分选项:

选项说明
abstract当abstract=True时,这个模型将是一个抽象基类
app_label在应用程序之外定义模型 INSTALLED_APPS,则必须声明它属于哪个应用程序:app_label = ‘test_app’
base_manager_name模型管理器的名字(模型管理器我们后面讲)
db_table用于数据表的名字, db_table=表名 ,当定义这个之后,Django不在自动派生数据表的名字
ordering对象的默认顺序,默认为升序,若是想降序的话就在字段名称前加 -,想按多个字段排序,只需在列表中按顺序写出即可 ,例如:按出版日期降序,价格升序 ordering = ["-pub_date",“price”]
proxy将另一个模型子类化的模型视为代理模型。proxy = True
indexes在模型上定义的索引列表 :indexes = [
models.Index(fields=[‘last_name’, ‘first_name’]),
models.Index(fields=[‘first_name’], name=‘first_name_idx’),]
unique_together当多个字段同时使用时,考虑唯一性:unique_together = (“driver”, “restaurant”)
label对象的表示:polls.Question
label_lower表示模型

二、关系型字段:

1、多对一(ForeignKey)

多对一的关系,通常被称为外键。外键字段类的定义如下:

class ForeignKey(to, on_delete, **options)[source]

外键需要两个位置参数,一个是关联模型(及要关联的类),另一个是on_delete选项,外键的定义在多的一方:
图书类 - 英雄类

# 图书类
class BookInfo(models.Model):
    name = models.CharField(max_length=20)
    pub_date = models.DateField()
    is_delete = models.BooleanField(default=False)
# 英雄类
class HeroInfo(models.Model):
	name = models.CharField(max_length=20)
	vote= models.IntegerField(default=0)
	# 外键,连接图书类
	book = models.ForeignKey(BookInfo, on_delete=models.CASCADE)

on_delete 参数说明(该参数的可选值都在django.db.models中):

  • CASCADE:模拟SQL语言中的ON DELETE CASCADE约束,将定义有外键的模型对象同时删除!(该操作为当前Django版本的默认操作!)
  • PROTECT:阻止上面的删除操作,但是弹出ProtectedError异常
  • SET_NULL:将外键字段设为null,只有当字段设置了null=True时,方可使用该值。
  • SET_DEFAULT:将外键字段设为默认值。只有当字段设置了default参数时,方可使用。
  • DO_NOTHING:什么也不做。
  • SET():设置为一个传递给SET()的值或者一个回调函数的返回值。注意大小写。

2、多对多(ManyToManyField)

多对多关系在数据库中也是非常常见的关系类型。比如一本书可以有好几个作者,一个作者也可以写好几本书。多对多的字段可以定义在任何的一方,请尽量定义在符合人们思维习惯的一方,但不要同时都定义。

class ManyToManyField(to, **options)[source]

实例:

class Student(models.Model):
	name = models.CharField(max_length=20)
	age = models.IntergeField(default=0)
	# 多对多关联 ManyToManyField(可以定义在两张表的任意一张中,尽量定义在符合大众逻辑的表中)
	sport = models.ManyToManyField(Sport)
	def __str__(self):
		return self.name
class Sport(models.MOdel):
	sport = models.CharField(max_length=20)
	def __str__(self):
		return self.sport 

多对多我们会使用中间表,将两张表关联起来(默认):
首先有一列id,这是Django默认添加的,没什么好说的。然后是Student和Sport的id列,这是默认情况下,Django关联两张表的方式。如果你要设置关联的列,可以使用to_field参数。
在这里插入图片描述
自定义中间表:

class Student(models.Model):
	"""学生"""
	name = models.CharField(max_length=20)
	age = models.IntergeField(default=0)
	# 多对多关联 ManyToManyField(可以定义在两张表的任意一张中,尽量定义在符合大众逻辑的表中)
	sport = models.ManyToManyField(Sport)
	def __str__(self):
		return self.name
class Sport(models.Model):
	"""喜欢的运动"""
	sport = models.CharField(max_length=20)
	def __str__(self):
		return self.sport 
class MiddleTable(models.Model):
	"""中间表:在中间表中,我们至少要编写两个外键字段,分别指向关联的两个模型"""
	student = models.ForeignKey(Student,on_delete=models.CASCADE)
	sport= models.ForeignKey(Sport,on_delete=models.CASCADE)
	

与普通的多对多不一样,使用自定义中间表的多对多不能使用add(), create(),remove(),和set()方法来创建、删除关系,clear()方法是有效的,它能清空所有的多对多关系。

3、一对一(OneToOneField)

一对一关系类型的定义如下:

class OneToOneField(to, on_delete, parent_link=False, **options)[source]

从概念上讲,一对一关系非常类似具有unique=True属性的外键关系,但是反向关联对象只有一个。这种关系类型多数用于当一个模型需要从别的模型扩展而来的情况。比如,Django自带auth模块的User用户表,如果你想在自己的项目里创建用户模型,又想方便的使用Django的认证功能,那么一个比较好的方案就是在你的用户模型里,使用一对一关系,添加一个与auth模块User模型的关联字段。

该关系的第一位置参数为关联的模型,其用法和前面的多对一外键一样。
如果你没有给一对一关系设置related_name参数,Django将使用当前模型的小写名作为默认值。看下面的列子:

from django.conf import settings
from django.db import models

# 两个字段都使用一对一关联到了Django内置的auth模块中的User模型
class MySpecialUser(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    supervisor = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='supervisor_of',
    )

这样下来,你的User模型将拥有下面的属性:

>>> user = User.objects.get(pk=1)
>>> hasattr(user, 'myspecialuser')
True
>>> hasattr(user, 'supervisor_of')
True

4、跨模块的模型

有时候,我们关联的模型并不在当前模型的文件内,没关系,就像我们导入第三方库一样的从别的模块内导入进来就好,如下例所示:

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,
    )
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值