基于 Django 类的视图加载另一个带有数据的表单

Posted

技术标签:

【中文标题】基于 Django 类的视图加载另一个带有数据的表单【英文标题】:Django Class based view loading another form with data 【发布时间】:2021-01-25 23:54:38 【问题描述】:

我不确定我是否正确使用了这个基于类的视图。我想做的事情我认为很简单。基本上是一个基于模型的表单,我只使用来自以下的“用户”字段:

class OnSiteLog(models.Model):
    objects = models.Manager()
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    checkIn = models.DateTimeField('checkin_date', null=True, blank=True)    
    checkOut = models.DateTimeField('checkout_date', null=True, blank=True)    
    notes = models.CharField(null=True, blank=True,max_length = 200)
    location = models.CharField(null=True, blank=True, max_length=200)
    autoCheckin = models.BooleanField(null=True, blank=True, default=False)


class QueryUser(LoginRequiredMixin, FormView):
    model = OnSiteLog
    form_class = QueryForm
    template_name = 'log/query.html'
    success_url = '/'
    def post(self, request, *args, **kwargs):

        theRecord = OnSiteLog.objects.filter(user_id=24)
        print(theRecord[0].user)
        super(QueryUser, self).post(request, *args, **kwargs)
        return render(request, 'log/query.html', 'log':theRecord)
    

从那里开始:模板非常简单,形式清晰:

% block content %
   <div class="breadcrumb-area">


        <!-- Background Curve -->
        <div class="breadcrumb-bg-curve">
            <img src="% static '/img/core-img/curve-5.png' %" >
        </div>
    </div>
<div class="container">
    <h2> Query for User </h2>
    <div class="row">
      <div class="col-sm">
            % crispy form %
      </div>
    </div>

    <div class="row">
       Logs
      <div class="col-sm">
      <table class="table">
      <tr>
        <th>User</th>
        <th>Check In</th>
        <th>Check Out</th>
        <th>Location</th>
        <th>Notes</th>
       
        </tr>
        % for ins in log %
          <tr>
            <td> ins.user </td>
            <td> ins.checkIn </td>
            <td> ins.checkOut </td>
            <td> ins.location </td>
            <td> ins.notes </td>
            % if request.user.is_superuser %
              <td> <a href="% url 'log_detail' ins.id %"><button type="button" class="btn btn-primary">Edit Entry</button></td>
            % endif %

            <!-- td><a href=" ins.id "><button type="button" class="btn btn-primary">Edit Insurance</button></a></td>
            <td><button type="button" class="btn btn-danger">Delete Insurance</button></td> -->
          </tr>
        % endfor %
      </table>
           
      </div>
    </div>


</div>

% endblock %

我想要的是,在他们使用选定的名称提交后重新加载表单,并且重新加载的表单具有来自该用户的 OnSiteLog 的所有登录信息(基本上选择所有用户 = '...' )

虽然我不确定如何从 def post 方法中的请求中获取正确的变量,但我在那里找到了一个好方法,然后作为测试,我输入了 id 24。所以我不确定如何获得它变量输出?

其次,脆皮表格(我认为)一直给我这个错误:

VariableDoesNotExist at /query_user/
Failed lookup for key [form] in ['True': True, 'False': False, 'None': None, , , 'log': <QuerySet [<OnSiteLog: OnSiteLog object (100)>, <OnSiteLog: OnSiteLog object (101)>, <OnSiteLog: OnSiteLog object (107)>, <OnSiteLog: OnSiteLog object (109)>, <OnSiteLog: OnSiteLog object (124)>, <OnSiteLog: OnSiteLog object (148)>, <OnSiteLog: OnSiteLog object (152)>, <OnSiteLog: OnSiteLog object (156)>, <OnSiteLog: OnSiteLog object (158)>, <OnSiteLog: OnSiteLog object (163)>, <OnSiteLog: OnSiteLog object (168)>, <OnSiteLog: OnSiteLog object (172)>, <OnSiteLog: OnSiteLog object (178)>, <OnSiteLog: OnSiteLog object (192)>, <OnSiteLog: OnSiteLog object (193)>, <OnSiteLog: OnSiteLog object (550)>, <OnSiteLog: OnSiteLog object (552)>, <OnSiteLog: OnSiteLog object (556)>, <OnSiteLog: OnSiteLog object (559)>, <OnSiteLog: OnSiteLog object (562)>, '...(remaining elements truncated)...']>]

因此,除了不太确定如何在 def post 中获取正确的变量之外,我也不确定为什么表单的重新呈现会吓坏。

【问题讨论】:

【参考方案1】:

您可以尝试覆盖 FormView 的这些方法,并使用适当的上下文再次将用户带到视图以填充表单。

# get the id of the log that was just created

    def form_valid(self, form, *args, **kwargs):
        user = form.cleaned_data.get('user')
        self.log_id = User.objects.get(username=user).select_related('log').last().id
        return super().form_valid(form, *args, **kwargs) 

# redirect successful form to same view

    def get_success_url(self):
        return reverse('this-view', kwargs='id': self.log_id)

# render populated form in context

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        try:
            context['form'] = self.form_class(instance=OnSiteLog.objects.get(id=self.kwargs['id']))
        except ObjectDoesNotExist:
            context['form'] = self.form_class()
        finally: 
            return context

然后您应该能够使用您刚刚创建的 OnSiteLog 实例填充您的表单。但是,有了这个,您必须在 url Django optional url parameters 中有可选的 url 参数。

【讨论】:

我将在使用计算机时尝试此操作,尽管 query.html 文件有一个 crispy_form 只是 'user' ,因此没有其他表单可以作为想法填充是我试图通过模板中的 for 循环处理的用户的所有日志的列表。我认为这可能是一个问题,也许类视图期望所有数据都是一种形式? (在这种情况下,我的表单有一个字段)并且不允许“堆叠”或将任何额外数据添加回模板? 我实际上是通过转到第二个 html 文件来准备的硬编码 ID id 是金色的 是的,这听起来不错 - 只是另一个列出用户日志的 ListView。从您的表单中,重定向到该新视图,但在 url 中添加新用户的 id 或用户名:def get_success_url(self): return reverse('new-view', kwargs='id': user.id)。然后您可以在下一个contextget_context_data 中使用kwargs['id'],具体取决于这是CBV 还是FBV。 logs = OnSiteLog.objects.filter(user__id=kwargs['id']) 天哪,我糟透了 :D 我以一种 hacky 的方式做到了。我不敢相信这一点给我带来了麻烦,我显然从来没有过多地混合 CBV 或 FBV。使用教程和什么不是很好,但并不总是显示关于这些东西的具体细节......我编辑了我原来的问题,但仍然不确定如何获得返回的用户 ID,但按照你所说的,我不知道完全在 CBV 中使用 def 帖子.... 实际上在这里给出了一个很好的答案,即使我的 hack(是的,total hack)朝着不同的方向发展。这只是一个用于办公室的小型 covid 跟踪应用程序,因此它不是一些强大的企业级应用程序,但您的提示确实有所帮助。我在我的编辑中得到了它的代码,但是对于 .filter(user_id=request.POST.get('user')) 工作得很好(分页不能这样工作,但其余工作正常)。稍后我可能会回来完善它。

以上是关于基于 Django 类的视图加载另一个带有数据的表单的主要内容,如果未能解决你的问题,请参考以下文章

带有 url 问题的基于 Django 类的视图

Django中基于类的视图上带有参数的函数装饰器

带有来自模型的自定义验证消息的 Django 1.5 基于类的视图

如何根据 Django 中当前基于类的通用视图模型向模板加载器添加路径

Django 在基于类的视图中处理多个表单

基于 Django 类的视图和通用视图详细信息使用