Passing tuple values to a model choices field

97 views
Skip to first unread message

Kayode Odeyemi

unread,
Aug 8, 2011, 5:06:15 AM8/8/11
to django-users
In the Django [1], the example as described below shows how to build Forms that are tied to a model.

from django.db import models
from django.forms import ModelForm

TITLE_CHOICES = (
    ('MR', 'Mr.'),
    ('MRS', 'Mrs.'),
    ('MS', 'Ms.'),
)

class Author(models.Model):
    name = models.CharField(max_length=100)
    title = models.CharField(max_length=3, choices=TITLE_CHOICES)
    birth_date = models.DateField(blank=True, null=True)

    def __unicode__(self):
        return self.name

class AuthorForm(ModelForm):
    class Meta:
        model = Author

I have got similar setup in the forms.py and models.py. However, the tuple values is not displayed as options in the form field. I have something like this:

models.py
---------

""" a tuple of branch code as key and branch name as value """
MY_INSTITUTION_BRANCHES = (
    ('BR_CODE1', 'HQ'),
    ('BR_CODE2', 'Branch 2'),
)

class Transaction(models.Model):
branch_name = models.ForeignKey('MyInstitution', related_name='my_institution', \
         help_text='The branch where this transaction is originate from')

class MyInstitution(models.Model):
    name = models.CharField(max_length=100)
    branch_name = models.CharField(max_length=1,unique=True, choices=MY_INSTITUTION_BRANCHES)

    def __unicode__(self):
        return self.name

forms.py
--------
class TransactionUpdateForm(forms.ModelForm):
    class Meta:
        model = Transaction
        fields = ('branch_name')

template file
-------------
<label class="label" for="id_branch_name">Branch name: </label>
{{form.branch_name}}

With this setup, I'm expecting a form select field to be prepopulated with the tuple values (human readable names). Instead, the form select field is prepopulated with MyInstitution name values as stored in the db.

Any help will be much appreciated.

Thanks

[1] https://docs.djangoproject.com/en/1.3/topics/forms/modelforms/#modelform
--
Odeyemi 'Kayode O.
http://www.sinati.com. t: @charyorde

Thomas Orozco

unread,
Aug 8, 2011, 5:40:54 AM8/8/11
to django...@googlegroups.com

Check out get_FOO_display, there: https://docs.djangoproject.com/en/dev/ref/models/instances/

> --
> 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.
>

Kayode Odeyemi

unread,
Aug 8, 2011, 5:55:19 AM8/8/11
to django...@googlegroups.com
Thanks for the reply.

I have a views.py like this:

@login_required
def update_transaction(request, tpin=None):
    qs = Q(my_institution=None) | Q(my_institution=request.user.get_profile().my_institution)
    txn = get_object_or_404(Transaction.objects.filter(qs), tpin=tpin) 
    context = {'page_title': 'Update Transactions'}
    if request.POST:
        update_form = TransactionUpdateForm(request.POST, instance=txn)
        if update_form.is_valid():
            update_form.save()
            return HttpResponseRedirect(reverse('search-txn'))

    else:
        update_form = TransactionUpdateForm(instance=txn)
    context['txn'] = txn
    context['form'] = update_form
    return render_to_response("update_transaction.html", context, context_instance=RC(request))

At what point do I do: update_form.get_branch_name_display()? In forms.py or views.py? Where?

It seems to me that get_FOO_display() is meant to display the values set by the user. This is not what I'm looking to do. What I got stuck with is that the tuple values are not displayed as options in the form select field(choices).

Thanks

Thomas Orozco

unread,
Aug 8, 2011, 6:00:06 AM8/8/11
to django...@googlegroups.com

Oh, sorry, I must have misunderstood then.

I remember reading a post on thread on SO that addressed this, and I believe that they came up with a template filter as there was no "simple" way to do it.

Here it is: http://stackoverflow.com/questions/1105638/django-templates-verbose-version-of-a-choice

Hope this helps!

Kayode Odeyemi

unread,
Aug 8, 2011, 8:06:51 AM8/8/11
to django...@googlegroups.com
That didn't help either. It still did not depict what I'm trying to do. Those filters are for retrieving values set by a user. However, I tried the code below which is to hard code the choices into the form field on creation

class TransactionUpdateForm(forms.ModelForm):
    branch_name_new = forms.models.CharField(required=True, widget=forms.Select(choices={'BR_CODE1': 'HQ','BR_CODE2': 'Branch 2'}))
    class Meta:
        model = Transaction
        fields = ('branch_name')
        widgets = {
            'branch_name_new': Select(choices={'BR_CODE1': 'HQ': 'Branch 2'}),
        }

In the template, I did an output like this: {{form.branch_name_new}}. Nothing gets displayed.

How does Django handle this literally. I have read the docs insideout and tried stuffs out as written, but nothing seem to work. Has anyone done this sort of stuff before - I mean this is meant to be basic stuff. I don't want to have to manually create HTML markups in the template, because I will be needing those Select field values coming from the db.

Thanks

Thomas Orozco

unread,
Aug 8, 2011, 8:15:52 AM8/8/11
to django...@googlegroups.com

Like they do in the admin, right ?

You might want to check Django's source for the admin forms and templates to get some inspiration then.

Hard coding the choices is never a satisfactory solution but I suggest you retrieve them from your models file so you stay DRY compliant and then it's pretty OK.

As you put the widget in your field I think you just need to put form.branch_name to get it to display.

Le 8 août 2011 14:07, "Kayode Odeyemi" <dre...@gmail.com> a écrit :

Kayode Odeyemi

unread,
Aug 8, 2011, 8:30:25 AM8/8/11
to django...@googlegroups.com
Yeah form.branch_name displayed but the values are not the tuples - this is the primary reason why I'm seeking for help.

I have dabbled into the modelForm (widgets) as an option, obviously no luck there.

At the moment, I'm building a new model that maps the db table that contains the values, build a class that returns the model values, pass it's values to render_to_response and have it printed as form select values in the template.

I will post here if this works.

Thanks for the heads up.

--
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.

Daniel Roseman

unread,
Aug 8, 2011, 9:56:12 AM8/8/11
to django...@googlegroups.com


On Monday, 8 August 2011 13:06:51 UTC+1, Kayode Odeyemi wrote:
That didn't help either. It still did not depict what I'm trying to do. Those filters are for retrieving values set by a user. However, I tried the code below which is to hard code the choices into the form field on creation

class TransactionUpdateForm(forms.ModelForm):
    branch_name_new = forms.models.CharField(required=True, widget=forms.Select(choices={'BR_CODE1': 'HQ','BR_CODE2': 'Branch 2'}))
    class Meta:
        model = Transaction
        fields = ('branch_name')
        widgets = {
            'branch_name_new': Select(choices={'BR_CODE1': 'HQ': 'Branch 2'}),
        }

In the template, I did an output like this: {{form.branch_name_new}}. Nothing gets displayed.

How does Django handle this literally. I have read the docs insideout and tried stuffs out as written, but nothing seem to work. Has anyone done this sort of stuff before - I mean this is meant to be basic stuff. I don't want to have to manually create HTML markups in the template, because I will be needing those Select field values coming from the db.

Thanks


I'm afraid it's really not clear what you're trying to do, or what the problem is. 

If the issue is that you have a field referring to a foreign key, and you want to change what the values displayed in the dropdown for that field, then you simply need to redefine the `__unicode__` method for the related model, as documented here: https://docs.djangoproject.com/en/1.3/ref/forms/fields/#modelchoicefield
An alternative, also documented at that link, is to subclass ModelChoiceField and override label_from_instance.
--
DR.

Tom Evans

unread,
Aug 8, 2011, 10:20:58 AM8/8/11
to django...@googlegroups.com
On Mon, Aug 8, 2011 at 2:56 PM, Daniel Roseman <dan...@roseman.org.uk> wrote:
>
> I'm afraid it's really not clear what you're trying to do, or what the
> problem is.
> If the issue is that you have a field referring to a foreign key, and you
> want to change what the values displayed in the dropdown for that field,
> then you simply need to redefine the `__unicode__` method for the related
> model, as documented
> here: https://docs.djangoproject.com/en/1.3/ref/forms/fields/#modelchoicefield
> An alternative, also documented at that link, is to subclass
> ModelChoiceField and override label_from_instance.

This exact question gets asked about 3 times a week (well, once you
have normalized out the different ways in which it is asked..).
Personally, I'm fed up of answering it.

I think that adjusting the labels needs to become a bit more flexible
- perhaps allow a "label_from_instance=callable" argument on
ModelChoiceField, or have ModelChoiceField look for a
MyForm.label_from_instance_<fieldname> method.

The current options are

a) change how the related field's model is displayed throughout Django
(which may be impossible to do for a cross app links/3rd party apps)
b) provide your own Field class which labels things appropriately

Both these options are more cumbersome than needs be, as evidenced by
the number of users who don't understand how to do this.

Cheers

Tom

Kayode Odeyemi

unread,
Aug 8, 2011, 3:54:22 PM8/8/11
to django...@googlegroups.com
I have made changes like this:

""" Introduced a new model to store the form field select values """
class Branch(models.Model):
    """Branch"""
    name = models.CharField(max_length=50)
    name_branch = models.CharField(max_length=50)
    address_1 = models.CharField(max_length=100)

    class Meta:
        db_table = 'branch'

    def __unicode__(self):
        return u"%s | %s | %s" % (
            unicode(self.name_branch),
            unicode(self.address_1))

class TransactionUpdateForm(forms.ModelForm):
    branchqs = Branch.objects.get(name_branch)
    branches_field = forms.BranchModelChoiceField(branchqs) #ModelChoiceField instance
    branch_name_new = forms.models.CharField(required=True, widget=forms.Select(choices={'BR_CODE1': 'HQ': 'Branch 2'}))
    class Meta:
        model = Transaction
        fields = ('branch_name')
        widgets = {
            'branch_name_new': Select(choices={'BR_CODE1': 'HQ': 'Branch 2'}),
        }

""" subclass of ModelChoiceField """"
class BranchModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return "My Object #%i" % obj.id

In template file I do this:

{{form.branches_field}}

Unfortunately, no luck yet.

I'm still trying other options though.

Thanks

--
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.

Kayode Odeyemi

unread,
Aug 9, 2011, 11:34:23 AM8/9/11
to django...@googlegroups.com
The label_from_instance should simply return the obj. I don't think any fuzzy codes is needed as 
described in the Django docs [1] 

The method label_from_instance already converts the objects to string. So a simple override like this:

class MyModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return obj

I made changes like this to my code:


""" Introduced a new model to store the form field select values """
class Branch(models.Model):
    """Branch"""
    name = models.CharField(max_length=50)
    name_branch = models.CharField(max_length=50)
    address_1 = models.CharField(max_length=100)

    class Meta:
        db_table = 'branch'

    def __unicode__(self):
        return u"%s | %s | %s" % (
            unicode(self.name_branch),
            unicode(self.address_1))

""" subclass of ModelChoiceField """"
class BranchModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return obj # Just return the obj

class TransactionUpdateForm(forms.ModelForm):
    branchqs =Branch.objects.values_list('name_branch', flat=True)
    branches_field = BranchModelChoiceField(branchqs) #ModelChoiceField instance
    class Meta:
        model = Transaction
        fields = ('branch_name')

In template file I do this:

{{form.branches_field}}

Reply all
Reply to author
Forward
0 new messages