一、简介
模型是有关您的数据的唯一、明确的信息来源。它包含您存储的数据的基本字段和行为。通常,每个模型都映射到一个数据库表。
基础知识:
每个模型都是一个 Python 类,它是 django.db.models.Model
.
模型的每个属性代表一个数据库字段。
有了这一切,Django 为您提供了一个自动生成的数据库访问 API。
示例
rom django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30)
first_name
并且last_name
是模型的字段。每个字段都被指定为一个类属性,每个属性映射到一个数据库列。
上面的Person
模型会创建一个这样的数据库表:
CREATE TABLE myapp_person ( "id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, "first_name" varchar(30) NOT NULL, "last_name" varchar(30) NOT NULL );
二、使用
一旦你定义了你的模型,你需要告诉 Django 你将要使用 这些模型。通过编辑您的设置文件并更改 INSTALLED_APPS
设置以添加包含您的models.py
.
例如,如果您的应用程序的模型存在于模块中 (由脚本 myapp.models
为应用程序创建的包结构),部分内容应为:manage.py startapp
INSTALLED_APPS
INSTALLED_APPS = [ #... 'myapp', #... ]
三、字段
模型最重要的部分——也是模型唯一需要的部分——是它定义的数据库字段列表。字段由类属性指定。注意不要选择与 模型 API冲突的字段名称
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()
四、字段类型
AutoField #IntegerField根据可用 ID 自动递增的。通常不需要直接使用它;如果没有另外指定,主键字段将自动添加到模型中 BigAutoField #一个 64 位整数,很像 an ,AutoField只是它保证适合从1到的数字9223372036854775807 BigIntegerField #一个 64 位整数,很像 an ,IntegerField只是它保证适合从-9223372036854775808到 的数字9223372036854775807。此字段的默认表单小部件是 NumberInput. BinaryField #存储原始二进制数据的字段。它可以被分配bytes、 bytearray或memoryview。 BooleanField #真/假字段。 #此字段的默认表单小部件是CheckboxInput, 或NullBooleanSelectif null=True。 CharField #一个字符串字段,用于小到大的字符串。 #对于大量文本,请使用TextField. #此字段的默认表单小部件是TextInput DateField #日期,在 Python 中由datetime.date实例表示 DateTimeField #日期和时间,在 Python 中由datetime.datetime实例表示 DecimalField #一个固定精度的十进制数,在 Python 中由一个 Decimal实例表示 DurationField #用于存储时间段的字段 - 在 Python 中由 timedelta. 在 PostgreSQL 上使用时,使用的数据类型是 an interval,而在 Oracle 上,数据类型是. 否则使用 a微秒 EmailField #ACharField使用 . 检查该值是否为有效的电子邮件地址 EmailValidator。 FileField #文件上传字段 FilePathField #ACharField其选择仅限于文件系统上某个目录中的文件名 FloatField #float在 Python 中由实例表示的浮点数。 GenericIPAddressField #Pv4 或 IPv6 地址,采用字符串格式(例如192.0.2.30或 2a02:42fe::4)。 ImageField #从 继承所有属性和方法FileField,但也验证上传的对象是有效的图像。 #除了可用于 的特殊属性外FileField,并且ImageField还具有height和width属性。 IntegerField #一个整数。从-2147483648to的值2147483647在 Django 支持的所有数据库中都是安全的 JSONField #用于存储 JSON 编码数据的字段。在 Python 中,数据以其 Python 原生格式表示:字典、列表、字符串、数字、布尔值和 None. TextField #一个大的文本字段 TimeField #一个时间,在 Python 中由一个datetime.time实例表示 URLField #ACharField代表 URL,由 . 验证 URLValidator UUIDField #用于存储通用唯一标识符的字段。使用 Python 的 UUID类。在 PostgreSQL 上使用时,它以 uuid数据类型存储,否则以char(32). ForeignKey #多对一的关系。需要两个位置参数:模型相关的类和on_delete选项。 #要创建递归关系(与自身具有多对一关系的对象),请使用.models.ForeignKey('self', on_delete=models.CASCADE) #如果需要在尚未定义的模型上创建关系,可以使用模型的名称,而不是模型对象本身 ManyToManyField #多对多的关系。需要一个位置参数 OneToOneField #一对一的关系
五、字段选项
每个字段都采用一组特定于字段的参数(记录在 模型字段参考中)。例如, CharField
(及其子类)需要一个 max_length
参数,该参数指定VARCHAR
用于存储数据的数据库字段的大小。
from django.db import models class Person(models.Model): name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
六、自动主键
默认情况下,Django 为每个模型提供一个自动递增的主键,其类型在每个应用程序中或在设置中AppConfig.default_auto_field
全局 指定。DEFAULT_AUTO_FIELD
例如:
id = models.BigAutoField(primary_key=True)
七、模型继承
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)
该Student
模型将具有三个字段name
:age
和 home_group
。该CommonInfo
模型不能用作普通的 Django 模型,因为它是一个抽象基类。它不生成数据库表,也没有管理器,不能直接实例化或保存。
从抽象基类继承的字段可以用另一个字段或值覆盖,或者用None
.
对于许多用途,这种类型的模型继承将正是您想要的。它提供了一种在 Python 级别分解常见信息的方法,同时仍然在数据库级别为每个子模型创建一个数据库表。
抽象基类的Meta继承
创建抽象基类时,Django 在基类中声明的任何Meta 内部类都可用作属性。如果子类没有声明自己的Meta 类,它将继承父类的Meta。如果孩子想要扩展父母的Meta类,它可以继承它。
2、多表继承
Django 支持的第二种模型继承类型是层次结构中的每个模型都是单独的模型。每个模型对应自己的数据库表,可以单独查询和创建。继承关系引入了子模型与其每个父模型之间的链接(通过自动创建的OneToOneField
)。例如:
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 行为——可能是更改默认管理器,或者添加新方法。
这就是代理模型继承的用途:为原始模型创建代理。可以创建、删除和更新代理模型的实例,所有数据都将被保存,就像使用原始(非代理)模型一样。不同之处在于您可以更改默认模型排序或代理中的默认管理器等内容,而无需更改原始内容
代理模型像普通模型一样被声明。通过将类的proxy
属性设置为 来告诉 Django 它是一个代理模型。Meta
True
例如,假设您想向Person
模型添加一个方法。可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
八、数据库迁移
migrate,它负责应用和取消应用迁移。
makemigrations,它负责根据您对模型所做的更改创建新的迁移。
sqlmigrate,它显示迁移的 SQL 语句。
showmigrations,其中列出了项目的迁移及其状态
九、执行原声sql
1、raw()
此方法接受原始 SQL 查询,执行它并返回一个 django.db.models.query.RawQuerySet
实例。这个RawQuerySet
实例可以像普通一样被迭代QuerySet
以提供对象实例。
class Person(models.Model): first_name = models.CharField(...) last_name = models.CharField(...) birth_date = models.DateField(...)
for p in Person.objects.raw('SELECT * FROM myapp_person'): print(p)
2、自定义sql
连接数据库
django.db.connection
表示默认的数据库连接。要使用数据库连接,请调用connection.cursor()
以获取游标对象。然后,调用以执行 SQL或返回结果行。cursor.execute(sql, [params])
cursor.fetchone()
cursor.fetchall()
from django.db import connection def my_custom_sql(self): with connection.cursor() as cursor: cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz]) cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz]) row = cursor.fetchone() return row
为了防止 SQL 注入,您不能%s
在 SQL 字符串中的占位符周围包含引号。
请注意,如果要在查询中包含文字百分号,则必须在传递参数的情况下将它们加倍:
cursor.execute("SELECT foo FROM bar WHERE baz = '30%'") cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' AND id = %s", [self.id])
十、orm
对象关系映射,它实现了对象和关系型数据库之间的数据交互,提高了开发效率。在实际开发中,常见的增删改查(CRUD)操作都可以交给 ORM,避免了手写 SQL 语句的麻烦。
all(): #查询所有结果,结果是queryset类型 filter(**kwargs): # 它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 get(**kwargs): #返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。 exclude(**kwargs): # 排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 order_by(*field): #queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型 reverse(): # queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型 count(): #queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。 first(): # queryset类型的数据来调用,返回第一条记录 last(): #queryset类型的数据来调用,返回最后一条记录,结果为model对象类型 exists(): #queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False values(*field): #用的比较多,queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。 values_list(*field): #它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 distinct(): #values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录,结果还是queryset
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通