2009-12-16 4 views
3

Как установить значение поля (которое относится к форме, но не основано непосредственно на той же модели) в форме (модели), когда оно отображается в администраторе?Django отображаемое значение дополнительного поля в modelform

Вот упрощенная версия того, что у меня есть (моя фактическое приложение/модель/и т.д. является более сложной):

  • building имеет много room сек
  • А 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 s. 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 поля правильно отображает room --but building поля уничтожено. Значение внешнего ключа существует в экземпляре формы, и администратор автоматически выполняет настройку поля room на это значение, но значение поля building должно быть установлено мной.

я могу получить значение без проблем, так как это легко в инициализации формы, чтобы проверить это является экземпляром, а затем проходя обратно, чтобы получить значение:

def __init__(self, *args, **kwargs): 
    super(EquipmentForm, self).__init__(*args, **kwargs) 
    if 'instance' in kwargs: 
     building_value = kwargs['instance'].room.building 

Но что мне делать с этим значением, чтобы отобразить это поле? Единственное, что я еще не пробовал, это добавить в свой шаблон больше кода, чтобы использовать Jquery для получения значения и установки его в конце, но я бы предпочёл, чтобы javascript на странице не попал в базу данных, чтобы отобразить отображение значение, поскольку кажется, что что-то должно быть сделано при визуализации формы ...

Любые мысли? Спасибо, что помогли!

ответ

1

Проверьте initial параметр Field в формах here. Может быть, настройка здания с первоначальным набором на объект Building поможет.


Кроме того, вам действительно нужно ограничивать выбор до здания?Я только что нашел достаточно изменить __unicode__ СПОСОБА Room «s, поэтому он показывает как Building и Room номер:

def __unicode__(self): 
    return "Room nr %s in %s" % (self.number, self.building) 

Тогда вы получите список всех номеров, но легко узнать, к какому здание они принадлежат к ...

+0

Я бы предпочел быть в состоянии ограничить выбор для строительства, так как A) Там будет пара сотен комнат и B) Я хочу использовать ту же процедуру для ограничения других внешних ключей в других местах. – mightyhal

+0

Поле.initial не поможет, так как значение, которое я хочу установить для здания, является динамическим (зависит от экземпляра). Form.initial выглядит многообещающим, устанавливая self.initial ['building'] в __init__, а print self.initial вертит словарь всех полей и их значений ... но когда он отображает, он не устанавливает значение для построения (хотя похоже, что это должно быть) – mightyhal

0

Как насчет этого?

def __init__(self, *args, **kwargs): 
super(EquipmentForm, self).__init__(*args, **kwargs) 
if 'instance' in kwargs: 
    self.data['building']=kwargs['instance'].room.building 
+0

модификация self.data ['building'] в __init__ не влияет. (отбрасывая print self.data в __init__, дает мне a {}, поэтому, возможно, мне нужно переопределить что-то помимо __init__, чтобы повлиять на self.data или self.data, это неправильная модификация) – mightyhal

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) 

Я намеренно не использую * арг, ** kwargs, потому что я не проверял, как этот конструктор вызывается elswere в коде (например, и начальная может быть в * args или ** kwargs).

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) 
Смежные вопросы