如何将数据从一个视图传递到另一个视图 [英] How to pass data from one view to the next

查看:61
本文介绍了如何将数据从一个视图传递到另一个视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

总结:我正在尝试建立一个工作站点.在 index.html 上,用户在表单中输入邮政编码以查看该邮政编码中的工作,此表单由 job_query 视图处理.这会将他们带到另一个页面(search.html),在那里起初您只能看到该特定邮政编码中的工作,但我正在尝试添加一个过滤器,让用户可以看到 X 英里内的工作.如何将在 index.html 上的 from 中输入的邮政编码值传递到下一页?

index.html:

找工作

<!--搜索栏--><form method = "GET" action = "{% url 'search' %}" ><div id = "form_grid"><input name="query" type="text" placeholder="邮政编码"><button type="submit">搜索</button>

</表单>

search.html:

 

views.py:

def job_query(request):如果 request.method == "GET":查询 = request.GET.get('查询')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对于jobs_matching_query 中的工作:number_of_results = number_of_results + 1返回渲染(请求,'core/search.html',{'query':查询,'jobs_matching_query':jobs_matching_query,'number_of_results':number_of_results})def内_英里(请求):英里 = request.GET['miles']#如何使用输入的邮政编码值?

urls.py:

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

我想我包含了所有相关信息,但如果我遗漏了什么,请告诉我,在此先感谢您的帮助.

解决方案

您可以编码在 URL 中输入的 ZIP,通过 cookie 传递它,将其存储在会话变量中,或使用 (hidden) 强制浏览器通过 GET 和 POST 请求传递它的输入元素.

在 URL 中编码

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

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

所以现在不能再获取your.domain.com/within_miles,而是your.domain.com/within_miles/12345.它使用户很容易操纵"URL,但由于用户可能可以提供任何 ZIP,因此保护它可能没有太大好处.

在表单中,生成的 URL 是这样的:

{% url 'within_miles' zip=query %}

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

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

使用隐藏表单元素

我们还可以对隐藏表单元素中的内容进行编码,例如这里我们可以在表单中创建一个元素:

<form id="within_miles_form" method = "GET" action = "{% url 'within_miles' %}" ><input class="search_bar" name="miles" type="text" placeholder="邮政编码 X 英里内"><input type="hidden" name="zip_code" value="{{ query }}"><button type="submit">过滤器</button>

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

使用会话变量和/或cookies

您还可以决定使用会话变量(存储在服务器端,因此安全")或 cookie(存储在客户端,可以被篡改).然而,一个潜在的问题是这些存储在浏览器中,并且对一个标签页中的 cookie 进行了更改,因此可能会影响另一个标签页.此外,cookie 和会话将消亡".在请求之后,因此可能会在以后的视图中造成很多麻烦.

您可以在视图中设置会话变量:

request.session['zip_code'] = query

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

设置和获取会话变量

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

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

设置和获取cookies

我们可以对 cookie 使用类似的方法.然而,浏览器可能会拒绝 cookie 或操纵它们,因此没有太多保证不会篡改数据(实际上没有).您可以通过以下方式设置 cookie:

response = render(request, 'core/search.html', {'query': query ,'jobs_matching_query': jobs_matching_query, 'number_of_results': number_of_results})response.set_cookie('zip_code', 查询)返回响应

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

我们可以 - 例如在稍后的视图中 - 检索内容:

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

改进job_query 视图

job_query 视图看起来有点奇怪:它使用了各种不常见"的代码实践.例如,元素的数量是通过迭代来计算的,而不是取len(..).这看起来也基本上像一个 ListView [Django-doc] 并且我们可以使用 Q-objects [Django-doc].列表视图看起来像:

def JobListView(ListView):模型 = 工作context_object_name = 'jobs_matching_query'模板名称 = '核心/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'],查询 = self.request.GET.get('查询'))返回 kwargs

在视图中,您不传递JobListView,而是传递JobListView.as_view() 结果作为参考.

Summary: I am trying to build a job site. On index.html the user enters a zip code into a form to see jobs in that zip code, this form is handled with the job_query view. This brings them to another page(search.html) where at first you only see jobs in that specific zip code but I am trying to add a filter that lets the user see jobs within X miles. How can I pass the zip code value entered in the from on index.html to the next page?

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"),

I think I included all the relevant info but if I am missing something please let me know, thanks in advance for any help.

解决方案

You can encode the entered ZIP in a URL, pass it through cookies, store it in the session variables, or use a (hidden) input element that forces the browser to pass it through a GET and POST request.

Encode it in the URL

In that case we can rewrite the URL to:

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

So now one can no longer fetch your.domain.com/within_miles, but your.domain.com/within_miles/12345. It makes it easy for a user to "manipulate" the URL, but since the user can probably provide any ZIP, there is probably not much gain to protect that.

In the form, the URL that is generated is thus:

{% url 'within_miles' zip=query %}

(you can use another variable that is more strictly a ZIP code)

You should thus ensure that query is here a five digit string (or otherwise change the expression in the url(..) part such that it allows all possible queries).

Using hidden form elements

We can also encode content in hidden form elements, for example here we can create an element in the 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">
    <input type="hidden" name="zip_code" value="{{ query }}">
    <button type="submit">Filter</button>
</form>

We thus add a form element, fill it with some data, and let the browser submit the value again to the next view. Note that again it is the browser that does this, so a user can inspect the DOM (most browsers allow that, and subsequently edit it).

Using session variables and/or cookies

You can also decide to use session variables (stored at server side, so "secure") or cookies (stored at client side, can be tampered with). A potential problem however is that these are stored in the browser, and changes to the cookies in one tab page, thus can have effect in the other tab page. Furthermore cookies and sessions will "die" after the request, and thus can create a lot of trouble in future views.

You can set a session variable in the view with:

request.session['zip_code'] = query

This will thus store an entry at the server side such that another call can retrieve that value again. The request.session acts like a dictionary that keeps some sort of state per session.

setting and obtaining session variables

In another view, you can thus query the request.session, like:

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

setting and obtaining cookies

We can use a similar approach with cookies. A browser however might reject cookies, or manipulate them, so there are not that much guarantees that there is no tampering with the data (in fact there are none). You can set a cookie with:

response = render(request, 'core/search.html', {'query': query ,'jobs_matching_query': jobs_matching_query, 'number_of_results': number_of_results})
response.set_cookie('zip_code', query)
return response

Before we thus return the result of render(..), we call .set_cookie(..) on the result.

We can - for example in a later view - retrieve the content with:

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

Improving the job_query view

The job_query view however looks a bit strange: it uses all kinds of "uncommon" code practices. For example the number of elements is calculated by iterating over it, instead of taking the len(..). This also looks basically like a ListView [Django-doc] and we can make the query more elengant by using Q-objects [Django-doc]. The listview then looks like:

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

In the view, you then not pass the JobListView, but JobListView.as_view() result as a reference.

这篇关于如何将数据从一个视图传递到另一个视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆