如何将数据从一个视图传递到下一个视图

时间:2018-09-16 20:28:50

标签: django django-forms django-views

摘要:我正在尝试建立一个工作现场。用户在index.html上将邮政编码输入表单,以查看该邮政编码中的作业,该表单由job_query视图处理。这将它们带到另一个页面(search.html),首先您只看到该特定邮政编码中的工作,但是我试图添加一个过滤器,使用户可以查看X英里内的工作。如何将在index.html上的from中输入的邮政编码值传递给下一页?

index.html:

<h2>Find a Job</h2>
<!--Search Bar-->
<form method = "GET" action = "{% url 'search' %}" >
    <div id = "form_grid">
        <input name="query"  type="text" placeholder="Zip Code">
        <button type="submit">Search</button>
    </div>
</form>

search.html:

    <form method = "GET" action = "{% url 'search' %}" >
                    <input  class="search_bar"  name="query"  type="text" placeholder="Zip Code">
                    <button  class="search_btn btn btn-outline-success  " type="submit">Find Jobs</button>
    </form>

   <form id="within_miles_form" method = "GET" action = "{% url 'within_miles' %}" >
                <input  class="search_bar"  name="miles"  type="text" placeholder="Within X miles of Zip Code">
                <button type="submit">Filter</button>
    </form>

<!--code to display jobs-->

views.py:

def job_query(request):
    if request.method == "GET":
        query = request.GET.get('query')
        jobs_matching_query = Job.objects.filter(zip_code__iexact = query) | Job.objects.filter(city__iexact=query) | Job.objects.filter(state__iexact=query)
        number_of_results = 0
        for job in jobs_matching_query:
            number_of_results = number_of_results + 1
        return render(request, 'core/search.html', {'query': query ,'jobs_matching_query': jobs_matching_query, 'number_of_results': number_of_results})
def within_miles(request):
    miles = request.GET['miles']
    #how can i use value of the zip code entered?

urls.py:

url(r'^search$', views.job_query, name="search"),
url(r'within_miles', views.within_miles, name="within_miles"),

我想我已经包括了所有相关信息,但是如果我缺少什么,请让我知道,在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

您可以在网址中编码输入的ZIP,通过Cookie传递,将其存储在会话变量中,或使用(隐藏的)输入元素强制浏览器通过GET传递和POST请求。

将其编码为URL

在这种情况下,我们可以将URL重写为:

url(r'^within_miles/(?P<zip>[0-9]{5})/$', views.within_miles, name="within_miles"),

因此,现在不再可以获取your.domain.com/within_miles,而只能获取your.domain.com/within_miles/12345。这使用户可以轻松地“操纵” URL,但是由于用户可能可以提供任何ZIP,因此保护该URL可能没有太多好处。

因此,在表单中,生成的URL是:

{% url 'within_miles' zip=query %}

(您可以使用另一个更严格的邮政编码变量)

因此,您应该确保query是一个五位数的字符串(或者更改url(..)部分中的表达式,以便允许所有可能的查询)。

使用隐藏表单元素

我们还可以使用 hidden 形式的元素对内容进行编码,例如,在这里我们可以创建以下形式的元素:

<form id="within_miles_form" method = "GET" action = "{% url 'within_miles' %}" >
    <input  class="search_bar"  name="miles"  type="text" placeholder="Within X miles of Zip Code">
    <input type="hidden" name="zip_code" value="{{ query }}">
    <button type="submit">Filter</button>
</form>

因此,我们添加了一个form元素,用一些数据填充它,然后让浏览器再次将值提交给下一个视图。请注意,再次由浏览器执行此操作,因此用户可以检查DOM(大多数浏览器允许这样做,然后对其进行编辑)。

使用会话变量和/或 cookies

您还可以决定使用会话变量(存储在服务器端,因此是“安全的”)或cookie(存储在客户端,可以被篡改)。但是,潜在的问题是这些存储在浏览器中,并且更改了一个选项卡页面中的cookie,因此可能在另一选项卡页面中起作用。此外,cookie和会话将在请求后“消失”,从而在以后的视图中造成很多麻烦。

您可以使用以下方法在视图中设置会话变量:

request.session['zip_code'] = query

因此,这将在服务器端存储一个条目,以便另一个调用可以再次检索该值。 request.session就像一个字典,在每个会话中保持某种状态。

设置和获取会话变量

在另一个视图中,您可以查询request.session,例如:

zip_code = request.session.get('zip_code')

设置和获取cookie

我们可以对Cookie使用类似的方法。但是,浏览器可能会拒绝Cookie或对其进行操作,因此并不能保证没有篡改数据(实际上没有篡改数据)。您可以使用以下方法设置Cookie:

响应=渲染(请求,“ core / search.html”,{“ query”:query,“ jobs_matching_query”:jobs_matching_query,“ number_of_results”:number_of_results}) response.set_cookie(“邮政编码”,查询) 返回响应

在我们返回render(..)的结果之前,我们先对结果调用.set_cookie(..)

我们可以-例如在以后的视图中-通过以下方式检索内容:

zip_code = request.COOKIES.get('zip_code')

改善job_query视图

然而,job_query视图看起来有些奇怪:它使用了各种“不常见”的代码实践。例如,元素数量是通过对其进行 iteration 而不是使用len(..)来计算的。这基本上看起来像是ListView [Django-doc],并且我们可以使用Q-objects [Django-doc]使查询更加复杂。列表视图如下:

def JobListView(ListView):
    model = Job
    context_object_name = 'jobs_matching_query'
    template_name = 'core/search.html'

    def get_context_data(self, **kwargs):
        kwargs = super(JobListView, self).get_context_data(**kwargs)
        kwargs.update(
            number_of_results=len(kwargs['object_list'],
            query = self.request.GET.get('query')
        )
        return kwargs

然后,在视图中,您不会通过JobListView,而是将JobListView.as_view()的结果作为参考。