Code

Opened 7 years ago

Closed 7 years ago

#4091 closed (worksforme)

Not able to get choices widget to auto selected="selected" on model_for_instance

Reported by: no@… Owned by: nobody
Component: Forms Version: 0.96
Severity: Keywords: foreignkey selected choices
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

It may have to do how I have my models defined (such as the str() function), but if I use form_for_instance
on an instance with a model that has foreign keys, it will not put selected="selected" on the appropriate choices.
Here are my models:

class Students(models.Model):
    ssn = models.CharField(unique=True, maxlength=11)
    name = models.CharField(blank=True, maxlength=50)
    address = models.CharField(blank=True, maxlength=50)
    dob = models.DateField(null=True, blank=True)
    email = models.CharField(blank=True, maxlength=50)
    level = models.CharField(blank=True, maxlength=5)
    
    def __str__(self):
      return self.ssn

class Courses(models.Model):
    cid = models.CharField(unique=True, maxlength=7)
    level = models.CharField(blank=True, maxlength=5)
    description = models.TextField(blank=True, maxlength=100)
    
    def __str__(self):
      return self.cid

class Semesters(models.Model):
    sname = models.CharField(unique=True, maxlength=20)
    
    def __str__(self):
      return self.sname

class Takes(models.Model):
    student = models.ForeignKey(Students, to_field='ssn', db_index=True, db_column='ssn')
    course = models.ForeignKey(Courses, to_field='cid', db_index=True, db_column='cid')
    semester = models.ForeignKey(Semesters, to_field='sname', db_index=True, db_column='sname')
    grade = models.CharField(blank=True, maxlength=2)
    
    def __str__(self):
      return "%s - %s" % (self.course.cid, self.semester.sname)

Now I want to do a form_for_instance on a Takes instance and I expect the appropriate student, course, and semester to have selected="selected"
in the html.
So now I do this:

instance = Takes.objects.get(id=1)
formClass = forms.form_for_instance(instance)
form = formClass(auto_id='form_%s')
print form

And I get no selected="selected". Now I've studied the documentation thoroughly, and they said this happens
when they are not "bound". However, I thought form_for_instance makes it bound? Am I doing something wrong or is this a bug?

To circumvent this problem, I've resorted to the following:

formClass = forms.form_for_instance(instance)
for field in formClass.base_fields:
  if hasattr(formClass.base_fields[field], 'choices'):
    for option_value, option_label in formClass.base_fields[field].choices:
      if formClass.base_fields[field].initial == option_label:
        formdict.update({field: option_value})
        break
  else:
    formdict.update({field: formClass.base_fields[field].initial})

The above code does exactly what I want, it puts the selected="selected" on the right choices.

Attachments (0)

Change History (1)

comment:1 Changed 7 years ago by PhiR

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Resolution set to worksforme
  • Status changed from new to closed
  • Triage Stage changed from Unreviewed to Accepted

I used the following model:

from django.db import models
from django import newforms as forms

# Create your models here.
class ZoneGeographique(models.Model):
        nom = models.CharField(maxlength=256)

        def __str__(self):
                return self.nom
        
        class Admin:
                pass
class Ville(models.Model):
        pays = models.ForeignKey(ZoneGeographique)
        nom = models.CharField(maxlength=256)
        
        def __str__(self):
                return self.nom + " en " + self.pays.nom
        
        class Admin:
                pass

Then from the django shell:

>>> from test_form.models import *
>>> fr = ZoneGeographique(nom='France')
>>> fr.save()
>>> de = ZoneGeographique(nom='Allemagne')
>>> de.save()
>>> paris = Ville(pays=fr, nom='Paris')
>>> paris.save()
>>> paris
<Ville: Paris en France>
>>> import django.newforms as forms 
>>> ParisForm = forms.form_for_instance(paris)
>>> print ParisForm()
<tr><th><label for="id_pays">Pays:</label></th><td><select name="pays" id="id_pays">
<option value="">---------</option>
<option value="1" selected="selected">France</option>
<option value="2">Allemagne</option>
</select></td></tr>
<tr><th><label for="id_nom">Nom:</label></th><td><input id="id_nom" type="text" name="nom" value="Paris" maxlength="256" /></td></tr>

The right instance is selected. It works

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.