1

我可能完全不在这里预订。(如果我是,请随时告诉我。)

我的用例是我有一个学校列表。学校模式很简单:

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() 正在正确制作副本,但是当表单显示时,“名称”或“默认”字段中没有列出任何值。我怀疑问题在于 cls.model = School,但 self.object 是 UserSchool 的一个实例。

我很接近但错过了什么吗?我完全走错了路吗?有没有更好的模型(比如有一个单独的 School 实例和一个“master”的特殊用户)?

(还有一个小麻烦——因为我是 Django 的老手,但是新的基于类的视图,我正在尝试使用 Vanilla Views,因为我发现更容易弄清楚发生了什么。)

4

1 回答 1

0

只是为了排除明显的情况-您没有将任何内容传递给表单构造函数。你试过instance=user_school吗?可能还有更多需要工作的地方,但我会从那里开始。

稍微扩展一下 - 在您看来,您完全覆盖了内置get方法。这很好,但这意味着您绕过了视图超类的一些自动化行为。具体来说,(您的祖先类之一)的方法使用视图类的方法实例化get表单。,另一个祖先,定义:ProcessFormViewget_formFormMixinget_form

return form_class(**self.get_form_kwargs())

并添加get_form_kwargs到表单的:ModelFormMixinself.objectkwargs

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

可能需要进行更多更改——我尚未对此进行测试——但getset方法都使用get_object, 并将其绑定到适当的表单。

于 2013-11-08T02:41:34.223 回答