How to use a DB table for choices=tuples in ChoiceField?

2,943 views
Skip to first unread message

Bill Beal

unread,
Jan 20, 2012, 10:44:16 PM1/20/12
to Django users
Hi All,

When I looked in the docs for how to fill in the
"choices=" attribute for a ChoiceField in a form,
I could only find static sets of tuples for examples.
I need to use a table from the DB for the tuples.
I thought I could make up the choice list myself
from the table, but I'm getting a Name Error:
name 'scac_choicelist' is not defined at the marked
line in my form:

from django import forms
from django.forms.fields import ChoiceField
from myapp.models import *

BOL_CODE_QUALIFIERS = (
('OB', 'Ocean Bill of Lading (OB)'),
('BM', 'House Bill of Lading (BM)'),
)

class BolForm(forms.Form):
- scac = forms.ChoiceField(
----- label=u'Ocean Carrier',
----- choices=scac_choicelist()) ######
- bill_of_lading = forms.CharField(
----- label=u'Bill of Lading #', max_length=50)
- bol_type = forms.ChoiceField(
----- label=u'Type of B/L',
----- choices=BOL_CODE_QUALIFIERS)

Here's my model:

from django.db import models

class Scac(models.Model):
- code = models.CharField(max_length=4)
- name = models.CharField(max_length=60)

- def __unicode__(self):
--- return self.code

- def scac_choicelist():
--- q = Scac.objects.all()
--- scaclist = []
--- for x in q:
----- scaclist.append((x.code, x.name))
----- return scaclist

I didn't know where to stick the scac_choicelist()
code, so I put it with the model.

Questions:
1. Is this a reasonable approach? If not, what?
2. If so, how can I get scaclist into the form?

I hope there is enough info here that my mistake
is obvious to somebody.

Thanks.

Bill Beal

unread,
Jan 20, 2012, 11:01:34 PM1/20/12
to Django users
Well, I put the code in line, thus:

class BolForm(forms.Form):
- q = Scac.objects.all()
- scaclist = []
- for x in q:
--- scaclist.append((x.code, x.name))
- scac = forms.ChoiceField(
----- label=u'Ocean Carrier', choices=scaclist)
- bill_of_lading = forms.CharField(
----- label=u'Bill of Lading #', max_length=50)
- bol_type = forms.ChoiceField(
----- label=u'Type of B/L', choices=BOL_CODE_QUALIFIERS)

It worked.  But is there a better way?
Message has been deleted

Bill Beal

unread,
Jan 20, 2012, 11:48:49 PM1/20/12
to django...@googlegroups.com
Thank you, Dennis.  I'll study your answer.  I have to do this kind of thing for a lot of different tables.  And I discovered another thing:  In the template I was reading the table in again from the database!  Before my problem was solved, I could populate the selection list from the DB table, but then there were no valid choices when I got back to the view.

I'm getting to know Django just enough that I can sometimes answer questions posted here, or at least make suggestions.

Regards

On Fri, Jan 20, 2012 at 11:22 PM, Dennis Lee Bieber <wlf...@ix.netcom.com> wrote:
On Fri, 20 Jan 2012 19:44:16 -0800 (PST), Bill Beal
<b.b...@eximflow.com> wrote:

       Caveat: I've only looked at Django, but not in enough detail to be
"expert"; my comments are based upon basic Python syntax/semantics (my
apologies to the developers, but I work better with printed
documentation and Django is too much of a moving target for the few
books that did come out to be relevant four months later)


>name 'scac_choicelist' is not defined at the marked
>line in my form:
>
       Which is true -- it is not defined at that point. (NOTE: your names
don't really help understanding the purpose of the variables <G>)
       Presuming the many "-"s represent indentation, "scac_choicelist" is
a method of Scac. That means it should have at least one parameter: self

       def scac_choicelist(self):
               scaclist = []
               for item in self.objects.all():
                       scaclist.append((item.code, item.name))
               return scaclist

NOTE: based on your "-"s, your return statement is inside your loop, so
you'd be returning after processing only one element.

       NOW... In the form module you need to reference an instance of the
model! The method itself is not visible.


>- scac = forms.ChoiceField(
>----- label=u'Ocean Carrier',
>----- choices=scac_choicelist()) ######
>

Something like:

       scac = forms.ChoiceField(       label=u"Ocean Carrier",
                                                               choices=Scac().scac_choicelist())

--
       Wulfraed                 Dennis Lee Bieber         AF6VN
       wlf...@ix.netcom.com    HTTP://wlfraed.home.netcom.com/

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.


Bill Beal

unread,
Jan 21, 2012, 8:01:31 AM1/21/12
to django...@googlegroups.com
It looks like the Pythonic way is to create the list in
models.py and invoke it from forms.py.

Sorry about the heterogeneous names--some of 
them match the document the requirements were 
extracted from and others are more meaningful 
to me.  The former were picked because we'll 
need a requirements cross-reference and they'll 
be easier to match up with the requirements.  
And the dashes in place of spaces--most of the 
code examples I see here are almost unreadable 
because of leading spaces disappearing.  
I saw one example of replacing all but the last 
leading space with '-', and it was more readable.

Regards

On Fri, Jan 20, 2012 at 11:22 PM, Dennis Lee Bieber <wlf...@ix.netcom.com> wrote:
On Fri, 20 Jan 2012 19:44:16 -0800 (PST), Bill Beal
<b.b...@eximflow.com> wrote:

       Caveat: I've only looked at Django, but not in enough detail to be
"expert"; my comments are based upon basic Python syntax/semantics (my
apologies to the developers, but I work better with printed
documentation and Django is too much of a moving target for the few
books that did come out to be relevant four months later)
>name 'scac_choicelist' is not defined at the marked
>line in my form:
>
       Which is true -- it is not defined at that point. (NOTE: your names
don't really help understanding the purpose of the variables <G>)
       Presuming the many "-"s represent indentation, "scac_choicelist" is
a method of Scac. That means it should have at least one parameter: self

       def scac_choicelist(self):
               scaclist = []
               for item in self.objects.all():
                       scaclist.append((item.code, item.name))
               return scaclist

NOTE: based on your "-"s, your return statement is inside your loop, so
you'd be returning after processing only one element.

       NOW... In the form module you need to reference an instance of the
model! The method itself is not visible.
>- scac = forms.ChoiceField(
>----- label=u'Ocean Carrier',
>----- choices=scac_choicelist()) ######
>

Leandro Ostera Villalva

unread,
Jan 21, 2012, 12:31:43 AM1/21/12
to django...@googlegroups.com
I'm new to this list but a nice way to share code snippets is thru services like gist. 

Here's how the first source code would have looked:  https://gist.github.com/1651488 

Ontopic: I believe that a method called 'as_list' would be more descriptive. Perhaps the manager included in models.Model has something like that.

If I recall correctly you could use this: as_list = list( Scac.objects.all() )
--
Regards,

Leandro Ostera,

Leandro Ostera Villalva

unread,
Jan 21, 2012, 10:31:52 AM1/21/12
to django...@googlegroups.com
Here's a nicer way to do it.

CHOICES = list ( (obj.code,obj.name) for obj in Scac.objects.all() )

Or you can always make a static method for it and call Scac.objects_as_list()
Reply all
Reply to author
Forward
0 new messages