Django-模型层:抽象基类、自定义管理器的使用

我的Django版本==1.8.2 数据库为mysql

参考文档:
django1.8.2–模型继承–抽象基类
django1.8.2—模型管理器

抽象基类

通常,你想使用父模型类来持有一些字段,如创建时间、更新时间等,而不想在每个子模型中都敲一遍。这个父模型类永远不会单独使用,这就是抽象基类。

我使用的案例:

  1. 在项目路径下新建python package命名常取’db’,在其中创建base_model.py
    Django-模型层:抽象基类、自定义管理器的使用_第1张图片
    代码如下:
from django.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

编写完基类之后,在 Meta类中设置 abstract=True这个模型就不会被用来创建任何数据表。取而代之的是,当它被用来作为一个其他model的基类时,它的字段将被加入那些子类中。
如:下面的模型类设置了两个字段,但是继承于BsaeModel基类在产生数据表时会有额外三个字段。

from django.db import models
from db.base_model import BaseModel

class Goods(BaseModel):
    """商品SPU模型类"""
    name = models.CharField(max_length=20, verbose_name='商品SPU名称')
    # 富文本类型:带有格式的文本
    detail = HTMLField(blank=True, verbose_name='商品详情')

    class Meta:
        db_table = 'df_goods'
        verbose_name = '商品SPU'
        verbose_name_plural = verbose_name
mysql> desc df_goods;
+-------------+-------------+------+-----+---------+----------------+
| Field       | Type        | Null | Key | Default | Extra          |
+-------------+-------------+------+-----+---------+----------------+
| id          | int(11)     | NO   | PRI | NULL    | auto_increment |
| create_time | datetime(6) | NO   |     | NULL    |                |
| update_time | datetime(6) | NO   |     | NULL    |                |
| is_delete   | tinyint(1)  | NO   |     | NULL    |                |
| name        | varchar(20) | NO   |     | NULL    |                |
| detail      | longtext    | NO   |     | NULL    |                |
+-------------+-------------+------+-----+---------+----------------+
6 rows in set (0.04 sec)

注意:如果抽象基类和它的子类有相同的字段名,那么将会出现error(并且Django将抛出一个exception)。

管理器

管理器是Django 的模型进行数据库查询操作的接口。Django 应用的每个模型都拥有至少一个管理器。
默认情况下,Django 为每个模型类添加一个名为objects的管理器。
可在模型中定义一个值为models.Manager()的属性,来重命名管理器。例如:

from django.db import models

class Person(models.Model):
    #...
    people = models.Manager()

使用例子中的模型, Person.objects会抛出AttributeError异常,而Person.people.all()会返回一个包含所有Person对象的列表。

1.自定义管理器

你可以在模型中使用自定义的管理器,方法是继承Manager基类并实例化你的自定义管理器。
你有两个原因可能会自己定义管理器:向管理器类中添加额外的方法,或者修改管理器返回的原始查询集。
例如:在应用的models.py中编写

class AddressManager(models.Manager):
    """地址模型管理器类"""
    # 1.改变原有查询的结果集:all()
    # 2.封装方法:用于操作模型类对应的数据表(增删改查)
    def get_default_address(self, user):
        """获取用户默认收货地址"""
        try:
        	# 这里其实可以看成self=Address.objects
            address = self.get(user=user, is_default=True)
        except self.model.DoesNotExist:
            # 不存在默认收货地址
            address = None
        return address


class Address(BaseModel):
    """地址模型类"""
    user = models.ForeignKey('User', verbose_name='所属账户')
    receiver = models.CharField(max_length=20, verbose_name='收件人')
    addr = models.CharField(max_length=256, verbose_name='收件地址')
    zip_code = models.CharField(max_length=6, null=True, verbose_name='邮政编码')
    phone = models.CharField(max_length=11, verbose_name='联系电话')
    is_default = models.BooleanField(default=False, verbose_name='是否默认')

    # 实例化模型管理器对象
    objects = AddressManager()

之后在视图层便可以简化代码(注释部分为未使用自定义管理器时的代码):

        # try:
        #     address = Address.objects.get(user=user, is_default=True)
        # except Address.DoesNotExist:
        #     address = None
        address = Address.objects.get_default_address(user)

这个例子的目的其实就是为了后台在查询用户的默认地址时,不会抛出异常,而返回None,我们把这个步骤封装在模型管理器类里面了。

除以上内容外还需注意:
同一模型使用多个管理器。你可以依据你自己的偏好在一个模型里面添加多个 Manager() 实例。
在这里插入图片描述

2.修改管理器的原始查询集

你可以通过重写Manager.get_queryset() 方法来覆盖管理器自带的Queryset.get_queryset() 会根据你所需要的属性返回查询集。

例如,下面的模型有两个管理器,一个返回所有的对象,另一个则只返回作者是Roald Dahl 的对象:

# First, define the Manager subclass.
class DahlBookManager(models.Manager):
    def get_queryset(self):
        return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl')

# Then hook it into the Book model explicitly.
class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)

    objects = models.Manager() # The default manager.
    dahl_objects = DahlBookManager() # The Dahl-specific manager.

在这个例子中,Book.objects.all()将返回数据库中所有的图书。而 Book.dahl_objects.all() 只返回作者是 Roald Dahl 的图书。

当然,因为get_queryset()返回QuerySet对象,可以使用filter()exclude()和所有其他QuerySet方法。所以下面这些例子都是可用的:

Book.dahl_objects.all()
Book.dahl_objects.filter(title='Matilda')
Book.dahl_objects.count()

你可能感兴趣的:(django,mysql,python)