【问题标题】:Django: Display user's previous choices for a ModelForm in the templateDjango:在模板中显示用户以前对 ModelForm 的选择
【发布时间】:2019-02-20 13:58:54
【问题描述】:

我正在尝试创建一个用户个人资料页面,用户可以在其中查看和更新​​他们对某些事物的偏好,例如他们是否是素食者,或者是否有特定的过敏症等。我希望将数据显示为表单,其中他们当前的偏好已经填充了表单字段。

所以我创建了以下模型:

class FoodPreferences(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE)  # One user has one set of food prefs
    vegetarian = models.BooleanField()
    vegan = models.BooleanField()
    ...

这在我的 forms.py 中被引用:

class FoodPreferencesForm(forms.ModelForm):

    class Meta:
        model = FoodPreferences
        exclude = ('user', )

我尝试创建一个继承FormView 的视图,然后引用该表单,如下所示:

class UserProfileView(generic.FormView):

    template_name = "registration/profile.html"
    form_class = FoodPreferencesForm
    success_url = reverse_lazy('user_profile')

这会将表单正确地保存到模型的实例中,但显然它只是在更新后再次显示空白表单,因此用户不知道他们当前的偏好是什么。

为了实现这一点,我想我可能需要重写get()post() 来为用户获取FoodPreferences 的实例,然后像传递request.POST 对象一样将这些值传递到表单中。但是,首先,我不知道该怎么做,其次,我将负责正确更新数据库,FormView 已经在这样做了。

这就是我为该解决方案准备的:

def get(self, request, *args, **kwargs):

    prefs = FoodPreferences.objects.get(user=request.user)
    form = self.form_class(prefs)
    return render(request, self.template_name, {'form': form, })


def post(self, request, *args, **kwargs):

    form = self.form_class(request.POST)
    if not form.is_valid():
        return render(request, self.template_name, {'form': form, 'error': 'Something went wrong.'})

    curr_prefs = FoodPreferences.objects.update_or_create(form.fields)
    prefs.save()

    return render(request, self.template_name, {'form': form, })

但我在get() 在线收到TypeError: argument of type 'FoodPreferences' is not iterable

form = self.form_class(prefs)

因为它不需要模型实例。

我是否以正确的方式思考这个问题?这似乎是一个很常见的问题,Django 会内置一些东西来解决它,但我找不到任何东西。

【问题讨论】:

    标签: django forms django-models modelform


    【解决方案1】:

    您应该很少需要在基于类的视图中定义getpost,而且您绝对不需要在这里。

    首先,您需要为您的视图使用更合适的基类。在这里您要更新现有项目,因此您应该使用 UpdateView。

    其次,您需要告诉类如何更新现有对象,您可以通过定义get_object 来做到这一点。所以:

    class UserProfileView(generic.UpdateView):
    
        template_name = "registration/profile.html"
        form_class = FoodPreferencesForm
        success_url = reverse_lazy('user_profile')
    
        def get_object(self, queryset=None):
            return self.request.user.foodpreferences
            # or, if you aren't certain that the object already exists:
            obj, _ = FoodPreferences.objects.get_or_create(user=self.request.user)
            return obj
    

    【讨论】:

    • 啊,我明白了。我认为让我感到震惊的是FoodPreferences 在他们第一次提交表单时不存在,所以我认为我不能使用UpdateView。但是从最初的测试来看,您的解决方案似乎运行良好!谢谢!
    猜你喜欢
    • 2015-11-09
    • 2013-06-23
    • 2012-05-24
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 2018-10-19
    • 1970-01-01
    相关资源
    最近更新 更多