Ajax call from django template - django

I have a django template which extends the base template that has code to load jquery in it. This template has a simple text box and I wanted to fetch the object through ajax.
{% extends 'base.html' %}
{% block content %}
<form id="ajaxform">
<input type="text" name="first_name" id="name" />
<input type="submit" value="Submit" />
</form>
<div id="dataDiv">
</div>
<script>
$('#ajaxform').submit(function(){
console.log('Form submitted');
$.get('{% url get_ajax_data %}', $(this).serialize(),function(data){
$('#dataDiv').text(data);
})
return false;
});
</script>
{% endblock %}
In this template, I tried to make ajax call to the get_ajax_data url and in the corresponding view I simply returned text as return HttpResponse('Ajax respose'). But this does not seem to work and the form gets submitted while I have returned false. I am not sure where I missed.

Till was on to the answer, Common practice is to initialize the submit() handler. This is done by setting it when the page is ready. Currently you have it to submit the form the regular way, it's not even registering with your javascript. To fix it you could write:
$(document).ready(function() {
$('#ajax_form').submit(fun // the rest of your code here.
});

jQuery event handlers fail silently if there's an error in them. Check for the obvious things like missing semicolons, etc. Make sure everything is valid in the event handler and it should work.

Related

How to use django-markdownx in my view in similar way to admin?

I'm stuck using django-markdownx to automatically update page and to submit changes.
I followed this question and answer and managed to get django-markdownx working in admin, and within my view. However in my view editing the textarea does not automatically update the page.
The admin page with django-markdownx is exactly what I want, updating the textarea updates the page, but not the underlying database field until you hit save.
So I then tried to rip out the admin code into my own view.
In my view/template I have a form, textarea similar to admin one. I also included "/static/markdownx/js/markdownx.js" and set my form to mostly be similar to the admin page:
<form method="POST" action="">{% csrf_token %}
<div class="markdownx">
<textarea name="myfield" rows="10" cols="40" required="" data-markdownx-upload-urls-path="/markdownx/upload/" data-markdownx-editor-resizable="" class="markdownx-editor" id="id_myfield" data-markdownx-urls-path="/markdownx/markdownify/" data-markdownx-latency="500" data-markdownx-init="" style="transition: opacity 1s ease;">
{{ note.myfield }}
</textarea>
</div>
<div class="markdownx-preview">
{{ note.formatted_markdown|safe }}
</div>
</form>
This didn't work.
I see periodically there is requests to /markdownx/markdownify/ when you edit in admin, but not mine. I'm not sure if I should aim to do the same or just do some timed javascript page refresh and pass all the data from within my form back to my view to then re-render the page again.
I can't quite get my head around the django-markdownx documentation.
UPDATE:
The Documentation seems to suggest that a call to MarkdownX() should do the initialisation.
<script src="/static/markdownx/js/markdownx.js"></script>
...
<script type="text/javascript">
let parent = document.getElementsByClassName('markdownx');
let md = new MarkdownX( element, element.querySelector('.markdownx-editor'), element.querySelector('.markdownx-preview'));
</script>
But when I try this I get.
Uncaught ReferenceError: MarkdownX is not defined
Also I don't see any initialisation like this within the admin page.
Is there an example of using the django-markdownx in your own views similar to the usage within admin?
Thanks
LB
The following is a broken solution.
The correct method would be to use the MarkdownX's built-in Javascript, but I just can't get it to work, yet. So, I wrote my own. It may be of use to others.
In template html, include js.cookie.min.js in order to get the django csrftoken. Then a callback function which will be called when a change is made to the textarea. We then update the preview div with HTML code we received back from MarkdownX's markdownify call.
<script src="https://cdn.jsdelivr.net/npm/js-cookie#2/src/js.cookie.min.js"></script>
...
<script type="text/javascript">
function myMDFunc( elem ) {
input = elem.value;
var csrftoken = Cookies.get('csrftoken');
$.ajax(
{
type: "POST",
url: "/markdownx/markdownify/",
data: { CSRF: csrftoken, csrfmiddlewaretoken: csrftoken, content: input}
})
.done(function(data, status){
document.getElementById("markdownx-preview").innerHTML = data;
});
}
</script>
Still in the template html, in the form, call this function both for onchange and onkeyup.
<form method="POST" action=""> {% csrf_token %}
{{ note.title }}
<div class="markdownx">
<textarea onchange="myMDFunc(this)" onkeyup="myMDFunc(this)" cols="60" rows="5" name="text" >
{{ note.myfield }}
</textarea>
</div>
<div class="markdownx-preview" id="markdownx-preview">
{{ note.formatted_markdown|safe }}
</div>
<input type="submit" id="submit" name="submit">
</form>
In summary, a change to the textarea means we invoke the 'onchange' or 'onkeyup', which calls myMDFunc. Then myMDFunc does an ajax call with data which is the raw MarkDown code, the response to this call is the pretty HTML data. The callback within myMDFunc updates the preview with that pretty HTML.
It kinda works. I'm sure the real MarkdownX code will handle drag'n'drop of images and pacing the ajax calls to be nice to the server.

Display Form Field based on other Fields within the Django Form

I am trying to create a way to only display certain fields within a django form based on the bound data of another field within that same form. I'm familiar with the idea of form.field.bound_type but I'm not sure how to continually check for state change on a field in a form and update the other field accordingly. Something like if you were filling out an application and it asked if you've committed a crime, if you click yes then a details text area pops up.
I'm using:
Django 1.8.4
Bootstrap3 6.6.2
As it pertains to this question. Here is what I've currently got with the field values edited for work protection. It does SORT of work. Meaning the form is fine, the if statement works initially but it doesn't reevaluate the if once the specified field has changed.
<form action= "/send_email/" method="post" class='col-sm-5'>
{% csrf_token %}
{% bootstrap_field form.field_one%}
{% bootstrap_field form.field_two%}
{% bootstrap_field form.field_three%}
{% if form.field_three.bound_data == "A Value" %}
{% bootstrap_field form.field_four%}
{% endif %}
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "glyphicon glyphicon-ok-circle" %} Submit
</button>
{% endbuttons %}
</form>
Solution:
With Birdie's help I was able to figure out the solution. For anyone who has hit this same Django related problem here is how you add or remove fields based on another field in the same form.
<script>
// function that hides/shows field_four based upon field_three value
function check_field_value(new_val) {
if(new_val != 'A value') {
// #id_field_four should be actually the id of the HTML element
// that surrounds everything you want to hide. Since you did
// not post your HTML I can't finish this part for you.
$('#field_four').removeClass('hidden');
} else {
$('#field_four').addClass('hidden');
}
}
// this is executed once when the page loads
$(document).ready(function() {
// set things up so my function will be called when field_three changes
$('#field_three').change( function() {
check_field_value(this.value);
});
});
</script>
<form action= "/send_email/" method="post" class='col-sm-5'>
{% csrf_token %}
{% bootstrap_field form.field_one%}
{% bootstrap_field form.field_two%}
<div id="field_three">{% bootstrap_field form.field_three%}</div>
<div id="field_four">{% bootstrap_field form.additional_notes %}</div>
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "glyphicon glyphicon-ok-circle" %} Submit
</button>
{% endbuttons %}
</form>
You cannot do this within the template because the template is executed on the server side, but the user interaction occurs on the client side.. in the browser. This must be done in javascript and run in the browser.
Here is an example of jQuery code which does this. I did not test it so it may need tweaking, but this should get you in the right direction.
You will need to look at your HTML to determine the id of the element you actually want to hide() and show(). Normally you would have some kind of HTML element (eg. a DIV) surrounding both the field or fields you want to hide as well as the label(s).. and you would hide everything at once by hiding the element which contains all the fields, rather than each individual field itself.
If you add the HTML surrounding field_four to your question, I will update the answer to work with what you've got...
<script>
// Ideally this script (javascript code) would be in the HEAD of your page
// but if you put it at the bottom of the body (bottom of your template) that should be ok too.
// Also you need jQuery loaded but since you are using bootstrap that should
// be taken care of. If not, you will have to deal with that.
// function that hides/shows field_four based upon field_three value
function check_field_value() {
if($(this).val() == 'A Value') {
// #id_field_four should be actually the id of the HTML element
// that surrounds everything you want to hide. Since you did
// not post your HTML I can't finish this part for you.
$('#id_field_four').hide();
} else {
$('#id_field_four').show();
}
}
// this is executed once when the page loads
$(document).ready(function() {
// set things up so my function will be called when field_three changes
$('#id_field_three').change(check_field_value);
// set the state based on the initial values
check_field_value.call($('#id_field_three').get(0));
});
</script>
Thanks all for the contribution, but I could not get the code above work. This is my solution:
<script>
function hideField() {
check = document.getElementsByName("put your field name here")[0].value;
response = document.getElementById("put your id here");
if (check === "Open") {
response.style.display = "none";
}else{
response.style.display = "block";
}
}
</script>
The key is to figure out Id for the field you want to hide, and name for the field you check. I did NOT use DIV container to assign the id and the name, but inspected rendered HTML page with developer tools in the browser. Let me know if you have questions or want more detailed explanation.
I found this question very interesting. I have updated it with bootstrap 4.0v, with the following script, I hope it can help someone:
<script>
// function that hides/shows field_four based upon field_three value
function check_field_value(new_val) {
if(new_val != 'A value') {
// #id_field_four should be actually the id of the HTML element
// that surrounds everything you want to hide. Since you did
// not post your HTML I can't finish this part for you.
$('#field_four').removeClass('d-none');
} else {
$('#field_four').addClass('d-none');
}
}
// this is executed once when the page loads
$(document).ready(function() {
// set things up so my function will be called when field_three changes
$('#field_three').change( function() {
check_field_value(this.value);
});
});
</script>
<form action= "/send_email/" method="post" class='col-sm-5'>
{% csrf_token %}
{% bootstrap_field form.field_one%}
{% bootstrap_field form.field_two%}
<div id="field_three">{% bootstrap_field form.field_three%}</div>
<div id="field_four">{% bootstrap_field form.additional_notes %}</div>
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "glyphicon glyphicon-ok-circle" %} Submit
</button>
{% endbuttons %}
</form>

How to properly use the django built-in login view

I'm just getting started with Django, and I'm trying to use built-in features as much as possible. As such, for user login, I'm using the built-in login view, and assigning it to the base url of my site:
urlpatterns=patterns('django.contrib.auth.views',
url(r'^/$','login',{'template':'mytemplate.html'}),
mytemplate.html looks something like this:
<!DOCTYPE html>
<html>
<body>
{%if form.errors %}
<p> Invalid username/password combination, please try again </p>
{% endif %}
<h1>Welcome to My Site!</h1>
<form action="{% url django.contrib.auth.views.login %}" method="post">
{% csrf_token %}
{{form.username.label_tag}}{{form.username}}
{{form.password.label_tag}}{{form.password}}
<input type="submit" id="submit" name="submit" value="Sign in" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
forgot username/password<br />
new user
</body>
</html>
my problem is, the template doesn't appear to be getting passed any of the context it's supposed to. In the rendered HTML, all of my variable tags simply disappear (i.e. rather than being replaced by the appropriate values, thay are replaced with nothing).
I imagine I'm skipping some critical step, but I can't figure out what it is. Any ideas?
You need to change from 'template' to 'template_name'
urlpatterns=patterns('django.contrib.auth.views',
url(r'^/$','login',{'template_name':'mytemplate.html'}),
https://docs.djangoproject.com/en/1.4/topics/auth/#django.contrib.auth.views.login
Try removing the template name from your url configuration. Django will then fall back to a standard template, that way you can see if you screwed up the template somehow or if something else is wrong.
My next guess would be to check your settings for the TEMPLATE_CONTEXT_PROCESSORS. If you have defined any of them, be sure to include
"django.contrib.auth.context_processors.auth",
If you haven't defined any, django will use a standard tuple, which allready includes the auth processor.

how to access jQuery.ajax() get parameters in Django views

I recently started to learn jQuery and right now I am playing around with .ajax() function.
I cannot figure out how to access the get parameters in Django.
My code looks like:
Jquery & html:
<div id="browser">
<ul>
{% comment %}
Theres a script for each ctg. Each script fades out #astream, fades in #stream_loading and then it should display #astream with new values based on the GET param in ajax call
Prolly it wont work, but first I need to interact with the GET param in my views.py
{% endcomment %}
{% for ctg in ctgs %}
<script type="text/javascript" charset="utf-8">
(function($) {
$(document).ready(function() {
$("#stream_loading").hide()
$("#browse_{{ctg}}").click(function() {
$("#astream").fadeOut()
$("#stream_loading").fadeIn()
$.ajax({
type: "GET",
url: "/{{defo}}/?param={{ctg}}",
success: function() {
$("#stream_loading").fadeOut()
$("#astream").fadeIn()
}
});
});
});
})(jQuery);
</script>
<li><a id="browse_{{ctg}}" title="{{ctg}}">{{ctg}}</a></li>
{% endfor %}
</ul>
</div>
<div id="astream">
{{ajaxGet}} #just to see whats rendered
{% include "astream.html" %}
</div>
<div id="stream_loading">
loading stream, please wait ...
</div>
Django:
#https_off
def index(request, template='index.html'):
request.session.set_test_cookie()
path=request.META.get('PATH_INFO')
defo=path[1:path[1:].find('/')+1]
request.session['defo']=defo
defo=request.session['defo']
# build the stream sorted by -pub_date
import itertools
chained=itertools.chain(
model1.objects.order_by('-pub_date').filter(),
model2.objects.order_by('-pub_date').filter(),
)
stream=sorted(chained, key=lambda x: x.pub_date, reverse=True)
ajaxGet=request.GET.get('param','dummy')
if request.is_ajax():
template='astream.html'
ajaxGet=request.GET.get('param',False)
renderParams={'defo':defo, 'stream':stream, 'ajaxGet':ajaxGet}
return render_to_response(template, renderParams, context_instance=RequestContext(request))
Then I try to show it up in my template
{{ ajaxGet }}
But everytime is rendered as 'dummy'
In firebug I can see get requests with proper key and value.
What do I miss here?
Thanks
There is a frequent gotcha that people often fall into when doing this kind of Ajax, and that is not preventing the default action of the link/button. So your Ajax function never has a chance to fire, and the request that you're seeing in the Django code is caused by the normal page load - which is why is_ajax() is false.
Give the click handler a parameter, event, and call event.preventDefault(); at the end of the function.

Django : writing a template tag that removes content outside of it

I am writing a site, and some pages are requested both with Ajax, or with a normal request. Of course, when requesting with Ajax, I'd like to render a slightly different template. I've tried several methods (A render_block snippet which was a great idea but buggy, using {% include %} to separate the templates while factorizing the code, using {% ifnot request.is_ajax %} to render content, like toolbar or menu, only if not Ajax). So I thought that it would be really cool to do like so :
<div> A menu that should not appear with Ajax </div>
{% ajax %}
<div> The Ajax part </div>
{% endajax %}
<div> A footer that should not appear with Ajax </div>
Then normal request returns :
<div> A menu that should not appear with Ajax </div>
<div> The Ajax part </div>
<div> A footer that should not appear with Ajax </div>
Ajax request :
<div> The Ajax part </div>
However, I don't really now where to start ... I've already written template tags, but never had to do something so complicated ! IS it even possible ?
That sounds like a really confusing way of doing it - I'd definitely stick to:
{% if not request.is_ajax %}
<div> A menu that should not appear with Ajax </div>
{% endif %}
<div> The Ajax part </div>
{% if not request.is_ajax %}
<div> A footer that should not appear with Ajax </div>
{% endif %}
Alternatively, separate out your templates, so that the stuff you want rendered both times is in one template (we'll call this my_ajax_template.html):
<div> The Ajax part </div>
When responding to requests that come from AJAX your view code can just render that template, but when responding to "normal" requests, you could render a template that looked like this:
<div> A menu that should not appear with Ajax </div>
{% include 'my_ajax_template.html' %}
<div> A footer that should not appear with Ajax </div>