我有三个模型:Player、League和LeaguePlayer。LeaguePlayer与 有外键关系,Player与 有外键关系League。Player有几个自定义查询,例如:
Player.objects.by_position('catcher'), 或者
Player.objects.by_position(position='batter', exclude='catcher'), 或者
Player.objects.by_best_position('shortstop').
我希望能够Player在过滤时使用自定义查询LeaguePlayer。一个例子可能是:LeaguePlayer.objects.by_position('catcher'),它将使用Player自定义过滤器by_position。所以如果LeaguePlayer有一个字段player_value,我想做类似的事情:
LeaguePlayer.objects.by_position('catcher').filter('player_value__gt'=100)
如果没有办法以某种方式“继承”过滤器Playerfor LeaguePlayer?或者如果没有,是否有不同的方式来组织我的模型,以便可以轻松创建这种类型的过滤?
@yuvi,我的问题背后的一些代码:
from django.db import models
from model_utils.managers import PassThroughManager
from player.models import Positions
class League(models.Model):
name = models.CharField(verbose_name="League name", max_length=50, unique=True)
number_of_teams = models.IntegerField(
verbose_name="Number of teams in your league",
choices=[(i, i) for i in range(6, 19)],
blank=False, default=10
)
...
class PlayerQuerySet(models.query.QuerySet):
def exclude_position(self, exclude=None):
non_excluded_positions = [...]
return self.filter(all_positions__in=non_excluded_positions).distinct()
def by_position(self, positions=None, exclude=None):
player_set = self
if exclude is not None:
player_set = self.exclude_position(exclude)
if positions is None:
return player_set.distinct()
return player_set.filter(all_positions__in=positions).distinct()
class PlayersManager(PassThroughManager):
def get_query_set(self):
return PlayerQuerySet(self.model, using=self._db)
class Players(models.Model):
name = models.CharField(max_length=30)
primary_position = models.ForeignKey(Positions, related_name='primary')
all_positions = models.ManyToManyField(Positions, related_name='positions')
objects = PlayersManager()
class LeaguePlayerQuerySet(models.query.QuerySet):
def custom_query(self):
return some filtered version of self
class LeaguePlayerManager(PassThroughManager):
def get_query_set(self):
return LeaguePlayerQuerySet(self.model, using=self._db)
class LeaguePlayer(models.Model):
league = models.ForeignKey(League)
player = models.ForeignKey(Players)
player_value_property = models.FloatField(null=True)
...
objects = LeaguePlayerManager()
@property
def player_value(self):
if not self.player_value_property:
self.player_value_property = calculate value based on self.league and self.player
self.save()
return self.player_value_property
可以在此处找到有关 PassThroughManager 的详细信息:https ://bitbucket.org/carljm/django-model-utils/overview 。简而言之,它允许链接自定义 QuerySet 方法。