I would usually do this in ajax I think.
But if for example I have a button and a search input box that will have a query value, how can I pass the search value (and possibly multiple values/parameters that is not obtained through a form field) to Django views on button click to the url?
HTML
<div>
<input id="search" name="search" type="text" class="query-search" placeholder="Search...">
<a class="btn btn-primary btn-lg btn-space col-sm-3" href="{% url 'routes_view' %}">View Routes</a>
</div>
Views
def view_detail(request):
...
<How to get values from HTML without using ajax? Or its the only way?>
URLs
url(r'^view/', views.view_detail, name='view_detail')
Understanding from the previous answer, if you do not want the search values to be sent as URL parameters, you can send them via an AJAX POST call and handle that in the view, like this:
<div>
<input id="search" name="search" type="text" class="query-search" placeholder="Search...">
<input onclick="setGetParameter()" type="button" class="btn btn-primary" value = "View Details"/>
</div>
<script>
function setGetParameter(){
var search_word = $("#search").val();
$.ajax({
type: "POST",
url: {% url 'view_detail' %},
data: search_word,
success: function(result){
alert("Success");
}
});
}
</script>
Your view should look something like this.
def search_view(request):
if request.method == "POST":
search_word = request.POST['data']
URL configurations will remain the way other answers describe them.
You can create a HTML form and can submit the form using post method if you do not want to pass values in url.
<div>
<form action="{% url 'view_detail' %}" method="post">
{% csrf_token %}
<input id="search" name="search" type="text" class="query-search"
placeholder="Search...">
<input class="btn btn-primary" type="submit" value="submit">
</form>
</div>
And then in your view you can fetch the data as request.POST.get('search'):
def view_detail(request):
searchWord = request.POST.get('search','')
return HttpResponse(searchWord)
In the same way you can pass multiple parameters.
You can make a button works like a link in your templates, and add the js function on the onclick event, then get the search input value and add the search parameter to the url window.location.href:
<div>
<input id="search" name="search" type="text" class="query-search" placeholder="Search...">
<input onclick="setGetParameter()" type="button" class="btn btn-primary" value = "View Details"/>
</div>
<script>
function setGetParameter(){
searchWord = document.getElementById('search').value;
window.location.href = "{% url 'view_detail' %}" + "?search="+searchWord;
}
</script>
In the views, you can use request.GET.get('search') to get the parameters (search content) you input from the templates, like this:
def view_detail(request):
searchWord = request.GET.get('search')
return HttpResponse(searchWord)
BTW, the urlpatterns is look like this:
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^view$', views.view_detail, name='view_detail'),
]
Related
I am trying to create a function to search for objects in base.html from the database using a keyword and printing the results in listing.html
base.html
<form method="post" action="{% url 'listing'}" name="searchform">
{% csrf_token %}
<div class="custom-form">
<label>Keywords </label>
<input type="text" placeholder="Property Keywords" name="search_keyword" value=""/>
<label >Categories</label>
<select data-placeholder="Categories" name = "home_type" class="chosen-select on-radius no-search-select" >
<option>All Categories</option>
<option>Single-family</option>
<option>Semi-detached</option>
<option>Apartment</option>
<option>Townhomes</option>
<option>Multi-family</option>
<option>Mobile/Manufactured</option>
<option>Condo</option>
</select>
<label style="margin-top:10px;" >Price Range</label>
<div class="price-rage-item fl-wrap">
<input type="text" class="price-range" data-min="10000" data-max="100000000000" name="price-range1" data-step="1" value="1" data-prefix="$₦">
</div>
<button onclick="location.href='listing'" type="button" class="btn float-btn color-bg"><i class="fal fa-search"></i> Search</button>
</div>
</form>
views.py
def listing(request):
global search_keyword
p = Paginator(Property.objects.order_by('-listed_on'), 2)
page = request.GET.get('page')
propertys = p.get_page(page)
nums = "p" * propertys.paginator.num_pages
if request.method == 'POST' and 'searchform' in request.POST :
search_keyword = request.POST['search_keyword']
propertys = Property.objects.filter(name__contains=search_keyword)
return render(request, 'listing.html',{'nums':nums, 'search_keyword':search_keyword, 'propertys':propertys})
return render(request, 'listing.html',{'nums':nums,'propertys':propertys})
Your syntax of url[django-doc] tag is wrong, it must be {% url 'listing' %} not {% url 'listing'}, you forget to add % at the end which is not the syntax of django template language.
Try this:
Template file:
<form method="POST" action="{% url 'listing' %}" name="searchform">
You can also make use of __icontains for case-insensitive.
i want to display my django search result on a new html page instead of the page where the search bar is. i have tried manipulating my form tag and it still does'nt redirect to the page when i search, rather it stays on the same page.
index.html
<form action="{% url 'elements:all-elements' %}" method="get">
<input type="text" class="form-control" name="q" value="{{ request.GET.q }}" type="text" placeholder="Search Free Web Elements and Resources">
<button type="submit" class="btn bt-round" ><b><i class="bi bi-search"></i></b></button>
</form>
views.py - this is the view handling the seach, i dont know if anything would be appended there
# Search Function
query = request.GET.get("q")
if query:
vectors = vectors.filter(
Q(title__icontains=query)).distinct()
You can render new template for your search results.
def search(request):
query = request.GET.get("q")
vectors = Model.objects.all()
if query:
vectors = vectors.filter(
Q(title__icontains=query)).distinct()
context = {"vectors":vectors}
return render(request, "template", context)
This is a HTML template that displays all of the proposals in a database (passed through views.py as a list in the dictionary parameter). I then use a jinja for-loop to go through all the proposals in the database and display their attributes.
How can I Post-request the {{ proposal.id }} back to my python code when the "Learn more" button is clicked? I need this to allow me to display the corresponding values in my other html template.
Sorry if this is a basic question, i'm a high school student and extremely new to django! Thanks alot in advance!
{% block body %}
{% for proposal in proposals %}
<div class="jumbotron">
<h2> Proposal : {{ proposal.title }} </h2>
<h4> Status : {{ proposal.status }} </h4>
<h4> Out of --- Votes: </h4>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: {{ proposal.votes_for }}%">
<span class="sr-only">35% Complete (success)</span>
{{ proposal.votes_for }}% For
</div>
<div class="progress-bar progress-bar-danger" style="width: {{ proposal.votes_against }}%">
<span class="sr-only">10% Complete (danger)</span>
{{ proposal.votes_against }}% Against
</div>
</div>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
If you just want to go to the Proposal details you should definitely look to a class-based DetailView.
You can make it with AJAX request or you can make it with form. For the both of types you should have a View to catch it.
HTML Form:
In your template you should have:
<form id="formId" method="post" action="{% url 'catch-proposal' %}">
{% csrf_token %}
<input type="hidden" name="proposal_id" value="{{ proposal.id }}"/>
<p><button type="submit" class="btn btn-primary btn-lg">Learn more</a></p>
<!-- <input type="submit" class="btn btn-primary btn-lg" value="Learn more"/> -->
</form>
It will go to your View from urls.py:
url(r'^post/for/proposal/$', catch_proposal, name='catch-proposal'),
# if your view class-based
# url(r'^post/for/proposal/$', CatchProposal.as_view(), name='catch-proposal')
Then in your view you will catch POST data:
def catch_proposal(request):
if request.method == "POST":
print(request.POST) # have a look for your post params
return reverse_lazy('index') # your response, you can make it on your own
AJAX:
Check it! AJAX and Django
Page uses AJAX without any HTML form
A page makes a POST request via AJAX, and the page does not have an HTML form with a csrf_token that would cause the required CSRF cookie to be sent.
Solution: use ensure_csrf_cookie() on the view that sends the page.
In your scripts define:
function sendPost(proposalId) {
$.ajax({
url: '{% url 'catch-proposal' %}', // or just /ajax/catch/proposal/
method : "POST",
data: {
// your data to send key => val
'id': proposalId
},
dataType: 'json', // it can be xml, json, script, html
success: function (result) {
// Do something if your request was successful (code=200)
// All response data stored in result
console.log(result)
},
error : function(xhr,errmsg,err) {
// Error case
console.log(xhr.status + ": " + xhr.responseText);
}
});
}
For your Learn More button:
<p><button class="btn btn-primary btn-lg" role="button" onclick="sendPost({{ proposal.id }})">Learn more</button></p>
And you will catch it in your View:
#ensure_csrf_cookie # Since you sending POST request without form tag
def catch_proposal(request):
response_data = {} # your response
if request.method == 'POST':
# your post request
if 'id' not in request.POST: # check the param from POST
# Provide error message
response_data['error_message'] = "Can't find ID in POST params..."
else:
# Do whatever
proposal_id = int(request.POST.get('id'))
try:
proposal = Proposal.objects.get(id=transport_id)
response_data['success'] = True
except Proposal.DoesNotExist:
response_data['success'] = False
return JsonResponse(response_data)
else:
response_data = {
'error_message': 'Something is going very strange and wrong...'
}
return JsonResponse(response_data)
Adding created View to urls.py:
from .views import catch_proposal # or yourapp.views
....
url(r'^ajax/catch/proposal/$', catch_proposal, name='catch_proposal'),
....
I currently have a working search form in my project that passes through form data to the GET request. Pretty standard.
What I'm wanting to do is search as data is entered into the search form, so that results will display in real time with search data. This is much like what Google does with the instant desktop results. Is this something that's possible with Django?
Below is my current (simple) search
#views.py
def ProductView(request):
title = 'Products'
all_products = Product.objects.all().order_by("product_Name")
query = request.GET.get("q")
if query:
products = all_products.filter(
Q(product_Name__contains=query) |
Q(manufacturer__contains=query)
).distinct()
return render(request, 'mycollection/details.html', { 'all_products' : products })
-
<!-- HTML -->
<!-- SEARCH BAR -->
<form class="navbar-form navbar-left" role="search" method="get" action="{% url 'mycollection:products' %}">
<div class="form-group">
<input type="text" class="form-control" name="q" value="{{ request.GET.q }}">
</div>
<button type="submit" class="btn btn-default">Search</button>
</form>
you can save the request.data in to session and if any data is associated with session search data you can put in to value of search box.
request.session['search'] = request.GET.get('q','')
templete :
{% if request.session.search %} {{request.session.search}} {% endif %}
I'm diving into Flask for the first time and I'm having some trouble getting something work.
I currently have a template for when my tab values is empty, it contains a form that when submitted should call a specific function using the parameters of the form and return another template. Each call of the form should in, fact call the index.html template with different values.
Relevant parts of code are as follows:
main.py
#app.route('/', methods=['POST','GET'])
def main():
global maxDepth, numberOfRelated
if not values:
return render_template('initial.html')
if request.method=='POST':
url = request.form['url']
maxDepth = request.form['depth']
numberOfRelated = request.form['numberOfRelated']
values = crawling(url,maxDepth,numberOfRelated)
return render_template('index.html',var=values)
The form part of initial.html and index.html are actually the same
<form class="form-inline" action="/" method="POST">
<div class="form-group">
<input name='url' type="text" class="form-control"/>
</div>
<div class="form-group minorForm">
<input name='numberOfRelated' type="text" class="form-control" />
</div>
<div class="form-group minorForm">
<input name='depth' type="text" class="form-control" />
</div>
<div class="form-group navbar-right">
<button class="btn btn-success minorForm generate" type="submit"> Generate</button>
</div>
</form>
In your main method, unless values is global, it won't be defined for if not values.
As to your question, add another render_template call just after the conditional for if the form was submitted:
if request.method=='POST':
url = request.form['url']
maxDepth = request.form['depth']
numberOfRelated = request.form['numberOfRelated']
values = crawling(url,maxDepth,numberOfRelated)
return render_template('index.html',var=values) # 1
return render_template('index.html',var=values) # 2
If the form is submitted, the conditional will be true and the template will be rendered at comment #1. If the user is navigating to the page normally, the conditional will be false and the line with comment #2 will be called.
I'm a bit confused about the question, but you should always redirect after a POST (unless there was an error in the form and no action was taken). That way the same action won't be repeated if the user reloads the page.