首页 > 解决方案 > 在 Django 中使用 SelectMultiple 保存失败

问题描述

我在使用“选择多个字段”保存数据库数据时遇到问题我的代码如下所示:

模型.py

class Author(models.Model):
    author_name = models.CharField(max_length=100)
    author_lastname = models.CharField(max_length=100)

class Book(models.Model):
    statement_title = models.CharField(max_length=1000, null=True, blank=True)
    author = models.ManyToManyField(Author,blank=True)

表格.py

class BookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = ['__all__']
        
        widgets = {
            'title': forms.Textarea(attrs={'type': 'text',
                                           'placeholder': 'Book title'}
            'author': forms.SelectMultiple()
        }

如果我添加一个新对象,一切都会保存但没有作者,但如果我在管理页面中保存作者,我可以在书籍详细信息视图中显示作者。

当然,我尝试了很多解决方案来解决这个问题,但没有解决我的问题。我知道我犯了一个错误,但我不知道在哪里......也许我应该在views.py中添加一些额外的东西?我将非常感谢任何提示和线索。

编辑:

我附上了 views.py (edit_book类似于add_book)。这只是一个典型的视图功能。当我尝试显示作者 ID 时,它工作正常。

视图.py

def edit_book(request, pk):
    book = get_object_or_404(Book, pk=pk)
    if request.method == "POST":
        form = BookForm(request.POST, instance=book)
        if form.is_valid():
            book = form.save(commit=False)
            print(">>>>>>>>>>>>>>>>>>>>>>>")
            print(book.author.all)
            for author in form.cleaned_data['author']:
                print(author.id)
            book.save()
            return redirect('book_details', book.id)
    else:
        form = BookForm(instance=book)
    return render(request,
                  'books/book/book_new.html',
                  {'form': form})

标签: django

解决方案


请不要使用form.save(commit=False). AModelForm只能保存ManyToManyFields with commit=True(或稍后 with .save_m2m()),如Django 文档中讨论save()方法

当您的模型与另一个模型具有多对多关系时,会看到使用commit=False的另一个副作用。如果您的模型具有多对多关系并且您指定何时保存表单,则 Django 无法立即保存多对多关系的表单数据。这是因为在实例存在于数据库中之前,无法为实例保存多对多数据。commit=False

但这里最简单的方法就是让表单本身保存对象:

def edit_book(request, pk):
    book = get_object_or_404(Book, pk=pk)
    if request.method == 'POST':
        form = BookForm(request.POST, instance=book)
        if form.is_valid():
            book = form.save()  # ← will save many-to-many fields
            return redirect('book_details', book.id)
    else:
        form = BookForm(instance=book)
    return render(
        request,
        'books/book/book_new.html',
        {'form': form}
    )

Django 不能保存多对多关系本身的原因是因为首先您创建的对象需要在数据库端创建,以具有主键。只有这样,联结表[wiki]才能填充元素。


推荐阅读