I asked this question previously and didn't get any help/solution. So I'm asking again.
I'm trying to make sure that even if the user refresh the page or goes back and comes back to that page, the radio button is still the same as what the user selects.
N.B: the value of the radio button is saved in sessions
<div class="col-md-1 ps-md-1">
<input class="align-middle h-100" type="radio" name="deliveryOption" id="{{option.id}}"
value="{{option.id}}">
</div>
Ajax
$('input[type=radio][name=deliveryOption]').on('change', function(e) {
e.preventDefault();
$.ajax({
type: "POST",
url: '{% url "checkout:cart_update_delivery" %}',
data: {
deliveryoption: $(this).val(),
csrfmiddlewaretoken: "{{csrf_token}}",
action: "post",
},
success: function (json) {
document.getElementById("total").innerHTML = json.total;
document.getElementById("delivery_price").innerHTML = json.delivery_price;
},
error: function (xhr, errmsg, err) {},
});
});
my view
def cart_update_delivery(request):
cart = Cart(request)
if request.POST.get("action") == "post":
delivery_option = int(request.POST.get("deliveryoption"))
delivery_type = DeliveryOptions.objects.get(id=delivery_option)
updated_total_price = cart.cart_update_delivery(delivery_type.delivery_price)
session = request.session
if "purchase" not in request.session:
session["purchase"] = {
"delivery_id": delivery_type.id,
}
else:
session["purchase"]["delivery_id"] = delivery_type.id
session.modified = True
response = JsonResponse({"total": updated_total_price, "delivery_price": delivery_type.delivery_price})
return response
when I added a django templating if statement, it kinda work but the radio button is always remember on the last radio button when refreshed.
{% for option in deliveryoptions %}
<input class="align-middle h-100" type="radio" {% if deliveryoption == %} checked=1 {% elif delivery_option == 2 %} checked="checked"{% endif %} autocomplete='on' name="deliveryOption" id="{{option.id}}"
value="{{option.id}}">
</div>
</div>
</div>
{% endfor %}
</div>
Related
I am trying to build a dependant dropdown in a django form, but it is not working. I have followed videos and tutorials, but got no luck.
I would like to select a brand of a car (make) and then a model of a car. The model depends on the car's brand, of course.
I have followed this tutorial https://python.plainenglish.io/python-and-django-create-a-dependent-chained-dropdown-select-list-b2c796f5a11
Status: The "Make" dropdown works fine. The "Model" dropdown is never showing anything.
It just does not work, but no error is shown... :S
models.py
from django.db import models
from django import forms
class Vehicle(models.Model):
make = forms.CharField(max_length=30)
model = forms.CharField(max_length=30)
...omitted
forms.py
from django import forms
from .models import Vehicle
import json
def readJson(filename):
with open(filename, 'r') as fp:
return json.load(fp)
def get_make():
""" GET MAKE SELECTION """
filepath = '/Users/alvarolozanoalonso/desktop/project_tfm/tfm/JSON/make_model_A.json'
all_data = readJson(filepath)
all_makes = [('-----', '---Select a Make---')]
for x in all_data:
if (x['make_name'], x['make_name']) in all_makes:
continue
else:
y = (x['make_name'], x['make_name'])
all_makes.append(y)
# here I have also tried "all_makes.append(x['make_name'])
return all_makes
class VehicleForm(forms.ModelForm):
make = forms.ChoiceField(
choices = get_make(),
required = False,
label='Make:',
widget=forms.Select(attrs={'class': 'form-control', 'id': 'id_make'}),
)
...omitted
class Meta:
model = Vehicle
fields = ['make', 'is_new', 'body_type', 'fuel_type', 'exterior_color', 'transmission', 'wheel_system', 'engine_type',
'horsepower', 'engine_displacement', 'mileage', 'transmission_display', 'year', 'fuel_tank_volume',
'city_fuel_economy', 'highway_fuel_economy', 'maximum_seating']
model.HTML
{% block javascript %}
<script>
$("#id_make").change(function () {
var makeId = $(this).val();
$.ajax({
type: "POST",
url: "{% url 'get-model' %}",
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'make': makeId,
},
success: function (data) {
console.log(data.models);
let html_data = '<option value="">-------</option>';
data.models.forEach(function (data) {
html_data += `<option value="${data}">${data}</option>`
});
$("#id_model").html(html_data);
}
});
});
</script>
{% endblock javascript %}
<form class="" action="" method="post">
{% csrf_token %}
{% for error in errors %}
<div class="alert alert-danger mb-4" role="alert">
<strong>{{ error }}</strong>
</div>
{% endfor %}
<div class="form-row">
<div class="form-group col-md-6">
<label>Status:</label>
{{ form.make }}
</div>
<div class="form-group col-lg-6">
<label >Model:</label>
<select id="id_model" class="form-control" name="state">
<option value="-----">Select Model</option>
</select>
</div>
...omitted
<div class="form-group col-md-6">
<button type="submit" class="btn btn-primary">Calculate</button>
</div>
</form>
views.py
def model(request):
context = {}
if request.method == 'GET':
form = VehicleForm()
context['form'] = form
return render(request, 'model.html', context)
if request.method == 'POST':
form = VehicleForm(request.POST)
if form.is_valid():
return render(request, 'model.html', context)
def getModel(request):
make = request.POST.get('make')
models = return_model_by_make(make)
return JsonResponse({'models': models})
Your change handler for id_make is attached before the select is created in the DOM, so your event handler does not fire.
You can use event delegation to set up an event handler before an element is created
$(document).on('change', "#id_make", function () {
var makeId = $(this).val();
$.ajax({
type: "POST",
url: "{% url 'get-model' %}",
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'make': makeId,
},
success: function (data) {
console.log(data.models);
let html_data = '<option value="">-------</option>';
data.models.forEach(function (data) {
html_data += `<option value="${data}">${data}</option>`
});
$("#id_model").html(html_data);
}
});
});
I'm trying to use Jquery with Ajax to check if username is available or not, I am checking the code twice, loading image is coming but username messages are not displaying and even loading image is not being hidden.
Help me find what went wrong, please
in Script.js
$(document).ready(function() {
$("#username").on('input', function(e) {
$('#msg').hide();
$('#loading').show();
if($('#username').val() == null || $('#username').val == ""){
$('#msg').show();
$('#msg').html("Username is required field.").css("color", "red");
$('#loading').hide();
}
else{
$.ajax({
type: "POST",
url: "/signup",
data: $('#RegisterForm').serialize(),
dataType: "html",
cache: false,
success: function(msg) {
$('#msg').show();
$('#loading').hide();
$("#msg").html(msg);
},
error: function(jqXHR, textStatus, errorThrown) {
$('#msg').show();
$('#loading').hide();
$("#msg").html(textStatus + " " + errorThrown);
}
});
}
});
});
python in main.py
#app.route('/signup', methods=['GET', 'POST'])
def signup():
--------
if request.method == 'POST' and form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user:
resp = jsonify('<span style="\'color:red;\'">Username unavailable</span>')
resp.status_code = 200
return resp
else:
resp = jsonify('<span style="\'color:green;\'">Username available</span>')
resp.status_code = 200
return resp
hashed_password = generate_password_hash(form.password.data, method='sha256')
new_user = User(username=form.username.data, email=form.email.data, password=hashed_password)
try:
---------
else:
-------
return render_template('signup.html', form=form)
WTForms in html
HTML code
<form class="form-signin" method="POST" action="/signup">
<h2 class="form-signin-heading">Sign Up</h2>
{% for field, errors in form.errors.items() %}
{{ ', '.join(errors) }}
{% endfor %}
{{ form.hidden_tag() }}
{{ wtf.form_field(form.username) }}
<div id="msg"></div>
<span id="loading" style="display: none;"><img src="{{ url_for('.static', filename='images/loading.gif') }}"></span>
{{ wtf.form_field(form.email) }}
{{ wtf.form_field(form.password) }}
{{ wtf.form_field(form.cpassword) }}
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign Up</button>
</form>
</div>
Jsonify expects a dictionary.
jsonify({'message':'ok'}) instead of a string
You need on the backend something like that:
# api
#app.route("/check/<username>", methods=["GET"])
def check(username):
has_username = db.session.query(exists().where(User.username == username)).scalar()
return jsonify({"exists": has_username})
Then in javascript
$('#username-input-id').on('input', function() {
$.getJSON( "/check/"+$("#username-input-id").val(), function( data ) {
$("#check").html("<i class='fa fa-list-alt'></i>");
if (data['exists'] === true){
$("#check").html("<i style='color:red;' class='fas fa-exclamation-triangle'></i>");
}
})
});
where #check above is a holder/span to show an icon if username exists. Customise it with your code.
Also, flask-wtf allows you to do
{{ form.email() }}
instead of
{{ wtf.form_field(form.email) }}
if you passed form=form as a variable
I have tried to make an ajax request for getting the background task status but I cannot get the data.
Here is my Ajax request;
var ii=setInterval(function()
{
$.ajax({
type: "get",
url: '{% url "data:status" %}',
success:function (data)
{
console.log(data)
}
});
}, 5000);
function Cii(){
clearInterval(ii)
}
Here is my HTML;
<div class="jumbotron text-center" id="status">
<div id="display_status">
{% if pending and running %}
<p>{{pending}} Waiting.</p>
<p>{{running}} Going on.</p>
{% else %}
{% if completed >= 0 %}
<a href='#'> It's done, press for make prediction!</a>
{% else %}
<p>0 Waiting.</p>
<p>0 Going on.</p>
{% endif %}
{% endif %}
</div>
</div>
Here is the function which is triggered from ajax request;
def get_process_status():
now = timezone.now()
pending_tasks = Task.objects.filter(run_at__gt=now)
running_tasks = Task.objects.filter(locked_at__gte=now)
completed_tasks = CompletedTask.objects.all()
connection.close()
return len(pending_tasks), len(running_tasks), len(completed_tasks)
And here is my view;
#login_required(login_url = "user:login")
def process_status_view(request):
if request.is_ajax():
pending, running, completed = get_process_status()
context = {
"pending": pending,
"running": running,
"completed": completed,
}
return render(request, "pending_page.html", context)
return render(request, "pending_page.html")
How can I fix this?
It seems that my request.session isn't saved or is somehow modified in other ways, despite using request.session.modified = True after changing the value.
Here is the debug output:
This should run first.
This should run second.
I have set main category to 2 (Shoes)
Main category is 1 (Books)
The code below should display a different ModelForm based on selected category, however when I select, for instance, Books, ShoesModelForm is displayed and vice-versa. This currently works as follows: whenever a value in a combobox is changed, two AJAX requests are fired. First one calls a view (load_categories) that renders another if a category has children, otherwise returns an HttpResponse which stops attaching the listener. Second one calls a view (load_modelform) that renders a specific ModelForm if selected category is root node (main category).
mappings = {
'1': BookProductForm,
'2': ShoesProductForm
}
def load_categories(request):
print("This should run first.")
category_id = request.GET.get('category')
request.session['category'] = category_id
request.session.modified = True
if Category.objects.get(id=category_id).is_root_node():
request.session['main_category'] = category_id
request.session.modified = True
print(f"I have set main category to {request.session['main_category']} ({Category.objects.get(id=category_id).name})")
subcategories = Category.objects.get(id=category_id).get_children()
if subcategories:
return render(request, 'products/category_dropdown_list_options.html', {'subcategories': subcategories})
return HttpResponse('leaf_node')
def load_modelform(request):
print("This should run second.")
main_category = request.session['main_category']
print(f"Main category is {main_category} ({Category.objects.get(id=main_category).name})")
form = mappings[main_category]
return render(request, 'products/category_modelform.html', {'form': form})
#login_required
def product_create_view(request):
if request.method == 'POST':
category = request.session.get('main_category')
create_product_form = mappings[category](request.POST)
if create_product_form.is_valid():
create_product_form.save()
return render(request, 'products/product_create.html', {
'categories': Category.objects.filter(parent=None)
})
What might be going on here?
#EDIT:
I'm including my template with jQuery code that contains Ajax requests:
{% extends 'pages/base.html' %}
{% load static %}
{% block cssfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'products/css/create.css' %}">
{% endblock %}
{% block content %}
<h1>Create a product</h1>
<div class='modelform'>
<form method='POST' id='productForm' data-products-url="{% url 'products:ajax_load_categories' %}" data-modelform-url="{% url 'products:ajax_load_modelform' %}">
{% csrf_token %}
<div class='categories'>
<label>Category</label>
<select>
{% for category in categories %}
<option value="{{ category.pk }}">{{ category.name }}</option>
{% endfor %}
</select>
</div>
<div class='the-rest'>
{{ form.non_field_errors }}
{% for field in form %}
{% ifnotequal field.name 'category' %}
{{ field.label_tag }} {{ field }}
{{ field.errors }}
{% endifnotequal %}
{% endfor %}
</div>
<input type="submit" name="" value="Submit">
</form>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
var $r_ = function() {
var url = $("#productForm").attr("data-products-url");
var categoryId = $(this).val();
var toRemove = $(this).nextAll('select');
$.ajax({
url: url,
data: {
'category': categoryId
},
success: function (data) {
if (data != 'leaf_node') {
toRemove.remove();
$(".categories").append(data);
}
else {
toRemove.remove();
}
}
});
var url2 = $('#productForm').attr('data-modelform-url');
setTimeout(function() {
$.ajax({
url: url2,
data: {
'category': categoryId
},
success: function (data) {
if (data != 'dont_change_modelform') {
$('.the-rest').empty();
$('.the-rest').append(data);
}
}
});
}, 100);
}
$(document).on('change', 'select', $r_);
</script>
{% endblock %}
I've been stuck on this issue for a few weeks as I'm not very familiar with how to get the ajax set up. I'm working on a Django app which is basically one page that has a Dropdown menu. I would like to get whatever the user selects from the Dropdown menu and pass that data into my views.py so I can use that information to display a graph. Right now the graph part is working (I can pass in hard coded data into it and it will generate the graph) and my dropdown is working as well. However, I don't know how to get data from the drop down into my views.py. Here is how it looks.
Display.html
{% extends "RecordEvent/nav.html" %}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
</head>
{% block content %}
<div class="row">
<div class="padded">
<div class="download-header">
<h3>Logs</h3>
<div class="row inline download-header">
<div class="col-lg-6">
<div class="dropdown padding col-lg-6">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span id="dropdownTitle" class="">Measurable</span>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
{% include 'RecordEvent/includes/EntryDropdown.html' %}
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div class='padded'>
<div class='col-sm-12' url-endpoint='{% url "api-data" %}'>
<h1>Graph Data</h1>
<canvas id="myChart" width="400" height="400"></canvas>
</div>
</div>
<script>
{% block jquery %}
var endpoint = 'display/api/chart/data/'
var defaultData = []
var defaultLabels = [];
$.ajax({
method: "GET",
url: endpoint,
success: function(data){
defaultLabels = data.labels
defaultData = data.default
console.log(data)
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: defaultLabels,
datasets: [{
label: '# Measurable',
data: defaultData,
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
})
{% endblock %}
</script>
{% endblock %}
The first div creates the Dropdown menu. Everything below is to get the graph setup.
views.py
#login_required
def DisplayView(request):
return render(request,'DisplayData/Display.html')
class ChartData(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, format=None):
all_entries = models.Entries.objects.all().filter(parent=2) #change to input from drop down
all_id = models.Entries.objects.all().values_list('id', flat=True)
all_measurables = models.Measurables.objects.all().filter(user_id=1) #change to current user
all_times = [m.timestamp for m in all_entries]
all_data = []
for m in all_entries:
data = m.data
json_data = json.loads(data)
value = json_data['value']
all_data.append(value)
data = {
"labels": all_times,
"default": all_data,
#"default": all_parent,
}
return Response(data)
#login_required
def LogDisplay(request):
measurables=[entry for entry in models.Measurables.objects.all().filter(user_id=request.user.id)]
return render(request, 'DisplayData/Logs.html',{'dropdown':measurables})
I need to get the value from the drop down into the where the comment says get value from drop down.
How can I do it?
to post via form
<form method='post' action = 'api url'>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
{% include 'RecordEvent/includes/EntryDropdown.html' %}
</ul>
</form>
amd in views.py access with
request.post[<name>]
to post via ajax
$('ul li').click(function(){
$.ajax({
url: <api url>,
type:'post',
data:{<name>:$(this).html()},
})