我有一个Position
模型,其中包含与Emplacement
模型相关的ForeignKey字段。
在Emplacement
的管理员中,我为Position
设置了内联管理员。
我想要实现的是,在num_position
实例中修改Emplacement
字段时,将删除与此实例相关的位置,并创建新的位置。
要实现此目的,我会覆盖Emplacement
模型的save()
方法并检查num_position
是否已更改。
问题是在修改Emplacement
字段后保存num_position
模型时出现以下错误:
ValidationError: Select a valid choice. That choice is not one of the available choices.
我想这与删除/重新创建职位有关,但我找不到原因。
怎么了?
models.py
class Emplacement(models.Model):
num_position = models.IntegerField()
# more fields
__original_num_position = None
def __init__(self, *args, **kwargs):
super(Emplacement, self).__init__(*args, **kwargs)
self.__original_num_position = self.num_position
def save(self, *args, **kwargs):
if self.num_position != self._Emplacement__original_num_position:
# if num_position has changed, delete existing positions and recreate <num_position> positions
Position.objects.filter(emplacement=self).delete()
for i in range(self.num_position):
position = Position()
position.emplacement = self
position.number = i+1
position.save()
super(Emplacement, self).save(*args, **kwargs)
class Position(models.Model):
emplacement = models.ForeignKey(Emplacement)
number = models.IntegerField()
admin.py
class PositionInline(admin.TabularInline):
model = Position
class EmplacementAdmin(admin.ModelAdmin):
inlines = [PositionInline]
my_site.register(Emplacement, EmplacementAdmin)
修改
我也试过一个信号,但得到了同样的错误:
@receiver(post_save, sender=Emplacement)
def create_positions(sender, instance, created, **kwargs):
"""Create positions when num_position has changed."""
if instance.num_position != instance.old_num_position:
Position.objects.filter(emplacement=instance).delete()
for i in range(instance.num_position):
position = Position()
position.emplacement = instance
position.numero = i+1
position.save()
答案 0 :(得分:1)
我遇到了完全相同的问题。 最后通过不在模型端实现创建/删除逻辑但在Forms / FormSets中来解决它。
所以在'main'管理类中,在你的'EmplacementAdmin'案例中,扩展了save_formset方法:
def save_formset(self, request, form, formset, change):
instance = form.instance
deleted = []
if instance and instance.__original_num_position != instance.num_position:
''' create new Positions if needed '''
formset.delete_positions = None # pass on a list, QuerySet, whatever
super(EmplacementAdmin, self).save_formset(request, form, formset, change)
并像这样创建一个PositionFormSet:
class PositionFormSet(BaseInlineFormSet):
delete_positions = []
@property
def deleted_forms(self):
deleted_forms = []
try:
deleted_forms = super(PositionFormSet, self).deleted_forms
except AttributeError:
pass
for form in self.forms:
if form.instance in self.delete_positions:
deleted_forms.append(form)
self.delete_positions = []
return deleted_forms
并在您的inlineadmin中设置此formset:
class PositionInline(admin.TabularInline):
model = Position
formset = PositionFormSet
不完全符合我的想法,但这个技巧对我有用。很想知道是否有更优雅的解决方案: - )