Chr*_*att 7 django django-forms django-admin
非常基本的使用场景.我想保存创建对象的用户和上次修改它的用户.但是,它是一个内联模型,所以我当然需要使用save_formset.Django文档有以下示例代码:
class ArticleAdmin(admin.ModelAdmin):
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
instance.user = request.user
instance.save()
formset.save_m2m()
Run Code Online (Sandbox Code Playgroud)
问题是,如果你注意到,因为super从未被调用,这是一个死胡同.如果ModelAdmin是子类并且以相同的方式覆盖此方法,则会丢失父级中固有的功能.这很重要,因为这是一个常见的使用场景,我想要分解功能,所以我创建了以下内容:
class TrackableInlineAdminMixin(admin.ModelAdmin):
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
if hasattr(instance, 'created_by') and hasattr(instance, 'modified_by'):
if not instance.pk:
instance.created_by = request.user
instance.modified_by = request.user
instance.save()
formset.save_m2m()
super(TrackableInlineAdminMixin, self).save_formset(request, form, formset, change)
Run Code Online (Sandbox Code Playgroud)
我super更多地调整了出于习惯的调用,而不是认为它实际上会导致formset保存两次.然而,它仍然适用于除了一个之外的每个场景:删除.只要您尝试删除管理员中的内联,就会出现错误.这个错误很模糊,并没有真正与我的问题相关,但我相信这与你刚删除其中一个实例后再次尝试保存formset有关.super删除调用时,代码工作正常.
长和短,有没有什么方法我都缺少自定义formset保存行为并允许子类做自己的覆盖?
这是一个doozie.
我玩得很开心,似乎所有动作都发生在这里django.forms.models.BaseModelFormSet.
问题是ModelFormSet.save()删除实例而不管commit标志如何,并且不修改表单以反映已删除的状态.
如果save()再次调用它会遍历表单并在ModelChoiceField清理时尝试提取引用的ID并引发无效的选择错误.
def save_existing_objects(self, commit=True):
self.changed_objects = []
self.deleted_objects = []
if not self.initial_forms:
return []
saved_instances = []
for form in self.initial_forms:
pk_name = self._pk_field.name
raw_pk_value = form._raw_value(pk_name)
# clean() for different types of PK fields can sometimes return
# the model instance, and sometimes the PK. Handle either.
pk_value = form.fields[pk_name].clean(raw_pk_value)
pk_value = getattr(pk_value, 'pk', pk_value)
obj = self._existing_object(pk_value)
if self.can_delete and self._should_delete_form(form):
self.deleted_objects.append(obj)
obj.delete()
# problem here causes `clean` 6 lines up to fail next round
# patched line here for future save()
# to not attempt a second delete
self.forms.remove(form)
Run Code Online (Sandbox Code Playgroud)
我能够解决此问题的唯一方法是修补BaseModelFormset.save_existing_objects删除self.forms对象时删除表单.
做了一些测试,似乎没有任何不良影响.
| 归档时间: |
|
| 查看次数: |
2159 次 |
| 最近记录: |