Django models

每个模型都是一个 Python 的类,继承 django.db.models.Model

模型类的每个属性都相当于一个数据库的字段

Django 提供了一个自动生成访问数据库的 API

1.使用模型

(1)setting.py的INSTALLED_APPS配置models所在的应用

(2)运行命令

manage.py makemigrations

manage.py migrate

2.字段

模型中每一个字段都应该是某个 Field 类的实例, Django 利用这些字段类来实现以下功能:

  • 字段类型用以指定数据库数据类型(如:INTEGER, VARCHAR, TEXT)
  • 在渲染表单字段时默认使用的 HTML 视图 
  • 基本的有效性验证功能,用于 Django 后台和自动生成的表单。

2.1.字段类型

(1)AutoField 自动递增

(2)BooleanField   true/false

(3)CharField  字符串

        字段选项:max_length

(4)DateField  日期

        auto_now=True  每次保存对象时,自动将该字段设置为现在。对于“最后修改”的时间戳很有用。

        auto_now_add=True  当第一次创建对象时,自动将该字段设置为现在。对创建时间戳很有用。

(5)DateTimeField 日期时间

(6)EmailField

(7)ImageField

(8)IntegerField

2.2.通用字段选项

(1)null

如果设置为 True,当该字段为空时,Django 会将数据库中该字段设置为 NULL。默认为 False 。

(2)blank

如果设置为 True,该字段允许为空。默认为 False。

该选项与 null 不同, null 选项仅仅是数据库层面的设置,而 blank 是涉及表单验证方面。如果一个字段设置为 blank=True ,在进行表单验证时,接收的数据该字段值允许为空,而设置为 blank=False 时,不允许为空。

(3)choices

一系列二元组,用作此字段的选项。如果提供了二元组,默认表单小部件是一个选择框,而不是标准文本字段,并将限制给出的选项。

from django.db import models


class Person(models.Model):
    SHIRT_SIZES = [
        ("S", "Small"),
        ("M", "Medium"),
        ("L", "Large"),
    ]
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)


p = Person(name="Fred Flintstone", shirt_size="L")
p.save()
print(p.shirt_size)  # "L"
print(p.get_shirt_size_display())  # "Large"

 (4)default

默认值

(5)primary_key

如果设置为 True ,将该字段设置为该模型的主键。

如果没有对任何一个字段设置 primary_key=True 选项。 Django 会自动添加一个 IntegerField 字段,并设置为主键。

(6)unique

如果设置为 True,这个字段的值必须在整个表中保持唯一。

3.关联关系

3.1.多对一

ForeignKey

3.2.多对多

ManyToManyField

3.3.一对一

OneToOneField

4.Meta类

使用内部 Meta类 来给模型赋予元数据,模型的元数据即“所有不是字段的东西”,

比如排序选项( ordering ),数据库表名( db_table ),权限(permissions)

5.模型方法

模型方法应该在某个对象实例上生效。在模型中添加自定义方法会给对象提供自定义的“行级”操作能力,与之对应的是类 Manager 的方法意在提供“表级”的操作。

5.1.重写已定义的模型方法

5.2.执行自定义SQL

6.模型继承

6.1.抽象基类

(1)概念

        抽象基类在要将公共信息放入很多模型时会很有用。编写基类,并在 Meta 类中填入abstract=True,该模型将不会创建任何数据表。当其用作其它模型类的基类时,它的字段会自动添加至子类。

从抽象基类继承来的字段可被其它字段或值重写,或用 None 删除。

(2)Meta 继承

        抽象基类的子类不会自动地变成抽象类。为了继承一个抽象基类创建另一个抽象基类,需要在子类上显式地设置 abstract=True。

        子类的Meta类,以属性的形式,继承父类的Meta

from django.db import models


class CommonInfo(models.Model):
    # ...
    class Meta:
        abstract = True
        ordering = ["name"]


class Student(CommonInfo):
    # ...
    class Meta(CommonInfo.Meta):
        db_table = "student_info"

        抽象基类的某些 Meta 属性对子类是没用的。比如, db_table

        如果子类从多个抽象基类继承,则默认情况下仅继承第一个列出的类的 Meta 选项。为了从多个抽象类中继承 Meta 选项,必须显式地声明 Meta 继承。

(3)related_name 和 related_query_name  

        若在 外键 或 多对多字段 使用了 related_name 或 related_query_name,必须为该字段提供一个 独一无二 的反向名字和查询名字。这在抽象基类中一般会引发问题,因为基类中的字段都被子类继承,且保持了同样的值(包括 related_name 和 related_query_name)。

        为了解决此问题,当在抽象基类中(也只能是在抽象基类中)使用 related_name 和 related_query_name,部分值需要包含 '%(app_label)s' 和 '%(class)s'。

  • '%(class)s' 用使用了该字段的子类的小写类名替换。
  • '%(app_label)s' 用小写的包含子类的应用名替换。每个安装的应用名必须是唯一的,应用内的每个模型类名也必须是唯一的。因此,替换后的名字也是唯一的。

6.2.多表继承

(1)概念

每个模型都是一个单独的模型,都指向分离的数据表,且可被独立查询和创建。

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)
  

Restaurant 中自动创建的连接至 Place 的 OneToOneField 看起来像这样: 

place_ptr = models.OneToOneField(
    Place,
    on_delete=models.CASCADE,
    parent_link=True,
    primary_key=True,
)

(2)Meta

多表继承情况下,子类不会继承父类的 Meta,但有几个属性除外:若子类未指定 ordering 属性或 get_latest_by 属性,子类会从父类继承这些。

(3)继承与反向关系

如果使用的名字是 ForeignKey 和 ManyToManyField 关系的默认值,在继承父类模型的子类中添加了这些关联,必须 指定 related_name 属性。假如忘了,Django 会抛出一个合法性错误。

class Supplier(Place):
    customers = models.ManyToManyField(Place, related_name='provider')

(4)指定父类连接字段

Django 会自动创建一个 OneToOneField ,将子类连接回非抽象的父类。如果你想修改连接回父类的属性名,你可以自己创建 OneToOneField,并设置 parent_link=True,表明该属性用于连接回父类。

6.3.代理模型

(1)概念

为原模型创建一个 代理。可以创建,删除和更新代理模型的实例,所以的数据都会存储的像使用原模型(未代理的)一样。不同点是可以修改代理默认的模型排序和默认管理器,而不需要修改原模型。

代理模型就像普通模型一样申明。需要告诉 Django 这是一个代理模型,通过将 Meta 类的 proxy 属性设置为 True。

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

(2)基类约束

一个代理模型只能继承自一个非抽象模型类,不能继承多个非抽象模型类,因为代理模型无法在不同数据表之间提供任何行间连接

一个代理模型可以继承任意数量的抽象模型类

一个代理模型也可以继承任意数量的代理模型,只需他们共享同一个非抽象父类。

7.操作数据库

7.1.创建/保存对象

(1)创建对象

b = Blog(name="Beatles Blog", tagline="All the latest Beatles news.")

(2)保存对象

Django 在显式调用 save() 才操作数据库。

(3)创建并保存对象

b3 = Blog.objects.create(name="Blog_3", tagline="All the latest Beatles news.")

(4)保存ForeignKey字段

(5)保存 ManyToManyField字段

7.2.QuerySet

要从数据库查询对象,要通过模型类的 Manager 构建一个 QuerySet。要从数据库查询对象,要通过模型类的 Manager 构建一个 QuerySet在 SQL 的层面上, QuerySet 对应 SELECT 语句,而*filters*对应类似 WHERE 或 LIMIT 的限制子句。

(1)查询全部

all_entries = Entry.objects.all()

(2)过滤器

filter(**kwargs)返回一个新的 QuerySet,包含的对象满足给定查询参数。

exclude(**kwargs)返回一个新的 QuerySet,包含的对象 不 满足给定查询参数。

链式过滤:

Entry.objects.filter(headline__startswith="What").exclude(pub_date__gte=datetime.date.today()).filter(pub_date__gte=datetime.date(2005, 1, 30))

(3)get()查询单个对象

one_entry = Entry.objects.get(pk=1)

如果没有满足查询条件的结果, get() 会抛出一个 DoesNotExist 异常;有不止一个记录满足 get() 查询条件时发出警告。会抛出 MultipleObjectsReturned

(4)跨模型

跨模型使用关联字段名,字段名由双下划线分割,直到拿到想要的字段。 

(5)跨多值关联

每个记录需同时满足

blog_1 = Blog.objects.filter(entry__headline__contains="Lennon", entry__pub_date__year=2023)

相同的记录,满足一个即可

blog_2 = Blog.objects.filter(entry__headline__contains="Lennon").filter(entry__pub_date__year=2023)

例如:

 blog_1返回空,blog_2返回一条记录。

7.3.执行SQL

(1)原生查询

        raw()

(2)直接执行自定义 SQL

对象 django.db.connection 代表默认数据库连接。要使用这个数据库连接,调用 connection.cursor() 来获取一个指针对象。然后,调用 cursor.execute(sql, [params]) 来执行该 SQL 和 cursor.fetchone(),或 cursor.fetchall() 获取结果数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值