Почему пользовательское поле modelform в админке Django не сохраняет данные
У меня есть 2 модели: Room и Roomgroup. Моя цель - представлять модели в админке обоими способами - Roomgroup в Room admin и Rooms в Roomgroup admin, поэтому я настроил модель Roomgroup admin в AdminModelforms, но она не работает так, как я ожидал, и я хотел бы знать, где я делаю что-то неправильно. И не слишком ли я усложняю?
Когда я сохраняю Roomgroup в админке, он не сохраняет экземпляр roomgroup в модель Room даже для нового экземпляра Roomgroup даже для существующего, похоже, что данные очищаются перед сохранением(). Что не так?
Примеры моделей здесь сокращены, но они соотносятся с моим кодом.
models.py
:
class Room(models.Model):
name = models.CharField(max_length=200, verbose_name=_('Name'), unique=True, null=False)
roomgroup = models.ForeignKey(Roomgroup, on_delete=models.SET_NULL, verbose_name=_('Room group'), null=True, blank=True)
class Roomgroup(models.Model):
name = models.CharField(max_length=200, verbose_name=_('Name'), unique=True, null=False)
admin_forms.py
:
class RoomgroupAdminForm(forms.ModelForm):
rooms = forms.ModelMultipleChoiceField(
Room.objects.all(),
widget=FilteredSelectMultiple(verbose_name=_('Rooms'), is_stacked=False),
required=False,
)
def __init__(self, *args, **kwargs):
super(RoomgroupAdminForm, self).__init__(*args, **kwargs)
# show just rooms without group
self.fields['rooms'].queryset = Room.objects.filter(roomgroup=None)
if self.instance.pk:
# show rooms without roomgroup and the ones already assigned to this roomgroup
self.fields['rooms'].queryset = Room.objects.filter(roomgroup=None) | Room.objects.filter(roomgroup=self.instance)
# preselect rooms already assigned for the roomgroup
self.initial['rooms'] = self.instance.room_set.all()
def save(self, commit=True):
instance = super(RoomgroupAdminForm, self).save(commit=False)
if not instance.pk:
for room in list(self.cleaned_data["rooms"]):
room.roomgroup = instance
if instance.pk:
"""
if roomgroup exists save roomgroup to rooms
"""
old_rooms = list(self.instance.room_set.all())
# for every new selected room
for room in list(self.cleaned_data['rooms']):
if room not in old_rooms:
# define roomgroup
room.roomgroup = instance
# remove roomgroup for rooms removed from group
for room in old_rooms:
if room not in list(self.cleaned_data['rooms']):
room.roomgroup = None
if commit:
instance.save()
instance.m2m_save()
return instance
просто для информации, admin.py
@admin.register(Roomgroup)
class RoomgroupAdmin(admin.ModelAdmin):
def get_rooms(self, obj):
return ", ".join([room.name for room in obj.room_set.all()])
form = RoomgroupAdminForm
list_display = ('name', 'timetable', 'get_rooms')
get_rooms.short_description = _('Rooms')