Send only specific value to server in Django - javascript

I have a html code like this:
{% for i, j, k in full_name %}
{{ i }} {{ j }}
<input type="text" name="follow_id" value="{{ k }}" />
<input type="submit" value="Follow"><br /> <br />
{% endfor %}
The output looks like this:
user1 user_id_of_user1 follow_button
user2 user_id_of_user2 follow_button
user3 user_id_of_user3 follow_button
If I press the follow button of user3 I want to send the id of user3 only so that I can access it in server like this:
followed_user = request.POST['follow_id']
# Process
But, no matter which follow_button I press, I get the user id of only user1. How to fix this?

This is not a Django issue, but a HTML issue. Here is the work around: 1 form for each user:
{% for i, j, k in full_name %}
<form action="mydomain.com/mysubmiturl/" method="POST"><!-- Leave action empty to submit to this very same html -->
{% csrf_token %} <!-- Django server only accept POST requests with a CSRF token -->
{{ i }} {{ j }}
<input type="text" name="follow_id" value="{{ k }}" />
<input type="submit" value="Follow"><br /> <br />
</form>
{% endfor %}
Note that all the forms submit to the same URL, and thus the same view function !

Just my 2 cents, I would use some jQuery for this job.
In your template:
{% for i, j, k in full_name %}
{{ i }} {{ j }}
Follow
{% endfor %}
Then submit the data using AJAX:
$('.follow-button').click(function (e) {
e.preventDefault();
var this_id = $(this).attr('id').replace('js-follow-', '');
$.ajax({
type: 'POST',
url: 'path/to/view',
data: {'follow_id': this_id},
success: function (resp) {
// do something with response here?
}
});
});

Related

How to implement predictive search into Shopify store

I'm trying to implement predictive search into the search bar on the store, however I'm having abit of trouble making sense of the docs.
Here's what I've got so far, hopefully someone can point me in the right direction with what it is I am missing:
%- if settings.predictive_search_enabled -%}
<predictive-search data-loading-text="{{ 'accessibility.loading' | t }}">
{%- endif -%}
<form action="{{ routes.search_url }}" method="get" role="search">
<ul>
<li>
<input
type="search"
name="q"
placeholder="Amp Hours (aH)"
class="amp-input"
value="{{ search.terms | escape }}"
{%- if settings.predictive_search_enabled -%}
role="combobox"
aria-expanded="false"
aria-owns="predictive-search-results-list"
aria-controls="predictive-search-results-list"
aria-haspopup="listbox"
aria-autocomplete="list"
autocorrect="off"
autocomplete="off"
autocapitalize="off"
spellcheck="false"
{%- endif -%}>
{%- if predictive_search.performed -%}
<ul class="amp-dropdown-container">
{%- if predictive_search.resources.products.size > 0 -%}
<h5 class="volt-options-title">Top Searches</h5>
{%- endif -%}
{%- for product in predictive_search.resources.products -%}
<li>
{{ product.title }}
</li>
{%- endfor -%}
</ul>
{%- endif -%}
</li>
</ul>
</form>
{%- if settings.predictive_search_enabled -%}
</predictive-search>
{%- endif -%}
A predictive search box shows up but its not the way I need it to be. (only want it displaying products, not pages collections etc aswell).
I've also seen the javascript below in other tutorials but dont know how to use it for what I need. Any suggestions?
<script>
var q = 'goki'
var b = '&resources[type]=product'
$.ajax('/search/suggest.json?q=' + q + b,{
type: 'GET',
dataType: 'json', // added data type
success: function(response) {
console.log(response);
var productSuggestions = response.resources.results.products;
if (productSuggestions.length > 0) {
var firstProductSuggestion = productSuggestions[0];
alert(firstProductSuggestion.body);
}
}
});
</script>

The submission form was duplicated in the ajax response page using Django views.py

I am trying to use a form to submit the parameter to views.py and get the results back to the html. However, the form part was repeatedly display in the page.
enter image description here
Here is my views.py
def fund_main_py(request):
last_trade_date = request.GET['last_trade_date']
print(last_trade_date)
plot_div1, plot_div2 = fund_main_main(last_trade_date)
return render(request, 'optionsfund.html', context={'plot_div1': plot_div1, 'plot_div2': plot_div2})
Here is my stocksettle.js
$(document).ready(function(){
$("#btn_submit").click(function(){
document.getElementById("result").innerHTML = '抓取中.... 若期限過長,請稍後1分鐘!';
var stock_code = $("#stock_code").val();
var last_trade_date = $("#last_trade_date").val();
$.ajax({
type: "GET",
url: "/fund_main_py",
data:{
"stock_code":stock_code,
"last_trade_date":last_trade_date
},
success: function (Data) {
$("#result").html(Data);
},
error: function (e) {
console.log(e);
}
});
})
});
Here is my optionsfund.html
<table border="0">
<tr>
<td><fieldset>
<span> 指數/股票代號 :</span>
<input type="button" id="btn_submit" value=" 查詢 ">
</fieldset></td>
</tr>
</table>
<span id="result">
<span id="plot1">
{% autoescape off %}
{{ plot_div1 }}
{% endautoescape %}
</span><br><br>
<span id="plot2">
{% autoescape off %}
{{ plot_div2 }}
{% endautoescape %}
</span>
</span><br><br>

Django/Js: how to post a form without reloading whole page

My application currently flows through 3 pages:
User selects question in index page
User submits answer in answer page
User is presented with result in results page.
I want to compress that down to a single page where the user submits an answer to the question and result is shown on the same page.
The following django-template code separates questions with Bootstrap accordion. How do I post the form without refreshing the whole page? I want to be able to display the result on the page, update CSS styling with Javascript etc.
<h2>{{ category.title }}</h2>
<div class="accordion" id="accordion{{category.title}}">
{% for challenge in category.challenge_set.all %}
<div class="card">
<div class="card-header" id="heading{{challenge.id}}">
<h2 class="mb-0">
<button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#collapse{{challenge.id}}" aria-expanded="true" aria-controls="collapse{{challenge.id}}">
{{ challenge.question_text }} - {{ challenge.point_value }} points
</button>
</h2>
</div>
<div id="collapse{{challenge.id}}" class="collapse in" aria-labelledby="heading{{challenge.id}}" data-parent="#accordion{{category.title}}">
<div class="card-body">
<p>{{ challenge.description }}</p>
<form action="{% url 'challenges:answer' challenge.id %}" method="post">
{% if challenge|is_answered:request %}
<label for="answered">Answer</label>
<input type="text" name="answered" id="answered" value="{{ challenge.answer_text }}" readonly>
{% else %}
{% csrf_token %}
<label for="answer">Answer</label>
<input type="text" name="answer" id="answer">
<input type="submit" value="Submit">
{% endif %}
</form>
</div>
</div>
{% endfor %}
</div>
Here is the view:
def index(request):
context = {'challenges_by_category_list': Category.objects.all()}
return render(request, 'challenges/index.html', context)
def detail(request, challenge_id):
challenge = get_object_or_404(Challenge, pk=challenge_id)
return render(request, 'challenges/detail.html', {'challenge': challenge})
def results(request, challenge_id, result):
challenge = get_object_or_404(Challenge, pk=challenge_id)
return render(request, 'challenges/results.html', {'challenge':challenge, 'result':result})
def answer(request, challenge_id):
challenge = get_object_or_404(Challenge, pk=challenge_id)
result = "Incorrect, try again!"
if challenge.answer_text.lower() == request.POST['answer'].lower():
current_user = request.user
session = User_Challenge(user=current_user, challenge=challenge, answered=True)
session.save()
points = Profile(user=current_user, points=challenge.point_value)
points.save()
result = "Correct!"
return HttpResponseRedirect(reverse('challenges:results', args=(challenge.id, result)))
You can try this:
Add the below script in your template:
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
write a script and a function inside it to submit the form data.
<script type="text/javascript">
function submitData( challenge_id ){
// Get answer from the input element
var answer = document.getElementById("answer").value;
// add the url over here where you want to submit form & challenge_id is also taken as a parameter.
var url = "<your_url>";
$.ajax({
url: url,
data: {
'answer': answer,
},
dataType: 'JSON',
success: function(data){
// show an alert message when form is submitted and it gets a response from the view where result is provided and if url is provided then redirect the user to that url.
alert(data.result);
if (data.url){
window.open(data.url, '_self');
}
}
});
}
</script>
Change type of the submit button and add an onclick event to call the submitData() function and pass the challenge id to it. And remove the action attr from the form.
see below:
<form method="post">
{% csrf_token %}
{% if challenge|is_answered:request %}
<label for="answered">Answer</label>
<input type="text" name="answered" id="answered" value="{{ challenge.answer_text }}" readonly>
{% else %}
<label for="answer">Answer</label>
<input type="text" name="answer" id="answer">
// over here
<button type="button" onclick="submitData({{ challenge.id }})">
Submit
</button>
{% endif %}
</form>
Return a JsonReponse to the ajax call from the views.
views.py
def answer(request, challenge_id):
answer = request.GET.get('answer', False)
url = False
if challenge.objects.filter(id=challenge_id).exists() and answer:
challenge = Challenge.objects.get(id=challenge_id)
if challenge.answer_text.lower() == answer.lower():
current_user = request.user
session = User_Challenge(user=current_user, challenge=challenge, answered=True)
session.save()
points = Profile(user=current_user, points=challenge.point_value)
points.save()
result = "Correct!"
# specify the url where you want to redirect the user after correct answer
url = ""
else:
result = "Incorrect, try again!"
data = {
'result': result,
'url': url
}
return JsonResponse(data)

form wizard does not move to the next screen in a jquery dialog

I an using django-crispy forms and using that in a jquery dialog box to show a form wizard. the problem that I am facing is that when used in the dialog box the wizard never moves to the next screen.
So, my wizard is defined as follows:
class ContactWizard(SessionWizardView):
def get_template_names(self):
return "reviewdialog.html"
def done(self, form_list, **kwargs):
return HttpResponseRedirect('index')
And the template is defined as:
{% load crispy_forms_tags %}
{% load i18n %}
{% block content %}
<form action="." method="post">
{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{% crispy form %}
{% endfor %}
{% else %}
{% crispy wizard.form %}
{% endif %}
{% if wizard.steps.prev %}
<button name="wizard_goto_step" value="{{ wizard.steps.first }}">{% trans "first step" %}</button>
<button name="wizard_goto_step" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
{% endif %}
</table>
<input type="submit" class="btn btn-success" value = "NEXT">
</form>
{% endblock %}
Now, I show this in a jquery dialog where I have overridden the submit method to ensure that the dialog does not close on clicking the 'NEXT' button
<script>
function EditDialog(pk) {
$.ajax({
url: "{% url 'populatereviewform' %}",
method: 'GET',
data: {
pk: pk
},
success: function(formHtml){
//place the populated form HTML in the modal body
$('.modal-body').html(formHtml);
$( "#dialog" ).modal({width: 500, height: 500});
},
dataType: 'html'
});
$('#dialog').submit( function(e) {
return false;
});
return false;
}
</script>
The AJAX part just populates the form with some data and the dialog object is a standard jquery modal dialog. The form is shown at the first screen and is populated with the correct value but when I press NEXT nothing happens in the sense that the wizard does not transition.
The urls.py is configured as:
url(r'^review/(?P<pk>\d+)/$', views.ContactWizard.as_view([DummyForm, OtherForm]), name='review'),
Som, the form starts with the DummyForm (which is a ModalForm) but does not progress to the next wizard screen. I have a feeling it could be something to do with my javascript but could bit get to the bottom of this.
EDIT
So, based on #udi's answer, I tried the following:
$("#dialog").submit(function(e)
{
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
var postData = $(this).serializeArray();
var formURL = $(this).attr("action");
$.ajax(
{
url : formURL,
type: "POST",
data : postData,
success:function(data, textStatus, jqXHR)
{
$('.modal-body').html(data);
},
error: function(jqXHR, textStatus, errorThrown)
{
alert(errorThrown)
}
});
e.preventDefault(); //STOP default action
e.unbind(); //unbind. to stop multiple form submit.
});
return false;
}
However, the data that is returned here is not the next screen of the wizard but the underlying page on which the dialog is shown. So, perhaps it is the formURL or postdata variables that are not initialized properly?
The template for the wizard screen is:
{% load crispy_forms_tags %}
{% load i18n %}
{% block head %}
{{ wizard.form.media }}
{% endblock %}
{% block content %}
<form id="review-form" action="." method="post">
{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{% crispy form %}
{% endfor %}
{% else %}
{% crispy wizard.form %}
{% endif %}
{% if wizard.steps.prev %}
<button name="wizard_goto_step" class="btn btn-success" value="{{ wizard.steps.first }}">{% trans "first step" %}</button>
<button name="wizard_goto_step" class="btn btn-success" value="{{ wizard.steps.prev }}">{% trans "prev step" %}</button>
{% endif %}
</table>
<input type="submit" class="btn btn-success" value = "Hello">
</form>
{% endblock %}
You will need to get the html of the next form via jQuery and update it in the dialog.

Symfony2 jQuery div refresh without

i have a form and i use jQuery for submit and work without refresh page..
$('#formnotifica').submit(
function(event){
event.preventDefault();
term = $(this).serialize();
url = $(this).attr('action');
$.post(
url,
term,
function(data){
}
)
}
);
Now i would refresh only my content the form and the date after click of submit or some second..
I use this code when i tried but give me another page Symfony and give me problems..
$(document).ready(function() {
$("#aggiorna").load("");
var refreshId = setInterval(function() {
$("#aggiorna").load("" + Math.random());
}, 1000);
});
Where #aggiorna is the "ID" of my .. How can i do for refresh my result of query in controller?? Thanks and sorry for my english
THIS IS THE CODE HTML
<div id="aggiorna">
<ul>
{% for n in notifications %}
{% if n.is_displayed == 0 %}
<li>
<form id="formnotifica" action="{{ path('profilo_index', {'id': n.id}) }}" method="post">
<input name="id" type="hidden" value="{{ n.id }}" />
<button class="submit" id="submit" type="submit" >{{n.text|raw}}</button>
</form>
</li>
{% else %}
<li>{{n.text|raw}}
</li>
{% endif %}
{% endfor %}
</ul>
</div>
In the controller there is only DQL query for update a field in my db
Remove:
event.preventDefault();

Categories

Resources