Я нашел довольно элегантное решение , которое хорошо работает для встроенных форм.
Применяется к моей модели, где я фильтрую поле inside_room, чтобы вернуть только комнаты, находящиеся в одном здании:
#spaces/admin.py
class RoomInlineForm(ModelForm):
def __init__(self, *args, **kwargs):
super(RoomInlineForm, self).__init__(*args, **kwargs) #On init...
if 'instance' in kwargs:
building = kwargs['instance'].building
else:
building_id = tuple(i[0] for i in self.fields['building'].widget.choices)[1]
building = Building.objects.get(id=building_id)
self.fields['inside_room'].queryset = Room.objects.filter(building__exact=building)
По сути, если в форму передается ключевое слово 'instance', это существующая запись, отображаемая в строке, и поэтому я могу просто извлечь здание из экземпляра. Если это не экземпляр, это одна из пустых «лишних» строк в строке, и поэтому он проходит через скрытые поля формы в строке, которые сохраняют неявное отношение обратно на главную страницу, и извлекает из него значение id. Затем он захватывает строительный объект на основе этого building_id. Наконец, теперь, имея здание, мы можем установить набор запросов в раскрывающихся списках, чтобы отображать только соответствующие элементы.
Более элегантно, чем мое первоначальное решение, которое вылетело и сгорело как встроенное (но сработало - хорошо, если вы не возражаете, сохраняя форму на полпути, чтобы заполнить выпадающие списки - для отдельных форм):
class RoomForm(forms.ModelForm): # For the individual rooms
class Meta:
mode = Room
def __init__(self, *args, **kwargs): # Limits inside_room choices to same building only
super(RoomForm, self).__init__(*args, **kwargs) #On init...
try:
self.fields['inside_room'].queryset = Room.objects.filter(
building__exact=self.instance.building) # rooms with the same building as this room
except: #and hide this field (why can't I exclude?)
self.fields['inside_room']=forms.CharField( #Add room throws DoesNotExist error
widget=forms.HiddenInput,
required=False,
label='Inside Room (save room first)')
Для не-строк: это работает, если комната уже существует. Если нет, он выдаст ошибку (DoesNotExist), поэтому я поймаю его и затем скрою поле (поскольку у администратора не было возможности ограничить его правильным зданием, поскольку вся запись комнаты была новой, и ни одно здание еще не было установлено!) ... как только вы нажмете "сохранить", оно спасет здание и при перезагрузке может ограничить выбор ...
Мне просто нужно найти способ каскадного фильтра внешних ключей от одного поля к другому в новой записи - то есть, новой записи, выбрать здание, и это автоматически ограничивает выбор в поле выбора inside_room - перед запись будет сохранена. Но это на другой день ...