I'm new to Django and AJAX and I'm trying to send the ID of a dropdown list to the Django View with an ajax POST. This ID is then used in a queryset filter to return with AJAX the row, based off the ID. I'm getting stuck with applying the filter to the query set, as it seems to be posting the ID and then a variable with None. When I print to console the variable sent in the POST I get the ID, followed by none, e.g.:
1748
None
My HTML is:
<select id="drugSet">
{% for dose in dose_set %}
<option id="{{ dose.pubmed_id }}">{{ dose.drug_name }}</option>
{% endfor %}
</select>
<span id="drugName"></span>
Javascript:
function NeedDrugInformation() {
var elementID = document.getElementById("drugSet");
var strUser = elementID.options[elementID.selectedIndex].id;
$.ajax({
type: "POST",
url: "drugsanddoses/",
dataType: "text",
async: true,
data: { csrfmiddlewaretoken: '{{ csrf_token }}', drugID: strUser },
});
$.ajax({
type: "GET",
url: "drugsanddoses",
dataType: "text",
async: true,
data: { csrfmiddlewaretoken: '{{ csrf_token }}' },
success: function (json) {
$('#drugName').html(json.drugInfo);
// $('.ajaxProgress').hide();
}
})
}
views.py:
def drugsanddoses(request):
drugIdentifier = request.POST.get('drugID')
print(drugIdentifier)
drugInfo = RiskCalculator.objects.values('drug_name', 'l_dose', 'h_dose', 'risk', 'pubmed_id', 'updated')
response_data = {}
try:
response_data['drugInfo'] = str(drugInfo)
except:
response_data['result'] = 'No details found'
response_data['message'] = 'There is currently no information in the database for this drug.'
return HttpResponse(json.dumps(response_data), content_type="application/json")
You're making two Ajax requests; one a POST, where the ID is present, and one a GET, where the ID is absent so it prints None. I don't really understand why you're making two requests, but that is what you are doing.
Related
I have a system that allows an admin to add managers to a campaign from a table. The table looks something along the lines of
<tr>
<td>Checkbox</td>
<td>Last name, First name</td>
<td>Employee Id #</td>
</tr>
Currently, when the "Add Manager" button is hit, I pass the manager's id and a "checked" value using this function
<script>
function addMgrs(){
dict = {}
$('#potentialReviewers tr').each(function() {
var userPid = $(this).find('td').eq(2).text()
var addMgrBox = $(this).find('.addMgrBox').attr('value')
if (addMgrBox == 'checked') {
dict[userPid] = addMgrBox }
// Create the Post request, pass the csrf_token in the header of the request
$.ajax({
url: '/campaign-view/' + '{{ campaign.id }}' + "/",
type: 'POST',
headers: {'X-CSRFtoken': '{{ csrf_token }}'},
data: dict,
dataType: 'json'
})
})
}
</script>
What this does is iterate through the table, build the JSON response and pass it back to the Django view to do the backend processing. My problem is this, for each row it sends a POST request and that drastically increases the time it takes for the process to complete. I'd like it to build the entire dictionary prior to sending the response, but just can't wrap my head around how to do that. Any help would be appreciated.
Alright, so as n1md7 pointed out in the comments, I simply needed to move the AJAX request outside of the loop. Here is what the code block looks like now:
<script>
function addMgrs(){
dict = {}
$('#potentialReviewers tr').each(function() {
var userPid = $(this).find('td').eq(2).text()
var addMgrBox = $(this).find('.addMgrBox').attr('value')
if (addMgrBox == 'checked') {
dict[userPid] = addMgrBox }
})
// Create the Post request, pass the csrf_token in the header of the request
$.ajax({
url: '/campaign-view/' + '{{ campaign.id }}' + "/",
type: 'POST',
headers: {'X-CSRFtoken': '{{ csrf_token }}'},
data: dict,
dataType: 'json'
})
}
</script>
As you can see, I now close the loop prior to making the request and it went from a 4+ minute process to almost instantaneous. Thank you n1md7
Having a tough time with this. I'm sending some data via Ajax to my Flask server route where it is being processed, with hopes to then render a new template with the processed data. The data seems to be flowing fine from my Javascript to my Flask server. (I am using JSGlue for Flask.url_for.) But as soon as it gets to "return render_template" it just dies. I get no traceback errors or anything. I've tried print() and console.log all over the place to get some kind of idea of what is killing it, but so far I've come up empty. Am I missing something obvious?
mypage.js
let c_list = [1,2,3....];
$.ajax({
url: Flask.url_for('get_genres'),
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(c_list),
success: function (data) {
console.log(data);
}
})
init.py
#app.route('/get_genres', methods=["GET", "POST"]
def get_genres():
if request.method == "POST":
categories = request.json
c = Querybuilder()
genres = c.genres_from_c(categories)
return render_template("genres.html", genres=genres)
index.html
<head>
{{ JSGlue.include() }}
</head>
<body>
{% block body %}
{% endblock %}
</body>
genres.html
{% extends "index.html" %}
{% block body %}
<div class="genre_list">
{% for genre in genres %}
<a href="#" src="{{ genres[genre] }}" class="unclicked" onclick="toggleClicked(this)">
<p>{{ genre }}</p></a>
{% endfor %}
NEXT
</div>
{% endblock %}
After A LOT of digging around, I finally managed to find a solution to this issue. Adding a success function to the ajax call that redirects to another route.
mypage.js
$.ajax({
url: Flask.url_for('genre_picks'),
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(genres),
success: function(response) {
window.location.href = response.redirect
}
});
init
#app.route('/genre_picks', methods=["POST", "GET"])
def genre_picks():
if request.method == "POST":
genres = request.json
return jsonify({'redirect': url_for("example", path=genres)})
#app.route('/example/<path>')
def example(path):
genres = path
return render_template("example.html", genres=genres)
I'm developing personal spending diary and I faced the problem.
For better UX I need to make process of adding new items without reloading page .
I make single ajax form but I need two .
I'm trying to solve this problem for 3 days .
Have anybody any suggestions ?
Here is my
forms.py
class AddIncome(forms.ModelForm):
class Meta:
model = Income
fields = ( 'title','value',)
class AddExpence(forms.ModelForm):
class Meta:
model = Expence
fields = ( 'title_exp','value_exp',)
Here is full
views.py
def dashboard(request):
if request.method == 'POST':
if request.is_ajax():
addincome = AddIncome(request.POST)
if addincome.is_valid():
addincome.cleaned_data
addincome.save()
latest = Income.objects.latest('id').id
income_object = model_to_dict(Income.objects.get(pk=latest))
return JsonResponse({'error': False, 'data': income_object})
else:
print(addincome.errors)
return JsonResponse({'error': True, 'data': addincome.errors})
else:
error = {
'message': 'Error, must be an Ajax call.'
}
return JsonResponse(error, content_type="application/json")
if request.method == 'POST':
if request.is_ajax():
addexpence = AddExpence(request.POST)
if addexpence.is_valid():
addexpence.cleaned_data
addexpence.save()
latest = Expence.objects.latest('id').id
expence_object = model_to_dict(Expence.objects.get(pk=latest))
return JsonResponse({'error': False, 'data': expence_object})
else:
print(addexpence.errors)
return JsonResponse({'error': True, 'data': addexpence.errors})
else:
error = {
'message': 'Error, must be an Ajax call.'
}
return JsonResponse(error, content_type="application/json")
else:
addincome = AddIncome()
addexpence = AddExpence()
income = Income.objects.order_by('-date').filter(is_published=True)
expence = Expence.objects.order_by('-date').filter(is_published=True)
data = {
'addincome_html': addincome,
'addexpence_html': addexpence,
'income':income,
'expence':expence
}
return render(request, template_name='main/dashboard.html', context=data)
Here is
Page forms
<form method="POST" name="create_incomefrm" id="create_incomefrm" action="{% url 'create_income_record' %}">
{% csrf_token %}
{{ addincome_html.as_p }
<button type="submit" id="popup-button-2" class="dashboard__popup-button"
name="createincomefrmbtn">Add <span>→</span></button>
</form>
<form method="POST" name="create_expencefrm" id="create_expencefrm" action="{% url 'create_expence_record' %}">
{% csrf_token %}
<div class="dashboard__popup-2" id="dashboardpopup-4">
{{ addexpence_html.as_p }}
<button id="popup-button-3" name="createexpencefrmbtn" class="dashboard__popup-button">Add<span>→</span></button>
</form>
Here is
ajax forms
$('#create_incomefrm').submit(function (e) {
e.preventDefault();
var formData = {
'title': $('#id_title').val(),
'value': $('#id_value').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
contentType: 'application/x-www-form-urlencoded',
encode: true,
};
$.ajax({
type: 'POST',
url: 'create/',
data: formData,
dataType: 'json',
}).done(function (data) {
//code
});
});
$('#create_expencefrm').submit(function (e) {
e.preventDefault();
var formData = {
'title_exp': $('#id_title_exp').val(),
'value_exp': $('#id_value_exp').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
contentType: 'application/x-www-form-urlencoded',
encode: true,
};
$.ajax({
type: 'POST',
url: 'create_exp/',
data: formData,
dataType: 'json',
}).done(function (data) {
//code
});
});
Solution
Create a hidden input for both form having same name/id. e.g. HTML
<!--form-1-->
<input type='hidden' name='form_type' value='income'>
<!--form-2-->
<input type='hidden' name='form_type' value='expense'>
Update JavaScript accordingly.
And then on your view catch each form by -
# form-1
if request.method == 'POST' and request.POST['form_type'] == 'income':
# rest of your code
# form-2
if request.method == 'POST' and request.POST['form_type'] == 'expense':
# rest of your code
I get a validate error when I create a form with an empty select field:
area_sp = forms.ChoiceField(widget=forms.Select(attrs={'class': 'form-control', 'id':'area_select'}))
then I populate the select in the template using ajax:
$.ajax({
url: '/endpoint/load_areas/',
type: 'post',
dataType: 'json',
data: {
'postcode': postcode
},
headers: {
'X-CSRFToken': "{{ csrf_token }}"
},
success: function (data) {
var ret = JSON.parse(data.result);
for (x in ret) {
$("#area_select").append(new Option(x, ret[x]));
}
},
error: function(data) {
alert("error");
}
});
Finally, when I submit the form I get the following error:
area_sp: Select a valid choice. 26835 is not one of the available choices.
Any idea?
Looks like you've just forgotten to define the valid choices. You have to tell the ChoiceField, otherwise you'll get a ValidationError. The docs about ChoiceField:
Validates that the given value exists in the list of choices.
So just set the choices attribute to whatever the form shall accept:
area_sp = forms.ChoiceField(
widget=forms.Select(
attrs={'class': 'form-control', 'id':'area_select'}
),
choices=[(value1, repr1), (value2, repr2), ...]
)
I have a list of brands and categories. One brand can have multiple categories.
{% for brand in brands %}
<li><input type="radio" value="{{brand.title}}" name="brand">{{brand.title}}</li>
{% endfor %}
{% for category in categories %}
<li><input type="checkbox" value="{{category.title}}" name="category" > {{category.title}}</li>
{% endfor %}
<input type="submit" value="submit" id="brand_category">
<script>
var parameter = [];
var brand = [];
var category = [];
$('#brand_category').click(function(event) {
$("input:checkbox[name=category]:checked").each(function(){
if ($(this).prop("checked", true)) {
category.push($(this).val())
}
});
parameter.push({
brand : $("input[type='radio']:checked").val(),
category: category
})
var json = JSON.stringify(parameter);
$.ajax({
type: "post",
url: "{% url 'seller_details' %}",
data: {
'parameter[]' : json ,
csrfmiddlewaretoken: '{{csrf_token}}'
},
contentType: 'application/json; charset=utf-8',
dataType:"json",
success: function(data) {
$('#loading-image').hide();
},
error: function(response, error) { }
});
});
</script>
I tried to send brand and category from the above script but it retains old data in the arrays brand, category and parameter. Is this the correct way to send data for the above scenario?
It sounds like you're defining the category array outside of the click handler and you're not clearing it's values between clicks. Also note that the if statement in the each block is redundant as the selector is only retrieving elements which are checked.
To solve the issue you can either change the code so that the array is defined inside the handler:
$('#brand_category').click(function(event) {
var category = [];
$("input:checkbox[name=category]:checked").each(function(){
category.push($(this).val());
});
// rest of your code...
});
Alternatively you can generate the array from scratch on each click:
var category = [];
$('#brand_category').click(function(event) {
category = $("input:checkbox[name=category]:checked").map(function() {
return this.value;
}).get();
// rest of your code...
});