Django在modelform中显示额外字段的值

时间:2009-12-16 05:25:38

标签: django field django-forms

如果在管理员中显示某个(模型)表单时,如何设置字段的值(与表单相关,但不是直接基于同一模型)?

这是我所拥有的简化版本(我的实际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命中数据库来显示值,因为它似乎应该在表单呈现时完成...

有什么想法?谢谢你的帮助!

4 个答案:

答案 0 :(得分:1)

检查表单hereinitial的{​​{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中)。