Search result fails with pagination - django

In my django project I'm using Django Endless Pagination for pagination and haystack + elasticsearch for searching. When I search a specific content the request method is POST and the result is correct, but when I try to paginate through the search result, next request is received as GET and the search result is lost and the whole content is iterated.
Here is my code:
views.py
#login_required(login_url="/")
#page_template('students/students_listing_block.html')
def students(request, template='students/students_listing.html', extra_context=None, *args, **kwargs):
sqs = SearchQuerySet().models(Student)
if request.POST:
searchcontent = request.POST.get('content', None)
if searchcontent:
sqs = sqs.filter(content=searchcontent)
students = sqs.order_by('-created_at')
context = {
'students': students,
}
if extra_context is not None:
context.update(extra_context)
return render_to_response(template, context,
context_instance=RequestContext(request))
and my template
{% load endless %}
{% lazy_paginate students %}
{% for student in students %}
// Do the displaying here
{% endfor %}
{% show_more %}

It is get request because the standard request method for search is GET. My recommendation is to change the request method for search into GET.
Or, if you want to keep using POST, you need to change the request method for every page link. This is a good library to change the hyperlink request method. https://github.com/rails/jquery-ujs
TEST

Related

Search functionality django

I've been following the tango with django book and I came across the search chapter using Bing's Search API. I tried to use it but it seems like Bing no longer offers those services. Now I want to make the search functionality local so that it could just search through my categories in the rango app but I don't know how to do this without the Bing search API. Anyone who could help me with a way around it if there is. Thanks in advance.
Here's an example to implement basic search in django:
1) templates/base.html
note: use GET method to get search input from form.
<form name="exampleform" method="GET" action="{% url 'search' %}">
2) views.py
def search(request):
try:
if 'q' in request.GET:# this will be GET now
querystring = request.GET.get('q')# passing in the query value to search view using the 'q' parameter
if len(querystring) == 0:
return redirect('index')
else:
pass
except:
pass
results = {}
if 'q' in request.GET:
querystring = request.GET.get('q')
if querystring is not None:
results = UserModel.objects.filter(
Q(email__icontains=querystring) |
Q(first_name__icontains=querystring) |
Q(last_name__icontains=querystring)).order_by('pk')# filter returns a list
context = {'results': results}
template = 'templates/search_result.html'
return render(request, template, context)
else:
return redirect('index')
context = {}
else:
return render(request, "templates/search_result.html")
2) urls.py
url(r'^search',views.search, name='search'),
3) templates/search_result.html
{% for each_object in results %} // results is list here so pick each element object using for loop
<a href="{% url 'user_detail' pk=each_object.pk %}">
<!--Upon successful search object image with hyperlink appears -->
<img src="{{each_object.image.url}}" alt="No Image"></a>
<p>{{each_object.email}}</p>
<p>{{each_object.first_name}}</p>
<p>{{each_object.last_name}}</p>
{% endfor %}
There are a few projects around to do search. Here's a non-exhaustive list: djangosearch, django-search (with a dash), django-sphinx.

Restrict access to Django template

I need to restrict access to a template in Django. This is the scenario:
A guest user uses a form
If the form is validated and fine send the user to the example.com/success/ url.
If the guest user tries to send that link example.com/success to a friend. The friend will see that page as a 404.
I have no clue how to achieve this. Any ideas?
Instead of going to a different URL (/success/), you could just show something different when the form was properly filled. For example, in your view:
def my_view(request, ...):
form = ...
show_success = False
if ... post method ...:
if form.is_valid():
... save etc. ...
show_success = True
return render(request, ..., {'show_success': show_success})
In your template:
{% if show_success %}
Success message here
{% else %}
Form here
{% endif %}

Different ways for sending request context with HttpResponseRedirect in django

I have a django app and implemented payment gateway functionality.
Now what i was trying is
After successful transation, need to do redirect user to another page that shows the response details so i am using HttpresponseRedirect to redirect the page, but i have the variable response in the view that contains reponse details, so i need to send this variable as the context to the redirecting url that renders template, so that i can use that response variable to display the results.
so for the above functionality, i got three methods
Sending the variable as the query parameter(which is not safe in this method because it is sensitive credit card transaction details)
Using session framework, which is not working in my case, the code is below
Django messaging framework(which is not so useful in this case)
views.py
def payment(request):
amount = 1
if request.method == 'POST':
form = CreditCardForm(request.POST)
if form.is_valid():
data = form.cleaned_data
...........
...........
response = stripe.payment_purchase(amount,data)
request.session['response'] = response
return HttpResponseRedirect(reverse('paygate:payment_success'))
else:
form = CreditCardForm(initial={'number':'4242424242424242'})
return render_to_response('payment/stripe_payment_form.html',{'form': form,
'response':response,},
context_instance=RequestContext(request))
payment_success url view
class PaymentSuccess(TemplateView):
template_name = 'payment/payment_success.html'
I tried to access response variable in the template, but displaying nothing
payment_success.html
{% extends "base.html" %}
{% block main_title %}Payment{% endblock %}
{% block title %}Success{% endblock %}
{% block content %}
<h1>Response Details</h1>
<p>Your status is <span>{{ request.session.response }}</span></p>
{% endblock %}
So can anyone please let me know the various different safe and secure ways to send context variables(in this case credit card payment details) to redirecting url using HttpResponseRedirect method
I think there is a 4. possible item in your list, that I suggest to use.
The safest and most pragmatic way of accomplish what you want is to have a successful view showing the actual results stored in your database.
The idea behind this is:
payment view is an action that a user performs on your database.
payment_success view is a way of telling the user that the action was performed successfully and with the the input the user desired.
Likewise, the best way of showing that the action is correct is to show its result on the database, i.e. what it is now stored on the database regarding that action.

django csrf_token in search result url

Have csrf in search result url. Don't know why is there and how to remove it. Search works nice. Here is URL
/search/?csrfmiddlewaretoken=675d1340034e094866d15a921407e3fc&q=testing
here is view:
def search(request):
query = request.GET.get('q', '')
rezult = []
if query:
qset1 = (
Q(title__icontains=query)
)
result = Product.objects.filter(qset1).distinct()
if result.count() == 1:
return HttpResponseRedirect(result[0].get_absolute_url())
return render_to_response('search/search.html',{'query': query, 'result': result, },context_instance=RequestContext(request))
Thanks
Remove {% csrf_token %} from your form in the template, you don't need it since you're making a GET request.
you added {% csrf_token %} in your form. if you dont need csrf remove this from your form and add csrf_exempt.
look at this sample of django:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
I would assume that you've added the {% csrf_token %} within one of the search form's input element. That would cause the token to be submitted along with the form.
Check your search form template.

Sphinx search on Django raise exception TypeError at /search/

I am trying out to build full-text searching by using sphinx search, postgresql & django based on this tutorial: http://pkarl.com/articles/guide-django-full-text-search-sphinx-and-django-sp/.
All setup done for sphinx & postgresql and it works but I got trouble when reach on Sample Django code part.
In django views & urlconf, I only changed the function of *search_results* into search and Story model with my own model. For URLConf, I only changed *search_results* into search just same like on views and nothing changed made on search template.
So when I try to search from my form in Django, I get exception:
TypeError at /search/
list() takes exactly 1 argument (0 given)
I also try to changed based on steyblind's comment by change the urlpattern & view definition like this:
(r'^search/(.*)?', search),
def search(request, query=''):
but still keep get TypeError exception.
Is there any mistake I am doing here? Thanks in advance.
Here's my snippets:
Urls.py
(r'^search/(.*)', search),
Views.py
def search(request, query):
try:
if(query == ''):
query = request.GET['query']
results = Flow.search.query(query)
context = { 'flows': list(results),'query': query, 'search_meta':results._sphinx }
except:
context = { 'flows': list() }
return render_to_response('search.html', context, context_instance=RequestContext(request))
search.html
{% extends "base.html" %}
{% block main %}
<div>
<form action="/search/" method="GET">
<input type="text" name="query"/>
<input type="submit">
</form>
{% if flows %}
<p>Your search for “<strong>{{ query }}</strong>” had <strong>{{ search_meta.total_found }}</strong> results.</p>
<p>search_meta object dump: {{ search_meta }}</p>
{% endif %}
<hr/>
{% for s in flows %}
<h3>{{ s.title }}</h3>
<p>(weight: {{ s.sphinx.weight }})</p>
<p>story.sphinx object dump: {{ s.sphinx }}</p>
{% empty %}
<p>YOU HAVEN'T SEARCHED YET.</p>
{% endfor %}
</div>
{% endblock %}
Correct me if I'm wrong, but Django-Sphinx seems to be an abandoned project. The last update to it was a year ago, with most updates being 3-5 years ago. Also, I cannot speak for Django then, but it can do now, out of the box, what you are trying to do with Sphinx.
What version of Django and Python are you using? The error you are getting is strange as list() can take no arguments. Try this in a python shell:
>> list()
[]
Regardless, I've made a few modifications to the code that could possibly help fix the issue. However, if there are no results, you are passing 'flows' as empty in this line:
context = { 'flows': list() }
If you look at the template, this really accomplishes nothing.
urls.py:
(r'^search/', search),
views.py:
def search(request):
query = request.GET.get('query')
if query:
results = Flow.search.query(query)
if results:
context = { 'flows': list(results),'query': query, 'search_meta':results._sphinx }
else:
context = { 'flows': list() }
return render_to_response('search.html', context, context_instance=RequestContext(request))
All that said, I'd highly suggest that since this project is so outdated that you use your own search. Or if you need more functionality, you could use a search app like Haystack which is updated frequently. Using the same urls.py as above, you could implement the below as an easy search that will return all results for a blank search, the actual filtered results for a query.
views.py:
def search(request):
query = request.GET.get('q')
results = Flow.objects.all()
if query:
results = results.query(query)
return render_to_response('search.html', {"flows": results,}, context_instance=RequestContext(request))