2011-01-18 2 views
9

Я пытался отфильтровать набор запросов на простой модели, но пока не повезло.Django: Фильтр для get_foo_display в Queryset

Вот моя модель:

class Country(models.Model): 
    COUNTRY_CHOICES = (
     ('FR', _(u'France')), 
     ('VE', _(u'Venezuela')), 
    ) 

    code = models.CharField(max_length=2, choices=COUNTRY_CHOICES) 

    def __unicode__(self): 
     return self.get_code_display() 

И я хотел бы сделать что-то вроде:

Country.objects.filter(get_code_display__icontains="france") 
Country.objects.filter(code__display__icontains="france") 
Country.objects.filter(get_code_display__icontains="france") 

Но ни один из тех, кто выше, не работают. Как вы фильтруете поле с атрибутом choices? Я думал, что переопределенный __unicode__ поможет, но я думаю, что я что-то упустил.

ответ

19

Вы не можете этого сделать. filter работает на уровне базы данных, и база данных ничего не знает о ваших длинных именах. Если вы хотите сделать фильтрацию по значению, вам нужно сохранить это значение в базе данных.

Альтернативой перевести значение обратно в код, и фильтр на что:

country_reverse = dict((v, k) for k, v in COUNTRY_CHOICES) 
Country.objects.filter(code=country_reverse['france']) 
+0

Спасибо Даниилу за ваш ответ. – jtheoof

+3

Не может быть что-то, что может сделать django, чтобы сделать его немного легче. Я думал, что это будет общая операция. – Sevenearths

+0

Класс ['Choices'] (https://bitbucket.org/carljm/django-model-utils/src#rst-header-choices) на ** django-model-utils * * может быть полезным таким образом. – caesarsol

1

Вы можете поменять значения в конструкторе:

class PostFilter(django_filters.FilterSet): 

    def __init__(self, data=None, queryset=None, prefix=None, strict=None): 
     data = dict(data) 
     if data.get('type'): 
      data['type'] = Post.get_type_id(data['type'][0]) 

     super(PostFilter, self).__init__(data, queryset, prefix, strict) 

    class Meta: 
     model = Post 
     fields = ['type'] 
0

Вдохновленный из this answer, я сделал следующее :

search_for = 'abc' 

results = (
    [ 
     x for x, y in enumerate(COUNTRY_CHOICES, start=1) 
     if search_for.lower() in y[1].lower() 
    ] 
) 

Country.objects.filter(code__in=results) 
0

Вы можете использовать Choices

from model_utils import Choices 

class Country(models.Model): 
    COUNTRY_CHOICES = Choices((
     ('FR', _(u'France')), 
     ('VE', _(u'Venezuela')), 
    )) 

    code = models.CharField(max_length=2, choices=COUNTRY_CHOICES) 

И сделать запрос:

Country.objects.filter(code=Country.COUNTRY_CHOICES.france)