2011-01-18 37 views
9

He intentado filtrar un queryset en un modelo simple pero sin suerte hasta el momento.Django: filtro para get_foo_display en un Queryset

Aquí es mi modelo:

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() 

y me gustaría hacer algo como:

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

Pero ninguno de los de arriba están trabajando. ¿Cómo se filtra en un campo que tiene un atributo choices? Pensé que el __unicode__ reemplazado ayudaría, pero creo que me falta algo.

Respuesta

19

No puede hacer esto. filter funciona en el nivel de la base de datos, y la base de datos no sabe nada sobre sus nombres largos. Si desea filtrar un valor, debe almacenar ese valor en la base de datos.

Una alternativa es traducir el valor de nuevo en el código, y filtrar el que:

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

Gracias Daniel por su respuesta. – jtheoof

+3

¿Hay algo que django pueda hacer al respecto para hacerlo un poco más fácil? Pensé que sería una operación común – Sevenearths

+0

La clase ['Choices'] (https://bitbucket.org/carljm/django-model-utils/src#rst-header-choices) en ** django-model-utils * * puede ser útil de esta manera. – caesarsol

1

Puede cambiar los valores en el constructor:

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

Inspirado this answer, hice lo siguiente :

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

Usted puede utilizar 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) 

Y hacer una consulta:

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