我有一个区域基础设施建模如下:每个地区都有一个ManyToMany国家,并且可选地说明州(如果它是美国境内的地区)
from django.contrib.auth.models import User
from django.contrib.localflavor.us.models import USStateField
from django.db import models
from django_countries import CountryField
class CountryManager(models.Manager):
def get_by_natural_key(self, country):
return self.get(country=country)
class Country(models.Model):
country = CountryField(unique=True)
objects = CountryManager()
class Meta:
ordering = ('country',)
def __unicode__(self):
return unicode(self.country.name)
def natural_key(self):
return (self.country.code,)
class StateManager(models.Manager):
def get_by_natural_key(self, state):
return self.get(state=state)
class State(models.Model):
state = USStateField(unique=True)
objects = StateManager()
class Meta:
ordering = ('state',)
def __unicode__(self):
return self.get_state_display()
def natural_key(self):
return (self.state,)
class Region(models.Model):
name = models.CharField(max_length=255, unique=True)
coordinator = models.ForeignKey(User, null=True, blank=True)
is_us = models.BooleanField('Is a US region')
countries = models.ManyToManyField(Country)
states = models.ManyToManyField(State, blank=True)
class Meta:
ordering = ('name',)
def __unicode__(self):
return self.name
每个用户都有(部分)定义的个人资料,如下所示:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='user_profile')
city = models.CharField(max_length=255)
country = CountryField()
state = USStateField(_(u'US only (determines user's region)'), blank=True, null=True)
我正在尝试按区域过滤一堆用户对象。所以我有
region = Region.objects.filter(id=self.request.GET['filter_region'])
if len(region) == 0:
raise Exception("Region not found for filter")
if len(region) > 1:
raise Exception("Multiple regions found for filter?")
region = region[0]
queryset = queryset.filter(user_profile__country__in=region.countries.all)
遗憾的是,这会返回一个空的查询集。我怀疑它与“Country”模型中有一个“country”字段这一事实有关(可怕的模糊命名,我知道,最初不是我的代码),而我只是按“Country”模型过滤,而不是其中的“国家”字段。 (这有意义吗?)
如何按ManyToMany字段的子字段进行过滤?
答案 0 :(得分:1)
首先,如果您只想要一个项目,为什么要使用.filter()
:
region = Region.objects.get(id=self.request.GET['filter_region'])
如果对象不存在,则会引发ObjectDoesNotExist
异常,但如果查询集为空,则会引发异常。如果您需要捕获该异常,则可以使用try...except
块或get_object_or_404
,如果您在视图中。
其次,不要直接使用self.request.GET['filter_region']
。如果密钥未设置,则您将引发IndexError
。请改用:
self.request.GET.get('filter_region')
现在,关于您的实际问题:UserProfile.country
是CountryField
,它只是一个专门的CharField
。而Region.countries
是具有模型Country
的M2M。这两个不可比,这就是你的查询集返回空的原因。
将UserProfile.country
设为Country
的外键并开始营业。