繁体   English   中英

具有自定义QuerySet类的Django抽象基础模型

[英]Django abstract base model with custom QuerySet class

我正在使用类似于T.Stone在这个问题上的答案的方法。 但是,我添加了一个抽象基类,因此我的models.py如下所示:

class CustomQuerySetManager(models.Manager):
    """A re-usable Manager to access a custom QuerySet"""
    def __getattr__(self, attr, *args):
        try:
            return getattr(self.__class__, attr, *args)
        except AttributeError:
            return getattr(self.get_query_set(), attr, *args)

    def get_query_set(self):
        return self.model.QuerySet(self.model)

class MyModel(models.Model): 
    class Meta:
        abstract = True

    class QuerySet(QuerySet):
        def user(self, pub, *args, **kwargs):
            return self.filter(publisher=pub, *args, **kwargs)

    ...some more methods here

class Book(MyModel):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author, related_name='book_author')
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()

    objects=models.Manager()
    obj=CustomQuerySetManager() #for testing purposes only, this will override objects later

这样,我就可以为给定的出版商获得所有书籍,例如:

p = Publisher.object.get(pk=1)
Book.obj.user(p).all()

我想扩展它,以便我可以在Book模型中定义一个自定义查询,然后将Q对象传递给QuerySet类,因此查询“ publisher = pub”对于不同的模型可以是不同的。 我仍然希望能够像Book.obj.user(p).all()这样称呼它。 在Book模型中,我需要:

pubQ=Q(publisher=pub)

我可以在哪里放置它,以及如何将其传递给Abstract Base Class中定义的QuerySet,同时使代码尽可能保持DRY?

这个答案很聪明,但是它打破了Python的“显式优于隐式”的原则。 我对您的代码的第一反应是告诉您,您无法模型中声明自定义查询集,但是我决定检查所提及的SO答案,以了解从何处获得该想法。 再次,这很聪明-不能轻视它,但是写得很好的代码是自记录的,应该可以被任何随机的Django开发人员使用并运行。 在那里,对等代码审查非常方便-如果您有一个,那么您将立即获得一个WTF。

Django核心团队通过以下方式进行操作:

class MyQuerySet(models.query.QuerySet):
    def some_method(self, an_arg, another_arg, a_kwarg='some_value'):
        # do something
        return a_queryset

class MyManager(models.Manager):
    def get_query_set(self):
        return MyQuerySet(self.model)

    def some_method(self, *args, **kwargs):
        return self.get_query_set().some_method(*args, **kwargs)

从某种意义上讲,它是DRY,您无需在管理器中重复实际的方法定义。 但是,它也很明确-您确切知道发生了什么。 它不像您所引用的方法那样干 ,而是“显式优于隐式”。 此外,如果在实际的Django代码库中以这种方式完成操作,则可以合理地确信,在自己的代码中这样做是个好习惯。 而且,它的副作用是可以更轻松地扩展和覆盖子类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM