使用 ModelForm Django 保存 ManytoManyField 的问题
Problem Saving ManytoManyField using ModelForm Django
models.py
from django.db import models
from django.contrib.auth.models import User
class Elements(models.Model):
element = models.CharField(max_length=10, unique=True)
def __str__(self):
return self.element
class Hero(models.Model):
added = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=10, unique=True)
element = models.ManyToManyField(Elements, blank=True)
def __str__(self):
return self.name
forms.py
from django import forms
from .models import Elements, Hero
class HeroForm(forms.ModelForm):
class Meta:
model = Hero
exclude = [
'added'
]
widgets = {
'element': forms.CheckboxSelectMultiple
}
views.py
from django.shortcuts import render
from .forms import HeroForm
def home(request):
form = HeroForm(request.POST or None)
if form.is_valid():
hero = form.save(commit=False)
hero.added = request.user
hero.save()
form = HeroForm()
return render(request, 'home.html', {'form': form})
每当我尝试像上面 views.py 中所示那样在保存前操作模型时,元素的 (manytoamyfield) 数据会自动设置为空。但是,如果我保存表单,因为它保存了用户选择的元素数据。
如何在保存表单之前操作表单数据并按原样保留 manytomanyfield 数据?
提前致谢
如果使用commit=False
,则ModelForm
不能保存多对多关系,因为此时对象没有主键。
您可以在 保存表格之前简单地更改表格中的实例:
from django.contrib.auth.decorators import login_required
@login_required
def home(request):
if request.method == 'POST':
form = HeroForm(request.POST)
if form.is_valid():
form<b>.instance.added = request.user</b>
form<b>.save()</b> # <i>no</i> commit=False
form = HeroForm()
else:
form = HeroForm()
return render(request, 'home.html', {'form': form})
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL
[Django-doc] to refer to the user model, than to use the User
model [Django-doc] directly. For more information you can see the referencing the User
model section of the documentation.
Note: You can limit views to a view to authenticated users with the
@login_required
decorator [Django-doc].
models.py
from django.db import models
from django.contrib.auth.models import User
class Elements(models.Model):
element = models.CharField(max_length=10, unique=True)
def __str__(self):
return self.element
class Hero(models.Model):
added = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=10, unique=True)
element = models.ManyToManyField(Elements, blank=True)
def __str__(self):
return self.name
forms.py
from django import forms
from .models import Elements, Hero
class HeroForm(forms.ModelForm):
class Meta:
model = Hero
exclude = [
'added'
]
widgets = {
'element': forms.CheckboxSelectMultiple
}
views.py
from django.shortcuts import render
from .forms import HeroForm
def home(request):
form = HeroForm(request.POST or None)
if form.is_valid():
hero = form.save(commit=False)
hero.added = request.user
hero.save()
form = HeroForm()
return render(request, 'home.html', {'form': form})
每当我尝试像上面 views.py 中所示那样在保存前操作模型时,元素的 (manytoamyfield) 数据会自动设置为空。但是,如果我保存表单,因为它保存了用户选择的元素数据。
如何在保存表单之前操作表单数据并按原样保留 manytomanyfield 数据?
提前致谢
如果使用commit=False
,则ModelForm
不能保存多对多关系,因为此时对象没有主键。
您可以在 保存表格之前简单地更改表格中的实例:
from django.contrib.auth.decorators import login_required
@login_required
def home(request):
if request.method == 'POST':
form = HeroForm(request.POST)
if form.is_valid():
form<b>.instance.added = request.user</b>
form<b>.save()</b> # <i>no</i> commit=False
form = HeroForm()
else:
form = HeroForm()
return render(request, 'home.html', {'form': form})
Note: In case of a successful POST request, you should make a
redirect
[Django-doc] to implement the Post/Redirect/Get pattern [wiki]. This avoids that you make the same POST request when the user refreshes the browser.
Note: It is normally better to make use of the
settings.AUTH_USER_MODEL
[Django-doc] to refer to the user model, than to use theUser
model [Django-doc] directly. For more information you can see the referencing theUser
model section of the documentation.
Note: You can limit views to a view to authenticated users with the
@login_required
decorator [Django-doc].