我可能完全不在这里预订。 (如果我是,请随时告诉我。)
我的用例是我有一份学校名单。学校模式很简单:
class School(models.Model):
name = models.CharField(max_length=100)
mascot = models.CharField(max_length=100, null=True, blank=True)
当我的用户想要编辑其中一所学校时,我不希望他们编辑主副本。相反,我想给他们自己的副本,他们可以玩。完成编辑后,他们可以提交更改,其他人也会批准。所以我有另一个类用于学校用户的副本:
class UserSchool(models.Model):
name = models.CharField(max_length=100)
mascot = models.CharField(max_length=100, null=True, blank=True)
master_school = models.ForeignKey(School)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
所以我设置了一个表单来处理UserSchool的编辑:
class UserSchoolForm(forms.ModelForm):
class Meta:
model = UserSchool
fields = ['name','mascot']
现在我有了EditSchool表格:
class EditSchool(UpdateView):
model = School
success_url = reverse_lazy('list_schools')
form_class = UserSchoolForm
def get(self, request, *args, **kwargs):
school = self.get_object()
# make a copy of the school for this user
user_school, created = UserSchool.objects.get_or_create(
master_school=school, user=request.user,
defaults={'name' : school.name, 'mascot' : school.mascot})
self.object = user_school
form = UserSchoolForm()
context = self.get_context_data(form=form)
return self.render_to_response(context)
我知道get()正确地复制了副本,但是当表单显示时,“name”或“default”字段中没有列出值。我怀疑问题在于cls.model = School,但self.object是UserSchool的一个实例。
我是否关闭但遗漏了什么?我完全走错了路吗?有没有更好的模型(比如有一个具有“master”特殊用户的School实例)?
(还有一个小的复杂因素 - 因为我是Django的老手,但新的基于类的视图,我正在尝试使用Vanilla Views,因为我发现更容易弄清楚发生了什么。)< / p>
答案 0 :(得分:0)
只是为了排除显而易见的事实 - 你没有向表单构造函数传递任何东西。你用instance=user_school
试过了吗?可能有更多需要工作但我会从那里开始。
要稍微扩展一下 - 在您的视图中,您完全覆盖了内置的get
方法。这没关系,但这意味着你绕过了视图超类的一些自动行为。具体来说,get
(您的一个祖先类)的ProcessFormView
方法使用视图类的get_form
方法实例化表单。 FormMixin
,另一个祖先,定义get_form
:
return form_class(**self.get_form_kwargs())
get_form_kwargs
上的ModelFormMixin
将self.object
添加到表单的kwargs
:
kwargs.update({'instance': self.object})
由于被覆盖的get
方法未调用get_form
,因此它也不会调用get_form_kwargs
,因此不会遍历为表单提供初始绑定的整个路径
我个人会尝试通过修改自定义视图的get_object
方法并将其余视图单独处理来解决此问题:
class EditSchool(UpdateView):
model = School
success_url = reverse_lazy('list_schools')
form_class = UserSchoolForm
def get_object(self, queryset=None):
school = super(EditSchool, self).get_object(queryset=queryset)
user_school, created = UserSchool.objects.get_or_create(
master_school=school, user=self.request.user,
defaults={'name' : school.name, 'mascot' : school.mascot})
return user_school
可能需要进行更多更改 - 我尚未对此进行测试 - 但get
和set
方法都使用get_object
,并根据需要将其绑定到表单。