2

I wanted some guidance if possible on how to make this more generic:

def get_industry_choices(self):
    industries = Industry.objects.all().order_by('name')
    ind_arr = [(ind.id, ind.name) for ind in industries]

    return ind_arr

Basically this function will return choices as expected for the forms.ChoiceField. I need to do this in a few places, and wanted to make the function above more generic. I know how to get the industries = Industry.objects.all().order_by('name') to be generic, but the 2nd part is what I'm not sure about. When creating the tuples, it has (ind.id, ind.name). the ind.name can be any value depending on the model passed in (it may not always have name in the model).

I tried to read up on this in a few places including:

Passing functions with arguments to another function in Python?

The above resource shows how to do it using a function passed in, but that seems a bit overkill? If I have to pass a function as an argument anyway, whats the point of making it more generic with one more function?

[EDIT]

Basically I want to produce something similar to this:

TITLE_CHOICES=(
    (1, 'Mr.'),
    (2, 'Ms.'),
    (3, 'Mrs.'),
    (4, 'Dr.'),
    (5, 'Prof.'),
    (6, 'Rev.'),
    (7, 'Other'),
)

So when doing forms.ChoiceField I can pass in TITLE_CHOICES for example as the possible choices. The first value is the value I get when the form is submitted, the second value is what the user sees on form. I want to be able to programmatically create this with any model, I pass in the model name and one field in the above example, name. I want to create the tuple such that it is (id, name). But name could be replaced with anything in a different model...

Community
  • 1
  • 1
KVISH
  • 12,923
  • 17
  • 86
  • 162
  • +1 for searching for an answer first – msw Aug 14 '12 at 04:32
  • Sorry if there was confusion...but was wondering if there was something I was missing, trying to make the above function as generic as possible. – KVISH Aug 14 '12 at 04:36
  • Basically I want to be able to pass in any Model and create a tuple from the `id` and a particular field in it. – KVISH Aug 14 '12 at 04:37
  • I think this is what you're looking for: http://stackoverflow.com/questions/285061/how-do-you-programmatically-set-an-attribute-in-python – Guy Sirton Aug 14 '12 at 04:37

3 Answers3

2

It is hard to tell from your question, but I think the bit you are missing is getattr(). For example

ind = something()
for field in ['id', 'name']:
    print getattr(ind, field)
msw
  • 42,753
  • 9
  • 87
  • 112
1

Actually, Django already has a shortcut for this: values_list.

Industry.objects.all().values_list('id', 'name')

or

fields = ['id', 'name']
Industry.objects.all().values_list(*fields)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • This is a much cleaner solution, but only for this specific use case. So i'll keep the other as the answer since it'll work in most other cases. – KVISH Aug 14 '12 at 14:16
0

Maybe this helps:

from some_app.models import SomeModel


def generate_choices(model, order=None *args):
    choices = model.objects
    if order:
        choices = choices.order_by(order)
    return choices.values_list('pk', *args)


class MyForm(forms.Form):
    my_choice_field = CharField(max_length=1,
                                choices=generate_choices(SomeModel, 'name'))
    other_choice_field = CharField(max_length=1,
                                   choices=generate_choices(SomeModel, 'city', 'state'))
Gerard
  • 9,088
  • 8
  • 37
  • 52