如果在管理员中显示某个(模型)表单时,如何设置字段的值(与表单相关,但不是直接基于同一模型)?
这是我所拥有的简化版本(我的实际app / model / etc更复杂):
building
有许多room
s room
有许多equipment
型号:
#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
添加或编辑设备时,最好能够限制room
选项(通过构建)。我可以这样做:我向ModelForm添加一个building
字段,然后当用户更改它时,模板文件中的一些JQuery会动态更新room
列表。 admin.py
部分如下:
#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)
添加新的equipment
时,这一切都运行良好 - 我的JQuery代码显示-----
,直到选择了一个建筑物,此时room
字段的下拉列表已启用并填充了该建筑物的相应room
。
问题是:在显示现有设备(demo.com/admin/spaces/equipment/12/
)时,或者如果添加表单未验证,则Room
字段会正确显示{{ 1}} - 但room
字段已被删除。表单实例中存在building
外键值,管理员自动负责将equipment.room
字段设置为该值,但room
字段的值需要由我设置
我可以毫无问题地得到这个值,因为在表单的 init 中很容易检查它是否是一个实例,然后遍历以获取值:
building
但是如何使用该值来显示字段呢?我还没有尝试过的唯一事情是在我的模板中添加更多代码以使用Jquery获取值并在最后设置它,但我宁愿不必让页面中的javascript命中数据库来显示值,因为它似乎应该在表单呈现时完成...
有什么想法?谢谢你的帮助!
答案 0 :(得分:1)
检查表单here中initial
的{{1}}参数。也许将初始设置为Field
对象的建筑设置会有所帮助。
另外,你真的需要限制选择到建筑物吗?我刚刚发现足以修改Building
的{{1}}方法,因此它会显示Room
和__unicode__
个数字:
Building
然后你会得到所有房间的清单,但很容易找到它们所属的建筑......
答案 1 :(得分:1)
这个应该有效:
class EquipmentForm(ModelForm):
def __init__(self, *args, **kwargs):
kwargs['initial']=kwargs.get('initial',{})
if kwargs['instance']:
kwargs['initial']['building']=kwargs['instance'].building
super(EquipmentForm, self).__init__(*args, **kwargs)
在views.py中:
instance.building="some_building"
form = EquipmentForm(request.POST, instance=instance)
答案 2 :(得分:0)
这个怎么样?
def __init__(self, *args, **kwargs):
super(EquipmentForm, self).__init__(*args, **kwargs)
if 'instance' in kwargs:
self.data['building']=kwargs['instance'].room.building
答案 3 :(得分:0)
这对我有用:
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=':',
empty_permitted=False, instance=None):
if instance:
initial = initial or {}
initial['field_name'] = instance.some_value
super(MyCustomForm, self).__init__(data, files, auto_id, prefix,initial,
error_class, label_suffix,empty_permitted, instance)
我故意不使用* args,** kwargs因为我没有检查这个构造函数在代码中是如何被称为elswere的(实例和initial可能在* args或** kwargs中)。