【问题标题】:Object creation assigns proxy class based on base model field(s)对象创建根据基本模型字段分配代理类
【发布时间】:2021-11-13 19:39:40
【问题描述】:

我希望能够使用基本模型创建一个对象,但根据对象的字段将该对象实际创建为代理类。

例如,对于以下模型:

class Animal(models.Model):
    species = models.CharField()

class Cat(Animal):
    class Meta:
        proxy = True

class Dog(Animal):
    class Meta:
        proxy = True

我该如何设置它,以便

cat = Animal.objects.create(species="cat")
dog = Animal.objects.create(species="dog")

Animal.objects.all() # Returns queryset of [cat, dog]
Cat.objects.all() # Returns queryset of [cat]
Dog.objects.all() # Returns queryset of [dog]

编辑: 我会对这两种类型的解决方案感兴趣:

a) 首先将对象创建为Animal,然后再转换为代理类

b) 对象直接创建为代理类

(不幸的是,解决方案类型 A 可能与我的用例最相关)

【问题讨论】:

    标签: django django-models django-queryset django-managers


    【解决方案1】:

    Animal 定义一个custom manager,它将基于物种filter the queryset。在这里,我们将使用类名作为物种名称的基础。

    class AnimalManager(models.Manager):
        def get_queryset(self):
            if self.model is Animal:
                return super().get_queryset()
            return super().get_queryset().filter(species=self.model.__name__.casefold())
    
    class Animal(models.Model):
        objects = AnimalManager()
        species = models.CharField(max_length=100)
    
    class Cat(Animal):
        class Meta:
            proxy = True
    
    class Dog(Animal):
        class Meta:
            proxy = True
    

    输出

    >>> from my_app.models import *
    >>>
    >>> # Create the animals
    >>> Animal.objects.create(species="cat")
    <Animal: Animal object (1)>
    >>> Animal.objects.create(species="dog")
    <Animal: Animal object (2)>
    >>> Animal.objects.create(species="cat")
    <Animal: Animal object (3)>
    >>> Animal.objects.create(species="cat")
    <Animal: Animal object (4)>
    >>> Animal.objects.create(species="dog")
    <Animal: Animal object (5)>
    >>>
    >>> # Query the animals
    >>> Animal.objects.all()
    <QuerySet [<Animal: Animal object (1)>, <Animal: Animal object (2)>, <Animal: Animal object (3)>, <Animal: Animal object (4)>, <Animal: Animal object (5)>]>
    >>> Cat.objects.all()
    <QuerySet [<Cat: Cat object (1)>, <Cat: Cat object (3)>, <Cat: Cat object (4)>]>
    >>> Dog.objects.all()
    <QuerySet [<Dog: Dog object (2)>, <Dog: Dog object (5)>]>
    

    【讨论】:

      【解决方案2】:

      您应该为每个代理创建一个custom manager

      class Animal(models.Model):
          species = models.CharField()
      
      class CatManager(models.Manager):
          def get_queryset(self):
              return super().get_queryset().filter(species='cat')
      
      class DogManager(models.Manager):
          def get_queryset(self):
              return super().get_queryset().filter(species='dog')
      
      class Cat(Animal):
          objects = CatManager()
          class Meta:
              proxy = True
      
      class Dog(Animal):
          objects = DogManager()
          class Meta:
              proxy = True
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-16
        • 1970-01-01
        • 2017-07-17
        • 1970-01-01
        • 2014-09-12
        • 1970-01-01
        • 1970-01-01
        • 2011-08-05
        相关资源
        最近更新 更多