tags:

views:

40

answers:

2

I am working with some data over which I have little control. I'd like to return ONLY the fields of my model that aren't certain 'uninteresting' values (e.g. '0', 'X' or '-'), and access them individually in the template.

My model is like this:

class Manors(models.Model):
    structidx = models.IntegerField(primary_key=True, verbose_name="ID")    
    hills = models.CharField(max_length=100, null=True, blank=True, verbose_name="Number of fields") 

In my template, I return a QuerySet of Manors, and I'd like to output something like this if the hills field isn't uninteresting:

{% for manor in manors %}
{% if manor.hills %}<li>Hills blah blah: {{ manor.hills }}</li>{% endif %}
{% endfor %}

I want to avoid too much logic in the template. Ideally, the manor object would simply not return with the uninteresting fields attached, then I could just do {% if manor.hills %}.

----UPDATE---- I could use a dictionary, like below, but it feels very inefficient - it would be better to return a QuerySet with just the interesting fields attached. Is that possible? -----------

I tried writing a model method that returns a dictionary of the interesting values, like this:

def get_field_dictionary(self):
    interesting_fields = {}
    for field in Manors._meta.fields:
        if field.value_to_string(self) != "N" and field.value_to_string(self) != "0" and field.value_to_string(self) != "-" and field.value_to_string(self) != "X":
            interesting_fields[field.name] = field.value_to_string(self)
    return interesting_fields

But I don't know how to access individual values of the dictionary in the template:

{% if manor.get_field_dictionary['hills'] %}<li>Hills blah blah: {{ manor.get_field_dictionary['hills'] }}</li>{% endif %}

gives a TemplateSyntaxError. Is there a better way to do this?

UPDATE: this did it in the end, as a method on the model.

def get_interesting_queryset(self):
    for field in Manors._meta.fields:
        if field.value_to_string(self) is None or field.value_to_string(self) == "N" or field.value_to_string(self) == "0" or field.value_to_string(self) == "-" or field.value_to_string(self) == "X" or field.value_to_string(self) == "":
            delattr(self, str(field.name))
    return self
A: 

Try this...

{% for k,v in manor.get_field_dictionary %}
  {% ifequal k "hills" %}
    <li>Hills blah blah: {{v}}</li>
  {% endifequal %}
{% endfor %}

Assuming the model method works, that should get you what you're looking for.

Brant
Thanks! That works, but it feels pretty inefficient, because I actually have 30 fields in the model. Is there any way to return a QuerySet with only the interesting fields attached?
AP257
A: 

Depending on the version of Django you are using, you should use the "in" operator. Lets take your model function. Have it output a list.

def get_field_list(self):
    interesting_fields = []
    for field in Manors._meta.fields:
        if field.value_to_string(self) != "N" and field.value_to_string(self) != "0" and field.value_to_string(self) != "-" and field.value_to_string(self) != "X":
            interesting_fields[] = field.value_to_string(self)
    return interesting_fields

Then. In your template do the following.

{% if 'hills' in manor.get_field_list %}<li>Hills blah blah: {{ manor.hills }}</li>{% endif %}

Also note that once you have the queryset, IIRC, you can edit it. Thus

for manor in Manors.objects.all():
    for field in Manors._meta.fields:
        if field.value_to_string(manor) == "N" or field.value_to_string(manor) == "0" or field.value_to_string(manor) == "-" or field.value_to_string(manor) == "X":
            delattr(manor, field.value_to_string(self))
emperorcezar
Thanks! Unfortunately I can't use the 'in' operator because I'm running Django 1.1. Editing the queryset looks like the way to go. Please could you give me a little more help though - where should I put this code, in models.py or views.py? How should I get the queryset I need (which is actually a filtered queryset) and then return the edited queryset to the template? Thanks so much...
AP257
I think you'll need it in the view since it doesn't deal with a single instance of a model. Maybe factor it out into a function if you're going to use it a lot.Just catch the queryset you need using the regular django db api and then push it on to your template.
emperorcezar
OK - sorry about this - so in views.py I now have: all_manors = Manors.objects.filter(structidx__in=place_ids) -- for manor in all_manors: -- but then field.value_to_string(self) in that code gives me an error: "global name 'self' is not defined". Should I be using something else instead of 'self'?
AP257
Just try it without the self call, using the manor instance instead. I think the self is a mistake on my end. I have edited the above code to reflect this.
emperorcezar
I eventually added it as a method on the model, with 'return self'. Thank you for all your help, I would never have got it alone.
AP257