Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在django中从单个表检索多态模型,或者如何在django中实现多态行为_Python_Django_Dry - Fatal编程技术网

Python 如何在django中从单个表检索多态模型,或者如何在django中实现多态行为

Python 如何在django中从单个表检索多态模型,或者如何在django中实现多态行为,python,django,dry,Python,Django,Dry,我是否可以从单个数据库表中读取多态模型,它们的行为取决于模型的(布尔)字段 在我的一个模型中,如果实例是“向前”与“向后”或“左”与“右”,则行为略有不同。这导致了大量的if子句和代码重复。因此,我希望有一个向前和向后的模型变体,封装不同的行为 但是,如何让模型管理器返回正确类的实例呢?我是否必须覆盖模型的\uuuuu init\uuuu 也许用一个例子来解释更容易。我在做什么: class Foo(models.Model): forward = models.BooleanField

我是否可以从单个数据库表中读取多态模型,它们的行为取决于模型的(布尔)字段

在我的一个模型中,如果实例是“向前”与“向后”或“左”与“右”,则行为略有不同。这导致了大量的if子句和代码重复。因此,我希望有一个向前和向后的模型变体,封装不同的行为

但是,如何让模型管理器返回正确类的实例呢?我是否必须覆盖模型的
\uuuuu init\uuuu

也许用一个例子来解释更容易。我在做什么:

class Foo(models.Model):
    forward = models.BooleanField()
    other_fields = ...

    def do_foobar(bar):
        if self.forward:
            gap = bar.end_pos - bar.current_pos
            self.do_forward_move(max = gap)
            if self.pos==bar.end_pos:
                and so on ...
        else:
            gap = bar.current_pos - bar.start_pos
            self.do_backward_move(max = gap)
            if self.pos==bar.start_pos:
                and so on ...
我想做的是:

class Foo(models.Model):
    forward = models.BooleanField()
    other_fields = ...

    def __init__(*args, **kwargs):
        """ return ForwardFoo or BackwardFoo 
        depending on the value of 'forward'"""
        How?

    def do_foobar(bar):
        gap = self.calculate_gap(bar)
        self.do_move(max = gap)
        if self.end_point_reached():
            and so on ...

class ForwardFoo(Foo):
    def calculate_gap(bar):
        return bar.end_pos - bar.current_pos
and so on ...

for f in Foo.objects.all():
    f.do_foobar(bar)
还是有完全不同的方法来避免这种代码重复?

代理模型:

class Foo(models.Model):
    # all model attributes here

class ForwardFooManager(models.Manager):
    def get_query_set(self, *args, **kwargs):
        qs = super(ForwardFooManager, self).get_query_set(*args, **kwargs)
        return qs.filter(forward=True)

class ForwardFoo(Foo):
    class Meta:
        proxy = True

    objects = ForwardsFooManager()

    # methods for forward model

class BackwardFooManager(models.Manager):
    def get_query_set(self, *args, **kwargs):
        qs = super(BackwardFooManager, self).get_query_set(*args, **kwargs)
        return qs.filter(forward=False)

class BackwardFoo(Foo):
    class Meta:
        proxy = True

    objects = BackwardFooManager()

    # methods for backward model
上面创建了两个代理模型:一个用于向前,一个用于向后。代理模型没有自己的数据库表;它们使用与从中继承的模型相同的数据库表。(这也意味着您不能向代理模型中添加任何其他字段,只能添加方法。)


还有一个自定义管理器,用于强制每个人只返回属于每个人的项目子集。只要添加您需要的任何特定方法,您就完成了。

太好了,谢谢!到目前为止,我还不知道代理模型。但他们仍然没有做我想做的一切。我仍然必须使用
ForwardFooManager
BackwardFooManager
。我不能简单地调用
Foo.objects.all()
并根据
forward
的值获取
ForwardFoo
BackwardFoo
实例。所以我把这个问题留待讨论,也许有人会想出一个不同的想法。这是不可能的,因为一般来说继承在Python中是如何工作的,特别是在Django中
Foo
将只返回
Foo
对象。看,恐怕你是对的。我将用一个不同的、更一般的问题来重新表述这个问题。也许有人有一个根本不同的想法。无论如何,谢谢你回答我这个有点长的问题。我把你的回答标记为“接受”,因为它给我带来了代理模型的想法。我进一步研究发现,这看起来很有希望。也许我可以将这个用于真正多态查询集的聪明解决方案与代理模型的使用结合起来,从而避免需要多个数据库查询。