我有三个模型: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)
如果没有办法以某种方式“继承”过滤器Player
for 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 方法。