Django-admin没有足够早地调用对象的save方法

2024-09-26 22:10:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Django有两个应用程序,其中一个应用程序的模型(ScopeItem)在其实例创建时必须同时创建另一个应用程序模型的实例(Workflow);也就是说,ScopeItem包含了它的工作流。在

这是很好的工作时,从外壳尝试。创建新的ScopeItem将创建一个Workflow,并将其存储在ScopeItem中。在admin中,我得到一个错误,即需要workflow属性。属性未填充,模型定义要求设置该属性。不过,overwritedsave方法可以做到这一点。因此,我的问题是,如何在签入管理发生之前调用save?在

{{{myinstance,然后在cd2}中成功地创建了一个

我知道我可以在ScopeItem中允许空的workflow属性,或者合并ScopeItemWorkflow类,以避免管理问题。但这两种方法都会在以后引起麻烦,我希望避免此类黑客攻击。在

我也不想在save_item中重复代码。仅仅从那里调用save显然不能切断它。在

以下是scopeitems/models.py中的代码:

class ScopeItem(models.Model):
    title = models.CharField(max_length=64)
    description = models.CharField(max_length=4000, null=True)
    workflow = models.ForeignKey(Workflow)

    def save(self, *args, **kwargs):
        if not self.id:
            workflow = Workflow(
                description='ScopeItem %s workflow' % self.title,
                status=Workflow.PENDING)
            workflow.save()
            self.workflow = workflow
        super(ScopeItem, self).save(*args, **kwargs)

workflow/models.py

^{pr2}$

scopeitems/admin.py我有:

from django.contrib import admin

from .models import ScopeItem
from workflow.models import Workflow


class ScopeItemAdmin(admin.ModelAdmin):
    list_display = ('title', 'description', 'status')
    list_filter = ('workflow__status', )
    search_fields = ['title', 'description']

    def save_model(self, request, obj, form, change):
        obj.save()

    def status(self, obj):
        return Workflow.STATUS_CHOICES[obj.workflow.status][1]

admin.site.register(ScopeItem, ScopeItemAdmin)

Tags: py模型selfobj应用程序属性admintitle
3条回答

您需要从管理中使用的表单中排除该字段,以便它不会被验证。

class ScopeItemForm(forms.ModelForm):
    class Meta:
        exclude = ('workflow',)
        model = ScopeItem

class ScopeItemAdmin(admin.ModelAdmin):
    form = ScopeItemForm
    ...

admin.site.register(ScopeItem, ScopeItemAdmin)

@Daniel Roseman的回答是正确的,只要你不需要在管理中编辑工作流字段。如果您需要编辑它,那么您需要在管理表单上编写一个自定义的clean()方法。

在表单.py

class ScopeItemAdminForm(forms.ModelForm):
    class Meta:
        model = ScopeItem

    def clean(self):
        cleaned_data = super(ScopeItemAdminForm, self).clean()
        if 'pk' not in self.instance:
            workflow = Workflow(
                description='ScopeItem %s workflow' % self.title,
                status=Workflow.PENDING)
            workflow.save()
            self.workflow = workflow
        return cleaned_data

在管理员py

^{pr2}$

您可以在workflow上设置字段blank=True

您说过不想在ScopeItem中允许“空workflow属性。”设置blank=Truepurely validation-related。因此,在后端workflow仍然是NOT NULL。来自Django文档:

If a field has blank=True, form validation will allow entry of an empty value.

参考您的例子,您应该能够使用:

workflow = models.ForeignKey(Workflow, blank=True)

相关问题 更多 >

    热门问题