【问题标题】:django- why after redirecting, the form display "None"django-为什么重定向后,表单显示“无”
【发布时间】:2016-01-22 23:32:36
【问题描述】:

我有一个表单,输入信息后,它会根据信息过滤数据库并进行一些计算,最后将结果显示到重定向的 url。

我确实可以重定向到另一个 url 并成功显示结果。但问题在于它无法显示用户提交的任何数据,每个字段都不显示任何内容,并且结果不是基于经过过滤的查询集。比如说求和,它只是对数据库中的所有列求和,而不使用过滤结果。

我怀疑查询集没有将过滤结果传递给def get_context_data,因此get_context_data中的查询集不起作用。

如果你解决了我的疑问,真的非常感谢你。

(我根据建议合并2个类做了一个EDIT版本,希望有人能纠正这个EDIT版本,谢谢)

urls.py

url(r'^result_list/$',ResultView.as_view(),name='result'),
url(r'^input/$',InputFormView.as_view(),name='input'),

views.py

class InputFormView(request):
#class InputFormView(FormView):
    template_name = 'inputform.html'
    form_class = InputForm

    response = HttpResponse( 'result' )
    request_form_data = request.POST #you need to sanitize/clear this data
    response.set_cookie('form_data', request_form_data)

#redirect to result page with submitted form information

    def get_success_url(self):
        return ''.join(
        [
            reverse('result'),
            '?company=',self.request.POST.get('company'),  <--do I need to change "POST" into "USER"?
            '&region=',self.request.POST.get('region')
        ]
        )

#class ResultView(ListView):
class ResultView(request):
    context_object_name = 'result_list'
    template_name = 'result_list.html'
    model = Result

    def get_context_data(self, **kwargs):
        context = super(ResultView, self).get_context_data(**kwargs)
        context["sales"] = self.get_queryset().aggregate(Sum('sales'))
        context["company"] = self.request.POST.get("company")
        context["region"] = self.request.POST.get("region")

        return context

    def get_queryset(self):
        if self.request.method == 'POST': 
            form = InputForm(self.request.POST)
            if form.is_valid():
                company = form.cleaned_data['company']
                region = form.cleaned_data['region']

                queryset=Result.objects.filter(region=region)
                return queryset
        return Result.objects.all()

    if request.COOKIES.has_key('form_data'):
        value = request.COOKIES['form_data'] #this data also should be sanitized

html

<div class="basicinfo">         <!--Entry Form information submitted by user-->
    <table border="1" cellpadding="1">
    <tr>
        <td align="left">Company</td>
        <td>{{ company }}</td>
    </tr>
    <tr>
        <td align="left">Region</td>
        <td>{{ region }}</td>
    </tr>
  </table>
</div>     

<!--Showing the filtered result in database-->  
<td><table border="0" cellspacing="10" cellpadding="10">
<tr><b>Sales</b></tr>
<td bgcolor="#F0F0F0"> {{ sales.sales__sum }}</td>

</tr>
<tr><b>Employee</b></tr>
<tr>
<td bgcolor="#F0F0F0"> {{ employee.employee__sum }}</td>

</table>

EDIT - 结合 2 个类视图

import urllib

#@csrf_exempt

class ResultView(ListView):
    context_object_name = 'result_list'
    template_name = 'result_list.html'
    model = Result

    def get_queryset(self):
        form = InputForm(self.request.GET)
        if form.is_valid():
            company = form.cleaned_data['company']
            region = form.cleaned_data['region']         
            queryset=Result.objects.filter(region=region)
            return queryset
        return Result.objects.all()

    def get_success_url(self):
        params = {
            'company': self.request.POST.get('company'),
            'region': self.request.POST.get('region')
        }
        return ''.join([reverse('result'), '?', urllib.urlencode(params.items())])

    def get_context_data(self,**kwargs):
            context = super(ResultView, self).get_context_data(**kwargs)
            context["sales"] = self.get_queryset().aggregate(Sum('sales'))         
            context["company"] = self.request.GET.get("company")
            context["region"] = self.request.GET.get("region")       
            return context

**EDIT-urls.py **

url(r'^result_list/$',ResultView.as_view(),name='result'),----for the result page
url(r'^input/$',result.views.get_success_url,name='input') -----for the form, I am not sure if this line correct or not?

【问题讨论】:

  • 究竟是什么,显示的是 None?
  • 我相信这是正在发生的事情 - 您假设数据在 POST 上下文中,但是当您重定向到另一个页面时,它不再是 POST - 因此您是在上下文中丢失数据。解决此问题的一种方法是将 POST 参数作为 kwargs 发送到重定向视图中。
  • hi@Daniel Roseman,在重定向页面中,“company”和“region”的值显示为“None”
  • 嗨@karthikr,你能把你的建议放在答案中吗?顺便说一下,在重定向页面中,它可以显示销售结果,只是不能显示表单数据,如公司名称和地区名称。
  • 您能确认您的重定向网址正确吗?即,您会被重定向到 /result/?company=cc&amp;region=abr?

标签: python django forms


【解决方案1】:

如果您将 get_queryset 方法更改为:

def get_queryset(self):
    # You are sending GET params here, not POST
    form = InputForm(self.request.GET)
    if form.is_valid():
        company = form.cleaned_data['company']
        region = form.cleaned_data['region']

        queryset=Result.objects.filter(region=region)
        return queryset
    return Result.objects.all()

和您的get_context_data 方法:

def get_context_data(self, **kwargs):
    context = super(ResultView, self).get_context_data(**kwargs)
    context["sales"] = self.get_queryset().aggregate(Sum('sales'))
    # Your variables are in GET, not POST
    context["company"] = self.request.GET.get("company")
    context["region"] = self.request.GET.get("region")
    return context

也就是说,您的代码可以进行一些重构。你真的需要接受 POST 请求的FormView 吗?您可以改为使用通过 GET 直接提交到结果视图的表单。

使用您当前的方法,您实际上是在处理表单两次 - 在每个视图中处理一次。

编辑:另外,您生成重定向网址的方式也不安全。你应该这样:

import urllib
def get_success_url(self):
    params = {
        'company': self.request.POST.get('company'),
        'region': self.request.POST.get('region')
    }

    return ''.join([reverse('result'), '?', urllib.urlencode(params.items())])

【讨论】:

  • 嗨@solarissmoke,关于“return ''.join([reverse('result'), '?', urllib.urlencode(params)])”有一些错误。我更新了帖子中的回溯,谢谢。
  • 我已经编辑了答案 - 试试urllib.urlencode(params.items())。
  • 嗨@solarissmoke,因为我有2个分别用于表单和结果的url,所以我也制作了2个单独的类视图。根据您的建议,您的意思是我删除了 InputFormView 类,将 def get_success_url 部分移动到 ResultView(request),对吗?如有错误请指正,谢谢。
  • 你确定你创建的 params 变量与我提供的例子完全一样吗?
  • hi@solarissmoke ,我已经更新了 EDIT views.py 和 url,因为您建议原始代码重复处理表单。你能看看编辑吗,因为我不太确定我是否像那样改变,表单的url应该指向哪个视图。提前致谢
【解决方案2】:

如果您发出 POST 请求,然后您正在重定向用户,则下一个请求将有空 POST(因为现在它是另一个请求)。因此,这并不是一个令人惊讶的行为。 如果你想在会话之间保存这些数据,你可以把它保存在用户会话中,例如。

您可以通过添加以下代码来修改您的一些视图(我相信这是重定向):

设置 cookie:

def your_view_which_makes_redirect(request):
  #.. here is your code
  response = HttpResponse( 'blah' )
  request_form_data = request.POST #you need to sanitize/clear this data
  response.set_cookie('form_data', request_form_data)

获取cookie:

def your_view_which_renders_page_after_rediret(request):
  if request.COOKIES.has_key('form_data'):
    value = request.COOKIES['form_data'] #this data also should be sanitized

1) 您还可以将此 cookie 的名称移动到设置中,因为现在它们是硬编码的,现在这是非常好的做法。类似 settings.SAVED_FORM_NAME_COOIKE_TOKEN 2) 你还必须清理 request.POST 和 request.COOKIES 中的数据,因为用户可以在那里放置一些恶意数据(SQL 注入等)。

【讨论】:

  • 谢谢~我不确定我是否理解正确,因此我按照您的建议更新了views.py,它返回错误,例如“名称请求未定义”,请您帮忙看看或直接编辑?
  • @Elena 您能否从您执行重定向的视图中显示代码?
  • 嗨@Paul,它已经在“def get_success_url(self):...”块中的views.py中了
猜你喜欢
  • 2016-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-31
  • 2020-07-14
  • 2011-12-19
  • 2016-06-03
  • 2016-02-12
相关资源
最近更新 更多