简体   繁体   中英

Django: Filter for get_foo_display in a Queryset

I've been trying to filter a queryset on a simple model but with no luck so far.

Here is my model:

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

And I would like to do something like:

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

But none of those above are working. How do you filter on a field that has a choices attribute? I thought the overridden __unicode__ would help but I guess I'm missing something.

You can't do this. filter works at the database level, and the database doesn't know anything about your long names. If you want to do filtering on a value, you need to store that value in the database.

An alternative is to translate the value back into the code, and filter on that:

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

You can swap values in 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']

Inspired from this answer , I did the following:

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)

You can use 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)

And make a query:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM