【问题标题】:2 Forms on same model not saving as same user - Django2 同一模型上的表单不保存为同一用户 - Django
【发布时间】:2020-12-29 17:39:05
【问题描述】:

我正在创建一份问卷/调查,并在同一模型上构建了两个表单(模型表单)。这些表单在单独的视图上调用,但在保存时,它们在数据库中显示为单独的用户。我不确定如何让它们保存为同一个用户,我已经在使用'post = form.save(commit=False), post.user = request.user, post.save()' 方法来保存表格。

编辑:添加以尝试保存到同一实例

型号:

 class QuizTakers(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    industry_choices = (
                        (1, 'Service'),
                        (2, 'Hospitality'),
                        (3, 'Wholesale/Retail'),
                        (4, 'Manufacturing'),
                        (5, 'Agriculture')
                        )

    industry  =  MultiSelectField(choices=industry_choices, max_length=1, max_choices=1)
    company_name = models.CharField( max_length=100)
    email = models.EmailField(blank=True)
    score = models.FloatField(default=0)
    completed = models.BooleanField(default=False)
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.company_name

表格:

# Form for getting company name
class QuizTakerForm(forms.ModelForm):
    class Meta:
        model = QuizTakers
        fields = ['company_name']

# Form for getting company industry
class QTIndustryForm(forms.ModelForm):
    class Meta:
        model = QuizTakers
        fields = ['industry']
    

观看次数:

# view for getting company name
def start(request):
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = QuizTakerForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            request.session['company_name'] = form.cleaned_data['company_name']
            post = form.save(commit=False)
            post.user = request.user
            post.save()

            # redirect to a new URL:
            return HttpResponseRedirect('industry/')

    # if a GET (or any other method) we'll create a blank form
    else:
        form = QuizTakerForm()
    return render(request, 'ImpactCheck/start.html', {'form': form})

# view for getting industry 
class IndustryView(FormView):
    template_name = 'ImpactCheck/industry.html'
    form_class = QTIndustryForm
    success_url = '1/'


    def get(self, request):
        company_name = request.session['company_name']
        this_user=QuizTakers.objects.filter(company_name=company_name).order_by('-timestamp').first()
        form=self.form_class(instance=this_user)
        company_name = request.session['company_name']
        return render(request, 'ImpactCheck/industry.html', {'form': form, 'company_name': company_name})

    def form_valid(self, form):
          # This method is called when valid form data has been POSTed.
          # It should return an HttpResponse.
          post = form.save(commit=False)
          post.user = self.request.user
          post.save()
          return HttpResponseRedirect('/1')

【问题讨论】:

  • 当你说这些表格在不同的视图上调用时,你知道它们的填写顺序是什么吗?如果您在不同的视图中拥有这些表单,则其中一个必须负责创建对象,另一个必须负责更新存储的对象。
  • 嗨@AkshathMahajan,感谢您的评论!首先调用公司名称视图。通过对象,您是指模型中的字段吗?每个表单都调用模型中的不同字段,并且都保存创建的表单。在调用 post.save() 之前,我尝试使用“post.user = request.user”将两者联系在一起
  • 您应该查看 django 中的表单实例,这样您就可以在公司名称视图中创建对象,然后在下一个视图中更新该对象。通过对象,我的意思是数据库中的一行
  • 我添加了尝试保存到同一个实例,方法是过滤具有相同公司名称和最新时间​​戳的实例,然后在调用表单时添加该实例过滤器。视图正在工作,但仍未保存到同一实例。

标签: django django-forms


【解决方案1】:

首先,在您的def start(request) 函数中,您应该考虑将ID 添加到request.session 而不是公司名称。类似于

def start(request):
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = QuizTakerForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            form.instance.user=request.user
            form.save()
            request.session['obj_id'] = post.id

            # redirect to a new URL:
            return HttpResponseRedirect('industry/')

现在您可以使用该 id 来获取公司名称和对象。

在您的IndustryView(FormView) 中,如果您在使用表单实例时遇到问题,最好使用UpdateView 而不是FormView(请务必先导入UpdateView

class IndustryView(UpdateView):
    template_name = 'ImpactCheck/industry.html'
    model = QuizTakers
    fields = ['industry']
    success_url = '/1'
    def get_object(self):
        return QuizTakers.objects.get(pk=self.request.session.get('obj_id'))

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx['company_name'] = QuizTakers.objects.get(pk=self.request.session.get('obj_id'))
        return ctx

我们使用get_context_data 方法,因为您需要在模板中使用company_name。这个视图中的 get_object 方法告诉 django 要更新哪个对象。默认情况下,它从 url 中获取 pk(作为 url 参数)。但是由于我们将 id 存储在 session 中,我们需要显式定义这个函数。

另外,由于我们切换到UpdateView,您也不再需要QTIndustryForm

【讨论】:

  • 非常感谢您的详细回答!当您说“您不需要手动定义 form_valid 方法”时,保存部分应该在哪里?当我完全删除 form_valid 部分时,行业不会保存到数据库中。当我在 form_valid 部分添加回来时,它会保存。
  • 对不起,我实际上改变了很多我的答案。我尝试在本地机器上运行最后一个,但由于某种原因它似乎不起作用。这虽然有效
  • 如果对您有帮助,您会考虑接受我的回答吗?
猜你喜欢
  • 1970-01-01
  • 2014-04-11
  • 2021-12-27
  • 2021-04-13
  • 2020-11-21
  • 2018-03-05
  • 1970-01-01
  • 2020-04-01
  • 2014-09-12
相关资源
最近更新 更多