Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
532 views
in Technique[技术] by (71.8m points)

python - dynamic filter choice field in django

I am using django-filter to filter results on a page. I am able to use static choice filters like this:

filters.py

FILTER_CHOICES = (
('', 'All States'),
('AL', 'Alabama'),
('AK', 'Alaska'),
('AZ', 'Arizona'),
#and so forth, I am not going to list all 50 states for this a question on a forum
)


class SightingFilter(django_filters.FilterSet):
    state = django_filters.ChoiceFilter(choices=FILTER_CHOICES)
    class Meta:
        model = Sighting
        fields = ['city', 'store', 'brand', 'product', 'flavor', 'fat', 'size']   

So that code above works fine, but if I try to make a dynamic list like "plant_number" below:

class SightingFilter(django_filters.FilterSet):
    state = django_filters.ChoiceFilter(choices=FILTER_CHOICES)
    plant_number = django_filters.ChoiceFilter(choices=[(o.plant_number, o.plant_number + " " + o.manufacturer_name) for o in Plant.objects.all()])
 class Meta:
        model = Sighting
        fields = ['city', 'store', 'brand', 'product', 'flavor', 'fat', 'size']

Then I get the error:

invalid literal for int() with base 10:

and it highlights this code in my template

{% for obj in filter %}
    <a href="/sighting/{{ obj.slug }}/ ">{{ obj.date|date:"m/d/Y" }} {{ obj.brand }} ${{ obj.price|intcomma }} </a><br />
{% endfor %}

The plant_number is a CharField in the model (plant numbers use the format XX-XXX, where the X's are digits).

My view looks like this:

def dashboard(request):
    if "Clear Filters" in request.GET:
        return redirect('/')
else:
    filter = SightingFilter(request.GET, queryset=Sighting.objects.all())
    context = {'filter': filter, 'request': request}
    return render_to_response('dashboard.html', context, context_instance=RequestContext(request))

Thanks for your help!

EDIT 1/14/15

So I am pretty certain the issue is that plant_number is a foreign key (sorry didn't include the models.py above). That is why it is expecting an int and not a string. So now I need to figure out how to get the foreign key value of the plant number instead of just the plant number. I tried:

plant_number = django_filters.ChoiceFilter(choices=[[o.plant_number.id, o.plant_number + " " + o.Manufacturer] for o in Plant.objects.all()])

Also tried:

plant_number = django_filters.ChoiceFilter(choices=[[o.plant_number_id, o.plant_number + " " + o.Manufacturer] for o in Plant.objects.all()])

Neither works. I get 'unicode' object has no attribute 'id' on the first one and 'Plant' object has no attribute 'plant_number_id' on the second.

models.py

class Sighting(models.Model):
    date = models.DateField(default=today)
    brand = models.CharField(max_length=200)
    product = models.CharField(max_length=200)
    flavor = models.CharField(max_length=200)
    fat = models.DecimalField(max_digits=4, decimal_places=2)
    size = models.DecimalField(max_digits=10, decimal_places=2)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    plant_number = models.ForeignKey('Plant', blank=True, null=True )
    store = models.CharField(max_length=200)
    city =  models.CharField(max_length=200)
    state = models.CharField(max_length=200, choices=STATE_CHOICES)
    photo = ProcessedImageField(upload_to=yogurtupload,
                                   processors=[ResizeToFit(600, 600)], #Resizes so the largest dimension is 600 (width or height, whichever hits 600 first)
                                   format='JPEG',
                                   options={'quality': 72})
    slug = models.SlugField(unique=True)

    def save(self):
        now = timestamp()
        forslug = str(now) + " " + str(self.plant_number) + " " + str(self.brand)
        self.slug = slugify(forslug)
        super(Sighting, self).save()

     def __unicode__(self):
        return self.slug

class Plant(models.Model):
    plant_number = models.CharField(max_length=200)
    Manufacturer = models.CharField(max_length=200)
    city = models.CharField(max_length=200)
    state = models.CharField(max_length=200, choices=STATE_CHOICES)
    slug = models.SlugField(unique=True)

    def save(self):
        self.slug = slugify(self.plant_number)
        super(Plant, self).save()

    def __unicode__(self):
        return self.slug
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

That's because FILTER_CHOICES is tuples in a tuple, not tuples in a list. Try this:

plant_number = django_filters.ChoiceFilter(choices=((o.plant_number.id, o.plant_number.foobar + " " + o.manufacturer_name) for o in Plant.objects.all()))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...