0

私の質問は、モデルと関連モデルの両方に同一の QuerySet メソッドを提供する QuerySet Mixin の作成に関するものです。これがサンプルコードで、最初のクラスByPositionMixinは私が注目しているものです:

from django.db import models
from django.db.models.query import QuerySet
from django.core.exceptions import FieldError

class ByPositionMixin(object):
    def batters(self):
        try:
            return self.exclude(positions=1)

        except FieldError:
            return self.exclude(position=1)

class PlayerQuerySet(QuerySet, ByPositionMixin):
    pass

class PlayerPositionQuerySet(QuerySet, ByPositionMixin):
    pass

class PlayerManager(models.Manager):
    def get_query_set(self):
        return PlayerQuerySet(self.model, using=self._db)

class PlayerPositionManager(models.Manager):
    def get_query_set(self):
        return PlayerPositionQuerySet(self.model, using=self._db)


class Position(models.Model):
    # pos_list in order ('P', 'C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF')
    # pos id / pk correspond to index value of pos_list(pos)
    pos = models.CharField(max_length=2)

class Player(models.Model):
    name = models.CharField(max_length=100)
    positions = models.ManyToManyField(Position, through='PlayerPosition')

    objects = PlayerManager()

class PlayerPosition(models.Model):
    player = models.ForeignKey(Player)
    position = models.ForeignKey(Position)
    primary = models.BooleanField()

    objects = PlayerPositionManager()

の中ByPositionMixinで、exclude(positions=1)どのクエリに対して試してみPlayerQuerySetます。フィールド名の違いは正確で、aには位置がありますが、aには 1 つの位置しかありません。したがって、クエリの違いは「位置」/「位置」です。多くのカスタム クエリ (例: 、など) があるため、それぞれについて書き出す/コードを作成する必要がありますか?FieldErrorexclude(position=1)PlayerPositionQuerySetPlayer()PlayerPosition()exclude()batters()pitchers()by_position()tryexcept

または、あるモデルに対して試行してから別のモデルに対して試行することなく、カスタム クエリを作成できる別のアプローチはありますか?

Player更新: 基本的に、 と の両方に正しい kwargs を提供する kwarg ヘルパー関数を作成することにしましたPlayerPosition。これは少し手の込んだ (そしておそらく完全に不必要な) ものですが、いくつかのカスタム クエリのコードを簡素化するために作成できるはずです。

class ByPositionMixin(object):
    def pkw(self, **kwargs):
        # returns appropriate kwargs, at the moment, only handles one kwarg
        key = kwargs.keys()[0]  # e.g. 'positions__in'
        value = kwargs[key]
        key_args = key.split('__')

        if self.model.__name__ == 'Player':
            first_arg = 'positions'

        elif self.model.__name__ == 'PlayerPosition':
            first_arg = 'position'

        else:
            first_arg = key_args[0]

        key = '__'.join([first_arg] + key_args[1:])
        return {key: value}

    def batters(self):  # shows how pkw() is used
        return self.exclude(**self.pkw(positions=1))
4

0 に答える 0