How do I set the value of a field (which is relevant to form, but not based directly on the same model) on a (model) form when it is displayed in the admin?
Here is a simplified version of what I have (my actual app/model/etc is more complicated):
- A
building
has manyroom
s - A
room
has many pieces ofequipment
Models:
#spaces/models.py
from django.db import models
class Building(models.Model):
name=models.CharField(max_length=32)
def __unicode__(self):
return self.name
class Room(models.Model):
number=models.CharField(max_length=8)
building=models.ForeignKey(Building)
def __unicode__(self):
return self.number
class Equipment(models.Model):
tech = models.CharField(max_length=64)
room = models.ForeignKey(Room)
def __unicode__(self):
return self.tech
When adding or editing a piece of equipment, it would be nice to be able to limit the room
choices down (by building). This I can do: I add a building
field to the ModelForm, and then as it gets changed by the user, a bit of JQuery in the template file dynamically updates the list of room
s. The admin.py
part looks like:
#spaces/admin.py
from demo.spaces.models import Building, Room, Equipment
from django.contrib import admin
from django import forms
class EquipmentForm(forms.ModelForm):
class Meta:
model = Equipment
building = forms.ModelChoiceField(Building.objects)
class EquipmentAdmin(admin.ModelAdmin):
form = EquipmentForm
admin.site.register(Equipment, EquipmentAdmin)
admin.site.register(Building)
admin.site.register(Room)
When adding a new piece of equipment
, this all works fine--my JQuery code displays -----
until a building is selected, at which point the drop down for the room
field is enabled and populated with the appropriate room
s for that building.
The problem is: when displaying an existing piece of equipment (demo.com/admin/spaces/equipment/12/
) or if the add form doesn't validate, the Room
field properly displays the room
--but the building
field is wiped out. The equipment.room
foreign key value exists in the form instance and the admin automagically takes care of setting the room
field to that value, but the value of the building
field needs to be set by me.
I can get the value without a problem, since it's easy in the init of the form to check for it being an instance, and then traversing back up to get the value:
def __init__(self, *args, **kwargs):
super(EquipmentForm, self).__init__(*args, **kwargs)
if 'instance' in kwargs:
building_value = kwargs['instance'].room.building
But what do I do with that value to make the field display it? The only thing I haven't tried yet is adding more code in my template to use Jquery to get the value and set it at the end, but I'd rather not have to have the javascript in the page hit the database to figure display the value, since it seems like something that should be done when the form is rendered...
Any thoughts? Thank you for you help!