具有1:N选择的DjangoAdmin表单不会保存对象

时间:2018-04-11 15:12:15

标签: python django django-forms django-rest-framework django-admin

我正在寻找一种方法,将一个或多个现有对象分配给当前对象,同时在add部分创建。像InLine这样的东西,但我不想创建它们,只选择并分配。

两个示例模型:

class Location(models.Model):
    name = models.CharField(max_length=30)

class Device(models.Model):
    name = models.CharField(max_length=20)
    location = models.ForeignKey(Location, null=True, blank=True, on_delete=models.DO_NOTHING)

因此,在Django Admin中创建Location时,我希望能够分配1-N个现有Devices

我找到了一种方法,使用自定义Form

这是admin.py

中的自定义表单
class LocationForm(forms.ModelForm):
    class Meta:
        model = Location
        fields = '__all__'

    devices = forms.ModelMultipleChoiceField(queryset=Device.objects.all()) 

    def __init__(self, *args, **kwargs):
        super(LocationForm, self).__init__(*args, **kwargs)
        if self.instance:
            self.fields['devices'].initial = self.instance.device_set.all()

    def save(self, *args, **kwargs):
        instance = super(LocationForm, self).save(commit=False)
        self.fields['devices'].initial.update(location=None)
        self.cleaned_data['devices'].update(location=instance)
        return instance

@admin.register(Location)
class LocationAdmin(admin.ModelAdmin):
    form = LocationForm

只要我不保存Location对象,它就能正常工作。这是一张django admin的外观图片。 Django Admin One to Many

但是当我尝试保存位置时,出现以下错误:

 File "admin.py", line 21, in save
    api          |     self.cleaned_data['devices'].update(location=instance)
    api          |   File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 692, in update
    api          |     rows = query.get_compiler(self.db).execute_sql(CURSOR)
    api          |   File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1378, in execute_sql
    api          |     cursor = super().execute_sql(result_type)
    api          |   File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1054, in execute_sql
    api          |     sql, params = self.as_sql()
    api          |   File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1334, in as_sql
    api          |     val.prepare_database_save(field),
    api          |   File "/usr/local/lib/python3.6/site-packages/django/db/models/base.py", line 932, in prepare_database_save
    api          |     raise ValueError("Unsaved model instance %r cannot be used in an ORM query." % self)
    api          | ValueError: Unsaved model instance <Location: Test Project> cannot be used in an ORM query.

我已尝试在保存方法中手动保存对象,但这也没有用,因为我不知道为什么它不能保存,所以我的想法已经用完了一点都不我虽然超类中的save方法已经足够但显然情况并非如此。

1 个答案:

答案 0 :(得分:1)

在读了七次问题之后才发现它。

在日志的第一行显示self.cleaned_data['devices'].update(location=instance)所以instance显然是未保存的内容,因此无法用作查询参数,因此我编辑了表单&#39; s像这样保存方法。

def save(self, *args, **kwargs):
        instance = super(LocationForm, self).save(commit=False)
        self.fields['devices'].initial.update(location=None)
        instance.save()
        self.cleaned_data['devices'].update(location=instance)        
        return instance

它正在发挥作用。