【问题标题】:ValidationError when modifying an object with inline admin使用内联管理员修改对象时出现 ValidationError
【发布时间】:2013-02-07 10:04:21
【问题描述】:

我有一个 Position 模型,其 ForeignKey 字段与 Emplacement 模型相关。 在Emplacement 的管理员中,我为Position 设置了一个内联管理员。

我想要实现的是,当Emplacement实例中修改num_position字段时,删除与该实例相关的位置并创建新的位置。

为了实现这一点,我重写了 Emplacement 模型的 save() 方法并检查 num_position 是否已更改。

问题是在修改其num_position 字段后保存Emplacement 模型时,我收到以下错误:

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()

【问题讨论】:

  • 我刚刚尝试创建一个新的 django 项目并将此代码粘贴到应用程序中。创建/保存 Emplacement/Position 对象时,我没有看到任何错误。仅运行此代码时您是否看到异常,或者是否有一些特定的方法来触发错误?

标签: django admin


【解决方案1】:

我遇到了完全相同的问题。 最后通过不在模型端实现创建/删除逻辑而是在 Forms/FormSets 中解决它。

因此,在“主”管理类中,在您的情况下为“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 中设置此表单集:

class PositionInline(admin.TabularInline):
    model = Position
    formset = PositionFormSet

不完全是我的想法,但这个技巧对我有用。很想知道是否有一些更优雅的解决方案:-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-10
    • 1970-01-01
    • 2012-04-07
    • 1970-01-01
    • 2022-06-28
    • 2012-06-24
    • 1970-01-01
    • 2015-06-21
    相关资源
    最近更新 更多