如果引发 ValidationError,删除链接会在 Django 管理内联表单集中消失
Posted
技术标签:
【中文标题】如果引发 ValidationError,删除链接会在 Django 管理内联表单集中消失【英文标题】:Delete link disappears in Django admin inline formset if ValidationError raised 【发布时间】:2011-11-25 01:40:59 【问题描述】:我有一个带有KeywordInline
的表格。当我使用表单添加新对象时,内联表单集有一个 js-link 可以将新表单添加到表单集中。新添加的表单有一个启用 js 的删除按钮(右侧的 x 标记)。
关键字内联
class KeywordInline(admin.TabularInline):
fields = ('word',)
model = models.Keyword
formset = forms.KeywordFromset
verbose_name = _('Keyword')
verbose_name_plural = _('Keywords')
extra = 1
can_delete = True
def get_readonly_fields(self, request, obj=None):
if obj:
if str(obj.status) == 'Finished':
self.extra = 0
self.can_delete = False
self.max_num = obj.keyword_set.count()
return ('word',)
self.extra = 1
self.can_delete = True
self.max_num = None
return []
KeywordFromset
class KeywordFromset(BaseInlineFormSet):
def clean(self):
super(KeywordFromset, self).clean()
formset_keywords = set()
for form in self.forms:
if not getattr(form, 'cleaned_data', ).get('word', None):
keyword = None
else:
keyword = form.cleaned_data['word']
if keyword in formset_keywords:
form._errors['word'] = ErrorList([_(self.get_unique_error_message([_('Keyword')]))])
else:
formset_keywords.add(keyword)
现在,如果我点击保存按钮并且 ValidationError 上升,那些删除按钮将从一开始就消失。因此,如果我错误地添加了错误的关键字,我将无法删除它。
这是正常行为吗?以及如何使删除链接持续存在?
非常感谢任何帮助。
【问题讨论】:
【参考方案1】:触发 ValidationError 的内联没有删除链接,因为它们尚未保存到数据库,因此没有删除链接。
我意识到这是不一致的行为(因为您可以在点击“保存”按钮之前删除这些行,但是一旦它们触发了验证错误就不能删除),但这是 Django 的正常默认方式。
要解决此问题,您可以override the template for inline 并在验证错误的情况下显示删除按钮。
【讨论】:
他不是在谈论删除复选框,而是在谈论“额外”内联上的 js x 按钮,而不是数据库中的那些。我不确定这是如何被接受的。我现在也遇到了这个问题。 code.djangoproject.com/ticket/15910【参考方案2】:我在使用 django 2.2 时遇到了这个问题
首先(不工作)我尝试创建删除链接
复制 admin/edit_inline/tabular.html 以在项目中编辑
改用新模板
class MyAdminInline(admin.TabularInline):
# ... other stuff
template = 'admin/edit_inline/tabular.html'
添加一些脚本
% load i18n admin_urls static admin_modify %
<script type="text/javascript">
function removeRowById(id, index)
document.getElementById(id).remove();
</script>
修改删除链接的显示方式
<td class="delete">
% if inline_admin_form.original % inline_admin_form.deletion_field.field % endif %
% if not inline_admin_form.original % <div><a class="inline-deletelink" onclick="removeRowById(' inline_admin_formset.formset.prefix -% if not forloop.last % forloop.counter0 % else %empty% endif %', forloop.counter0 )">Remove</a></div> % endif %
</td>
它显示链接按钮,但保存时。 django 向我抛出另一个错误。 所以这种方式不会在 inline_admin_formset 内更新
第二(工作)我尝试另一种方式
只需更改删除复选框的显示方式
<td class="delete">
% if inline_admin_form.original % inline_admin_form.deletion_field.field % endif %
</td>
到
<td class="delete">
% if inline_admin_form.original % inline_admin_form.deletion_field.field
% elif not inline_admin_form.original %
% if inline_admin_form.form.non_field_errors %
inline_admin_form.deletion_field.field
% endif %
% endif %
</td>
如果字段不是原始的(有 pk)并且上面有验证错误,则显示删除复选框
【讨论】:
以上是关于如果引发 ValidationError,删除链接会在 Django 管理内联表单集中消失的主要内容,如果未能解决你的问题,请参考以下文章
从 django 模型的保存方法中引发 ValidationError?
如何检查 Prismatic Schema 强制期间引发的 ValidationError?
Django 模型 validate_unique 方法不会引发 ValidationError
如何在 Django 的 views.py 中引发 ValidationError(或做类似的事情)?