多重继承中的Python非预期MRO

时间:2017-07-13 19:07:54

标签: python django python-3.x inheritance django-rest-framework

我的viewset和mixins有以下类设计。我的问题是,当我从super().create()拨打SomeModelViewSet时,它会调用该视图集被覆盖update()而不是update() MixinA。正在调用MixinA.create(self)吗?

如果设计不好,请提醒我。

免责声明:我从update()致电create()是由于针对某些不常见规范的解决方法

mixins.py

class MixinA(mixins.CreateModelMixin, mixins.UpdateModelMixin):
    def create(self, request, *args, left=None, right=None **kwargs):
        # ...
        self.update(request, left=left, right=right)

    def update(self, request, *args, left=None, right=None, **kwargs):
        # ...

class MixinB(mixins.DestroyModelMixin):
    def destroy(self, request, *args, **kwargs):
        # ...

class MixinC(mixins.ListModelMixin):
    def list(self, request, *args, **kwargs)
        # ...

viewsets.py

class BaseViewSet(MixinC):
    # ...

class MyViewSet(MixinA, MixinB, BaseViewSet):
    pass

views.py

class SomeModelViewSet(MyViewSet):
    def create(self, request, pk=None, **kwargs):
        a = someObj(pk=pk)
        b = someObj(pk=None)
        return super().create(request, left = a, left = b, **kwargs)

    def update(self, request, first_pk=None, second_pk=None, **kwargs):
        a = someObj(pk=first_pk)
        b = someObj(pk=second_pk)
        return super().update(request, left=a, right=b)

    def destroy(self, request, first_pk=None, second_pk=None, **kwargs):
        lookup = {'first__pk': first_pk, 'second_pk': second_pk}
        return super().destroy(request, **lookup)
  

修改

MRO似乎是这样的

SomeModelViewSet.create() -> MixinA.create() -> SomeModelViewSet.update() -> MixinA.update()

我想要的是以下内容,因此self.update()

中的MixinA.create()
SomeModelViewSet.create() -> MixinA.create() -> MixinA.update()

参数leftrightMixinA.create()SomeModelViewSet.update()

之间变化
create(): TripDispatcherViewSet
    # left: Klass(pk='1')
    # right: Klass(pk=None)
create(): IntermediaryModelCreateModelMixin
    # left: Klass(pk='1')
    # right: Klass(pk=None)
update(): TripDispatcherViewSet
    # left: Klass(pk=None)
    # right: Klass(pk=None)
update(): IntermediaryModelCreateModelMixin
    #left: Klass(pk=None)
    # right: Klass(pk=None)

1 个答案:

答案 0 :(得分:1)

通话顺序很有意义。当您致电self.update()时,您要求口译员在update()对象上找到适当的self方法,该方法是根据MRO完成的,因此会找到SomeModelViewSet.update()

所以是的,你可以通过拨打MixinA来解决这个问题。但是,这里的基本问题是您正在调用一个专为继承而设计的API,而实际上并不需要继承的行为。因此,在我看来,更好的设计是通过使用不同的方法明确承认。类似的东西:

MixinA.update(self)

这里的优势在于,您要为class MixinA(mixins.CreateModelMixin, mixins.UpdateModelMixin): def create(self, ...): ... self._my_update(...) def update(self, ...): self._my_update(...) def _my_update(self, ...): ... 分离出update()的API - 这是专为继承而设计的 - 来自您希望为MixinA.create()利用的实现细节。

相关问题