2011-01-18 18 views
9

Tôi đã cố gắng lọc một queryset trên một mô hình đơn giản nhưng không có may mắn cho đến nay.Django: Bộ lọc cho get_foo_display trong một Queryset

Đây là mô hình của tôi:

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

Và tôi muốn làm một cái gì đó như:

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

Nhưng không ai trong số những người ở trên đang làm việc. Làm cách nào để lọc trên một trường có thuộc tính choices? Tôi nghĩ rằng các __unicode__ ghi đè sẽ giúp đỡ, nhưng tôi đoán tôi đang thiếu một cái gì đó.

Trả lời

19

Bạn không thể thực hiện việc này. filter hoạt động ở cấp cơ sở dữ liệu và cơ sở dữ liệu không biết gì về tên dài của bạn. Nếu bạn muốn lọc trên một giá trị, bạn cần lưu trữ giá trị đó trong cơ sở dữ liệu.

Một cách khác là để dịch các giá trị trở lại mã, và lọc trên rằng:

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

Cảm ơn Daniel cho câu trả lời của bạn. – jtheoof

+3

Chẳng phải có điều gì đó mà django có thể làm để làm cho nó dễ dàng hơn một chút. Tôi nghĩ rằng đây sẽ là một hoạt động phổ biến – Sevenearths

+0

Lớp ['Choices'] (https://bitbucket.org/carljm/django-model-utils/src#rst-header-choices) trên ** django-model-utils * * có thể hữu ích theo cách này. – caesarsol

1

Bạn có thể trao đổi các giá trị trong 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

Lấy cảm hứng từ this answer, tôi đã làm như sau :

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

Bạn có thể sử dụng 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) 

Và làm cho một truy vấn:

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