Django 多对多过滤器
我有一个区域基础设施建模如下:每个区域都有一个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)
遗憾的是,这返回一个空的查询集。我怀疑这与“国家”模型中有一个“国家”字段有关(我知道,命名非常含糊,不是我原来的代码),而且我只是按“国家”模型进行过滤,而不是按“国家”模型进行过滤。其中的“国家/地区”字段。 (这有意义吗?)
如何按 ManyToMany 字段的子字段进行过滤?
I have a Region infrastructure modeled as follows: Each region has a ManyToMany of countries, and optionally states (if it's a region within the US)
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
Each user has a profile defined (partially) as follows:
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)
I'm trying to filter a bunch of user objects by region. So I have
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)
Sadly though, this returns an empty queryset. I suspect it has to do with the fact that the "Country" model has a "country" field within it (terrible ambiguous naming, I know, not my code originally), and I'm only filtering by "Country" models, not the "country" fields within them. (Does that make sense?)
How can I filter by a subfield of the ManyToMany field?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,如果您只想要单个项目,为什么要使用
.filter()
:如果该对象不存在,那么这将引发
ObjectDoesNotExist
异常,但您'如果查询集无论如何都是空的,则会引发异常。如果您需要捕获该异常,则可以使用try... except
块或get_object_or_404
(如果您在视图中)。其次,不要直接使用
self.request.GET['filter_region']
。如果未设置该键,您将引发IndexError
。使用,而不是:现在,关于您的实际问题:
UserProfile.country
是一个CountryField
,它只是一个专门的CharField
。而Region.countries
是具有模型Country
的 M2M。两者不具有可比性,这就是您的查询集返回空的原因。将
UserProfile.country
设为Country
的外键,然后您就可以开始工作了。First, why are you using
.filter()
if you want just a single item do:That will raise an
ObjectDoesNotExist
exception if the object doesn't exist, but you're raising an exception if the queryset is empty anyways. If you need to catch that exception you can either use atry...except
block orget_object_or_404
if you're in a view.Second, don't use
self.request.GET['filter_region']
directly. If the key isn't set you'll raise anIndexError
. Use, instead:Now, as to your actual problem:
UserProfile.country
is aCountryField
which is just a specializedCharField
. WhereasRegion.countries
is a M2M with the modelCountry
. The two are not comparable, which is why your queryset is coming back empty.Make
UserProfile.country
a foreign key toCountry
and you're in business.