2011-01-18 10 views
9

Ho cercato di filtrare un queryset su un modello semplice ma senza fortuna fino ad ora.Django: Filtro per get_foo_display in una Queryyset

Ecco il mio modello:

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

e vorrei fare qualcosa di simile:

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

Ma nessuno di quelli sopra stanno lavorando. Come si filtra su un campo che ha un attributo choices? Ho pensato che l'override di __unicode__ sarebbe stato d'aiuto ma immagino che mi manchi qualcosa.

risposta

19

Non è possibile farlo. filter funziona a livello di database e il database non sa nulla dei tuoi nomi lunghi. Se si desidera filtrare su un valore, è necessario archiviare tale valore nel database.

Un'alternativa è di tradurre il valore indietro nel codice, e filtrare su quella:

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

Grazie Daniel per la risposta. – jtheoof

+3

Non c'è qualcosa che il django possa fare per renderlo un po 'più facile. Ho pensato che sarebbe stata un'operazione comune – Sevenearths

+0

La classe ['Choices'] (https://bitbucket.org/carljm/django-model-utils/src#rst-header-choices) su ** django-model-utils * * può essere utile in questo modo. – caesarsol

1

È possibile scambiare i valori nel costruttore:

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

Ispirato da this answer, ho fatto la seguente :

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

È possibile utilizzare 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) 

E fare una query:

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