def tracker(request):
if request.method == "POST":
orderId = request.POST.get('orderId','')
email = request.POST.get('email','')
try:
order = Orders.objects.filter(order_id=orderId, email=email)
if len(order) > 0:
update = Updateorder.objects.filter(order_id=orderId)
updates = []
for item in update:
updates.append({'text':item.update_desc, 'time':item.time_stamp})
response = json.dumps(updates, default=str)
return HttpResponse(response)
else:
print(len(order))
return HttpResponse(f"{len(order)}")
except Exception as e:
return HttpResponse(f'exception {e}')
return render(request,'shop/Tracker.html')
{% extends 'shop/base.html' %} {% block title %}MAC Tracker {% endblock %} {% block body %}
<div class="container">
<div class="col-md-8 offset-md-2 my-4">
<h3>Step 1 - Enter your Email address and tracker ID to track your order</h3>
<form method="post" id="trackerForm" action="#">{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-6">
<label for="name">Tracker ID</label>
<input type="text" class="form-control" id="orderId" name="orderId" placeholder="Enter tracker ID">
</div>
<div class="form-group col-md-6">
<label for="email">Email</label>
<input type="email" class="form-control" id="email" name="email" placeholder="Enter Email">
</div>
</div>
<button type="submit" class="btn btn-primary">Track Order</button>
</form>
</div>
<div class="col-md-8 offset-md-2 my-5">
<h3>Your order status</h3>
<ul class="list-group" id="items">
<b>Enter your order Id and Email and click Track Order to find details about your order!</b>
</ul>
</div>
</div>
{% endblock %} {% block js %}
<script>
$('#trackerForm').submit(function(event) {
$('#items').empty();
var formData = {
'orderId': $('input[name=orderId]').val(),
'email': $('input[name=email]').val(),
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val()
};
$.ajax({
type: 'POST',
url: '/shop/tracker/',
data: formData,
encode: true
})
.done(function(data) {
console.log(data);
updates = JSON.parse(data);
if (updates.length > 0 & updates != {}) {
for (i = 0; i < updates.length; i++) {
let text = updates[i]['text'];
let time = updates[i]['time'];
mystr = `<li class="list-group-item d-flex justify-content-between align-items-center">
${text}
<span class="badge badge-primary badge-pill">${time}</span>
</li>`
$('#items').append(mystr);
}
} else {
mystr = `<li class="list-group-item d-flex justify-content-between align-items-center">
Sorry, We are not able to fetch this order id and email. Make sure to type correct order Id and email</li>`
$('#items').append(mystr);
}
});
event.preventDefault();
});
</script>
{% endblock %}
I am using ajax to submit the form when I try to submit the form it is showing the error jquery-3.4.1.js:9837 POST http://127.0.0.1:8000/shop/tracker/ 404 (Not Found).
I have added event.preventDefault(); still it is not working
$.ajax({
type: 'POST',
url: '/shop/tracker/',
data: formData,
encode: true
})
.done(function(data) {
console.log(data)
updates = JSON.parse(data);
if (updates.length > 0 & updates != {}) {
for (i = 0; i < updates.length; i++) {
let text = updates[i]['text'];
let time = updates[i]['time'];
mystr = <li class="list-group-item d-flex justify-content-between align-items-center">
${text}
<span class="badge badge-primary badge-pill">${time}</span>
</li>
$('#items').append(mystr);
I am expecting the html output in the same page but there is no changes occurring.for reference views.py and html page has shown in above sections.
thank you stefan and henrik for your comments I just corrected the url and the page is working properly. The corrected url : '/shop/tracker' earlier it was '/shop/tracker/' one extra slash at the end causing the problem.
Related
I am trying to clear all filters on button click at once. This is what I have on filters.py file and filters class:
class Filters(django_filters.FilterSet):
id = django_filters.NumberFilter(label=_("ID"))
name = django_filters.TextFilter(label=_("Name"))
And in base template:
<form id="filters-filters-form" action="javascript:;" onsubmit="onSubmit(this)" class="form form-inline main-filter">
{% bootstrap_form filter.form layout='inline' %}
<div>
<button class="btn ml-auto mr-2" onclick="resetFilters()">Clear all</button>
{% trans "Apply" as button_text %}
{% bootstrap_button button_text button_class="btn-primary" %}
</div>
</form>
resetFilters() function:
var resetFilters = function() {
let formId = document.getElementById('filters-form')
let formChildren = formId.childNodes;
Array.from(formChildren).forEach(formChild => {
formChild.val(null).trigger('change')
});
}
Is there any easy way to reset all filters?
P.S: I need to reset these filters without any id of form-control because it will be reusable base template
you can just add a button and add the URL of your form :
<a class="btn ml-auto mr-2" href={<pass your URL here>} > Clear All </a>
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)
While I'm looking at log file, I got many error logs related to CSRF
I got warning log below
Forbidden (CSRF token missing or incorrect.): /my/site/uri
and right after that error log below
Internal Server Error: /my/site/uri
Traceback (most recent call last):
File "/data/kukkart_env/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 140, in get_response
response = middleware_method(request, callback, callback_args, callback_kwargs)
File "/data/kukkart_env/local/lib/python2.7/site-packages/django/middleware/csrf.py", line 216, in process_view
return self._reject(request, REASON_BAD_TOKEN)
File "/data/kukkart_env/local/lib/python2.7/site-packages/django/middleware/csrf.py", line 106, in _reject
return _get_failure_view()(request, reason=reason)
TypeError: server_error() got an unexpected keyword argument 'reason'
And there is a form for a cart to submit.
There is a CSRF_TOKEN in a form
{% block cart %}
<form class="form-horizontal" method="post" action="/my/site/uri/">
{% csrf_token %}
<div class="modal" id="cartShowAllModal">
<div class="modal_wrap">
<div class="modal_content">
<h5 class="title">Cart</h5>
<div class="content-box">
<div class="modal_cart_wrap">
<div class="inner">
<ul class="cart_list">
{{ cart_form.product_formset.management_form }}
{% if cart_form.total_count != 0 and cart_form.total_count %}
{% for product_form in cart_form.product_formset %}
</ul>
<div id="cart_message_empty" class="cart_list empty" style="display: none;">
{% else %}
<div id="cart_message_empty" class="cart_list empty" style="display: block;">
{% endif %}
<p class="txt"><span class="blind">Empty Cart</span></p>
</div>
</div>
</div>
</div>
<div class="cart_func">
{% if cart_form.total_count != 0 %}
<button id="cart_close" type="button" class="btn cancel"><span>Continue Shopping</span></button>
<button id="cart_message_checkout" type="submit" class="btn checkout"><span>Checkout</span></button>
{% endif %}
</div>
<script>
$('#cart_close').on('click', function () {
closeModal();
})
</script>
<span class="blind">Close Popup</span>
</div>
</div>
</div>
</form>
{% endblock %}
the views.py is this
I don't know what the issue is.
class CartSubmitView(CheckoutClearSessionMixin, View):
def post(self, request, *args, **kwargs):
if 'cart_product_pks' not in self.request.session:
return HttpResponseRedirect('/')
if len(self.request.session['cart_product_pks']) == 0:
return HttpResponseRedirect('/')
if self.request.user.is_authenticated() and self.request.user.is_non_registered:
from account import views as account_views
account_views.logout(request)
return HttpResponseRedirect('/account/login/?next=/order/checkout/')
for cart_product_pk in self.request.session['cart_product_pks']:
for key, value in self.request.POST.items():
try:
if int(value) == int(cart_product_pk):
quantity = int(self.request.POST[key.replace('id', 'quantity')])
order_product = models.OrderProduct.objects.get(pk=cart_product_pk)
order_product.quantity = quantity
order_product.save()
except:
continue
self.request.session['cart_checkout'] = True
self.request.session['order_product_pks'] = self.request.session['cart_product_pks']
return HttpResponseRedirect('/order/checkout/')
There is not that much source code related csrf token here
What makes this error?
It means that the form you are submitting is missing the csrf_token which is used to prevent malicious attacks.
To integrate a csrf_token in a form, you should add {% csrf_token %}. Example:
<form>
{% csrf_token %}
<input type="text" />
</form>
To integrate into an AJAX request, you can use the {{ csrf_token }} variable. Example:
var data = {
csrfmiddlewaretoken: "{{csrf_token}}",
...
};
$.ajax({
type: 'POST',
url: 'url/to/ajax/',
data: data,
dataType: 'json',
...
});
I want to retrieve data to modelForm based on user input. I am developing a transaction app, I want to retrieve account balance to the form based on the account number selected by the user. First I want to print an alert to test the existence of the account number but keep getting 500 internal server error.
Here is the code
models.py
class Account(models.Model):
ACCOUNT_TYPE = (
('Checking','Checking'),
('Savings','Savings'),
)
user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
account_number = models.PositiveIntegerField(primary_key=True)
account_type = models.CharField(max_length=8, choices=ACCOUNT_TYPE, default='select')
account_balance = models.PositiveIntegerField(blank=True, default=0)
views.py
#login_required
def validate_account_number(request):
account_number = request.Get.get['account_number']
data = {
'is_exist': Account.objects.filter(
account_number=account_number).exists()
}
return JsonResponse(data)
transaction.html
<form class="form-horizontal" method=POST id="sendform">
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade active show" transfer="home">
<div class="col-md-6">
<div class="tile">
<h3 class="tile-title">Transfer Money</h3>
<div class="tile-body">
{% csrf_token %}
{% bootstrap_form form%}
{{ form.non_field_errors }}
<div class="tile-footer">
<div class="row">
<div class="col-md-8 col-md-offset-3">
<button type="submit"> <i class="fa fa-fw fa-lg
fa-check-circle"></i>Send</button> <a class="btn btn-
secondary" href="#"><i class="fa fa-fw fa-lg fa-times-circle">
</i>Cancel</a>
</div>
</div>
</div>
</div>
</div>
</div></div>
</div>
</form>
</main>
{% endblock %}
{% block javascript %}
<script>
$("#id_creditor_account").change(function(){
var account_number = $(this).val();
$.ajax({
url: '{% url 'users:validate_account_number'%}',
data:{
'account_number':account_number
},
dataType: 'json',
success: function(data){
if (data.is_exist){
alert("Account exist");
}
}
});
});
</script>
Here is the screenshot: html_transction_page
Error from console
jquery-3.2.1.min.js:4 GET http://127.0.0.1:8000/users/ajax/validate_account_number/?account_number=5645786809 500 (Internal Server Error)
send # jquery-3.2.1.min.js:4
ajax # jquery-3.2.1.min.js:4
(anonymous) # (index):265
dispatch # jquery-3.2.1.min.js:3
q.handle # jquery-3.2.1.min.js:3
ListPicker._handleMouseUp
The attribute is request.GET, not request.Get. And as Ralf says, it is a method. So either:
account_number = request.GET.get('account_number')
or
account_number = request.GET['account_number']
I think the error is in your view: the method GET.get cannot be indexed, but it can be called.
Try changing
# with brackets, capitalized 'Get'
account_number = request.Get.get['account_number']
to
# with parenthesis, all uppercase 'GET'
account_number = request.GET.get('account_number')
EDIT
Ah, right, its request.GET (all uppercase), not request.Get (capitalized).
New to Django/Python/stackexchange...
I have a Jquery Datatable and I'm having difficulty passing along the value of a cell (called email_id) of the table as an HTTP parm to be used when handling a new form page.
The view is initially receiving the request correctly per the debug output:
WSGIRequest: GET '/main_app/makeTask/?csrfmiddlewaretoken=gDeTwaNfGNLO7cdMk1
B9gsdpcGYpKAyL&email_id=14d2a002852e1738'
It successfully extracts email_id with request.GET.get() on the first call (then proceeds to construct the form and render it) but it gets dropped when the form is being rendered. I.e., email_msg_id is extracted correctly on the GET but not on the subsequent POST.
Here is the extraction code along with the render statement. The problem is the 'email_id' is not propagating when I render the form so it cannot be used by view when it processes the form input.
email_msg_id = request.GET.get('email_id', "GET - no email_id")
...
return render(request, 'main_app/makeTask.html', {'form': form, 'email_id': email_msg_id})
Debug message:
<WSGIRequest: GET '/main_app/makeTask.html'>
Here are relevant sections of urls.py:
url(r'^makeTask', views.make_task, name='makeTask'),
My Jquery call (which appears to be working/passing along the email_ID correctly:
$('#make_task').click( function () {
alert( table.cell('.selected',4).data()+' Converted to Task');
// alert(table.cell('.selected',0).data()+' Make Task selected:');
$.ajax({
type: "GET",
url: "/main_app/makeTask/",
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'email_id' : table.cell('.selected',4).data(),
},
success: makeTaskSuccess,
dataType: 'html'
});
function makeTaskSuccess(data)
{
alert('Convert email to task ');
}
} );
Here is the view (with unrelated stuff removed):
def make_task(request):
if request.method == "GET":
email_msg_id = request.GET.get('email_id', "GET - no email_id") # from the post dictionary of the request object passed in
else:
email_msg_id = request.POST.get('email_id', "POST - no email_id")
print "EMAIL_MSG_ID: ", email_msg_id, "METHOD: ", request.method
if request.method == 'POST':
form = MakeTaskForm(request.POST or None) # Create a form instance and populate it with the data
if form.is_valid():
# process and save to db
#...
return HttpResponseRedirect(reverse('main_app.views.index'))
else:
print form.errors
return
else:
form = MakeTaskForm()
return render(request, 'main_app/makeTask.html', {'form': form, 'email_id': email_msg_id})
#return render(request, 'main_app/makeTask.html', context_dict)
UPDATE: added relevant template code:
<form id="make_task_form" method="post" action="/main_app/makeTask/", method="Post">
{% csrf_token %}
<div class="row">
<div class="col-lg-8 col-xs-12">
<div class="form-group">
<label>Due Date:  </label>
<label class="radio-inline">
<input type="radio" name="due_selection" id="optionsRadiosInline1" value="TODAY" {{ form.due_selection }} Today
</label>
</div>
</div>
<div class="col-lg-4 col-xs-12">
<p>Specific Date: <input type="text" id="datepicker" {{ form.due_date }}</p>
</div>
</div>
<div class="row">
<div class="col-lg-4 col-xs-12">
<button type="submit" class="btn btn-info btn-med" id="btn-make-task">
Make Task
</button>
<i class="fa fa-trash-o fa-2x pull-right"></i>
</div>
</div>
</form>
From the code you posted I assume you're using GET for AJAX and POST in your form.
The form code you posted is wrong, access your form fields in your template like this (also get rid of the duplicated method attribute in <form>):
<form id="make_task_form" method="post" action="/main_app/makeTask/">
{% csrf_token %}
<div class="row">
<div class="col-lg-8 col-xs-12">
{{ form.due_selection }}
</div>
<div class="col-lg-4 col-xs-12">
{{ form.due_date }}
</div>
</div>
<div class="row">
<div class="col-lg-4 col-xs-12">
<button type="submit" class="btn btn-info btn-med" id="btn-make-task">
Make Task
</button>
<i class="fa fa-trash-o fa-2x pull-right"></i>
</div>
</div>
</form>
To use <input type="radio"> for the field due_selection you should specify the RadioSelect widget in your ModelForm class:
CHOICES = (('1', 'First',), ('2', 'Second',))
due_selection = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)