How can Javascript or jQuery access my Django Models? - django

I have a little bit of jQuery on my page which needs to access one of my Django Models. Basically it's a form autocomplete, and it needs to look up values in my database.
I understand how to get values into a Django Template, but getting them into some Javascript code is confusing.
Is this possible? How can it be done?
Thank you.

This link has everything you need. The code is properly written and easy to understand. You can use the values of your model/table to be auto populated in the input field. Check from this link.
def get_Datas(request):
if request.is_ajax():
q = request.GET.get('term', '')
Datas = DataModel.objects.filter(short_name__icontains = q )[:20]
results = []
for Data in Datas:
Data_json = {}
Data_json['value'] = Data.short_name
results.append(Data_json)
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)
And use this in template,
<link rel="stylesheet" href="http://code.jquery.com/ui/1.8.18/themes/base/jquery-ui.css" type="text/css" media="all" />
<div class="ui-widget">
<label for="datas">datas: </label>
<input id="datas">
</div>
And the script would be:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript">
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
<script>
$(function() {
$("#datas").autocomplete({
source: "/get_Datas/",
minLength: 1,
});
});
</script>

Related

How can i send a post request using vue to django without getting a 403 error?

Im trying to send information using a post request of Vue, but every time i try i get an error 403 58
my django service is ok , i think that the problem is for the csrf token but i dont know how to send it with vue
var vue = new Vue({
el:"#app",
data: {
nombre:"",
apellido:"",
password:""
},
methods:{
enviar:function () {
data = {
"nombre":this.nombre,
"apelldio":this.apelldio,
"password":this.password
};
this.$http.post("http://localhost:8000/usuarios\\",data).then(function (data, status, request) {
if(status ==200){
console.log(data);
}
},function () {
console.log("Error");
});
}
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://bootswatch.com/4/flatly/bootstrap.min.css">
</head>
<body>
<h1>Insertar un nuevo usuario </h1>
<table id = "app">
<tr><td>Nombre:</td><td><input type="texte" class="form-control" v-model="nombre"></td></tr>
<tr><td>Apellido:</td><td><input type="texte" class="form-control" v-model = "apellido"></td></tr>
<tr><td>Password:</td><td><input type="texte" class="form-control" v-model="password"></td></tr>
<tr> <td> <button type="button" id = "enviar" class="btn btn-info" #click="enviar">Enviar</button></td></tr>
</table>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.1.13/vue-resource.min.js"></script>
{% csrf_token %}
<!-- here goes the scripts of vue and vue resource!>
You could use a method that involves fetching the csrf token with javascript and then passing it to the POST request as a header as mentioned here in Django documentation. In that link there is also examples about fetching the csrf token value.
Also, if the endpoint does not require this kind of protection you can disable it like in this example.
You can use something like this:
{% csrf_token %}
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.1.13/vue-resource.min.js"></script>
<script>
var csrf = document.querySelector('[name="csrfmiddlewaretoken"]').value;
Vue.http.interceptors.push(function (request, next) {
request.headers['X-CSRF-TOKEN'] = csrf;
next();
});
// Or maybe
Vue.http.headers.common['X-CSRF-TOKEN'] = csrf;
</script>
You can also use it like this, for example:
<script>
var csrf = '{{ csrf_token }}';
Vue.http.headers.common['X-CSRF-TOKEN'] = csrf;
// Or other way
// Vue.http.interceptors.push(...);
</script>
Note: I'm no django developer but gave you the basic idea, so check the doc for more info.

django update time variable in template

What are the options (best way) to update a value of a variable in a template?
template:
<div class="time-container">
{{ time }}
</div>
view:
def index(request):
now = datetime.now()
context = {
'time': now,
}
return render(request, 'times/index.html', context)
I would like to show an actual time (django instance synchronized from ntp) updated every seconds. Should I use a websockets?
Use JavaScript. Here's an example using jQuery and Moment.js:
<!-- this div will contain time -->
<div class="time-container"></div>
...
<!-- include required js libraries -->
<script src="path/to/jquery.js"></script>
<script src="path/to/moment.js"></script>
<!-- now the actual js code to show time -->
<script>
function updateTime(){
$('.time-container').html(moment().format('h:mm:ss'));
};
updateTime();
setInterval(function(){
updateTime();
},1000);
</script>

How to hook up Google Maps to GeoDjango?

GeoDjango docs don't tell anything about hooking up GMap and I don't understand what's going on.
models.py:
from django.contrib.gis.db import models
class Location(models.Model):
name = models.CharField(max_length=100)
coords = models.PointField(srid=4326, blank=True, null=True)
forms.py:
from django.contrib.gis import forms
class LocationForm(forms.ModelForm):
class Meta:
model = Location
fields = ['coords', 'name']
In the add_location.html such code was automatically generated for 'coords':
<div id="div_id_coords" class="form-group">
<div class="controls ">
<div id="id_coords_div_map">
<div id="id_coords_map"></div>
<span class="clear_features">
Delete
</span>
<textarea id="id_coords" class="vSerializedField required" cols="150" rows="10" name="coords"></textarea>
<script type="text/javascript">
var map_options = {};
var options = {
geom_name: 'Point',
id: 'id_coords',
map_id: 'id_coords_map',
map_options: map_options,
map_srid: 4326,
name: 'coords'
};
var geodjango_coords = new MapWidget(options);
</script>
</div>
</div>
</div>
In my js file I am trying to get coordinates of marker into my model:
var mapOptions = {...};
map = new google.maps.Map($('#id_coords_map')[0], mapOptions);
map.addListener('click', function(e){
placeMarker(e.latLng, map);
var position = marker.getPosition();
});
var marker;
function placeMarker(latLng, map) {
marker = new google.maps.Marker({...});
return marker
}
But it doesn't work. It even doesn't come to getting coordinates because I get the error in the chrome console (when I push button Add location at my form):
Uncaught ReferenceError: MapWidget is not defined
related to the line:
var geodjango_coords = new MapWidget(options);
And as validation error at the form field COORDS I can see - "No geometry value provided"
I guessed that something is wrong with connecting GMap and checked what widget was in COORDS field (via self.fields['coords'].widget in the __init__ of ModelForm) and it turned out that it was OpenLayers widget.
What should I do to get GMap as widget and get marker's coords saved in the instance?
P.S. HEAD content at the page (it is about connecting to google maps):
<script type="text/javascript" charset="UTF-8" src="https://maps.googleapis.com/maps-api-v3/api/js/25/5/intl/ru_ALL/common.js"></script>
<script type="text/javascript" charset="UTF-8" src="https://maps.googleapis.com/maps-api-v3/api/js/25/5/intl/ru_ALL/map.js"></script>
<script type="text/javascript" charset="UTF-8" src="https://maps.googleapis.com/maps-api-v3/api/js/25/5/intl/ru_ALL/util.js"></script>
<script type="text/javascript" charset="UTF-8" src="https://maps.googleapis.com/maps-api-v3/api/js/25/5/intl/ru_ALL/onion.js"></script>
<script type="text/javascript" charset="UTF-8" src="https://maps.googleapis.com/maps-api-v3/api/js/25/5/intl/ru_ALL/stats.js"></script>
<script type="text/javascript" charset="UTF-8" src="https://maps.googleapis.com/maps-api-v3/api/js/25/5/intl/ru_ALL/controls.js"></script>
<script type="text/javascript" charset="UTF-8" src="https://maps.googleapis.com/maps-api-v3/api/js/25/5/intl/ru_ALL/marker.js"></script>
adding {{ form.media }} into HEAD has taken away the error 'Uncaught ReferenceError: MapWidget is not defined' from the Chrome console.. but it didn't solve the problem - please, look at -
GeoDjango Google Maps - error - No geometry value provided

typeahead autocomplete for Django

base.html
<html lang=en>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="/media/js/autocomplete.css">
<script type="text/javascript" src="/media/js/jquery-1.2.1.js"></script>
<script type="text/javascript" src="/media/js/dimensions.js"></script>
<script type="text/javascript" src="/media/js/autocomplete.js"></script>
{% block extra_css %}{% endblock extra_css %}
<title>{% block title %}books are social{% endblock title %}</title>
</head>
<body>
{% block body %}
{% endblock body %}
</body>
</html>
and the smaller template:
<script type="text/javascript" >
$(function(){
setAutoComplete("bookSearchField", "bookResults", "/lookup/?query=");
});
</script>
<label for="bookSearchField">Book: </label>
<input type="text" id="bookSearchField" name="bookSearchField">
urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('project.app.views',
(r'^/lookup/$', 'book_lookup'),
)
models.py
class Book(models.Model):
name = models.CharField(max_length=200)
views.py
from django.utils import simplejson
from django.http import HttpResponse
from project.app.models import Book
def book_lookup(request):
# Default return list
results = []
if request.method == "GET":
if request.GET.has_key(u'query'):
value = request.GET[u'query']
# Ignore queries shorter than length 3
if len(value) > 2:
model_results = Book.objects.filter(name__icontains=value)
results = [ {x.id :x.name,} for x in model_results ]
json = simplejson.dumps(results)
return HttpResponse(json, mimetype='application/json')
so is there any tutorial/solution to create bootstrap typeahead for elagent and responsive .
<input id="book_lookup" class="search-query typeahead" data-items="4" type="text"
placeholder="Select here....">
Edited:
<script type="text/javascript">
var typeahead_data = [];
function get_client_names() {
$.ajax({
url: "/lookup/?query=",
success: function (data) {
$.each(data, function (key, value) {
typeahead_data.push(value.toString());
});
// assign the array to my typeahead tag
$('.typeahead').typeahead({
source: typeahead_data,
});
}
});
}
$(function () {
get_client_names();
});
</script>
need something like
$("#book_lookup").tokenInput([{"id": 1, "name": "ddddd"},{"id": 2, "name": "ddffddd"}],{preventDuplicates: true,
hintText: "Type book name here...",
validateInputAjax: true,
validateInputObjectType: "book name",
validateInputNewObjectLink: function (value) {
$('#book_lookup').tokenInput(
'add', {'id': value, 'name': value});
return true;
},
validateInput: function (value) {
$.post("/lookup/", {validate_field_name: value},
function(data){
if (data.valid) {
$("#book_lookup").tokenInput('valid', value);
} else {
$("#book_lookup").tokenInput('invalid', value, 'is not a valid Book name');
};
});
}});
});
how to change data-source to book_lookup json view ?
I have used Bootstrap's typeahead before and what I did was create a method to get the dictionary via Ajax like this:
<script type="text/javascript">
var typeahead_data = [];
function get_client_names() {
$.ajax({
url: "/lookup",
success: function (data) {
$.each(data, function (key, value) {
typeahead_data.push(value.toString());
});
// assign the array to my typeahead tag
$('.typeahead').typeahead({
source: typeahead_data,
});
}
});
}
$(function () {
get_client_names();
});
</script>
The tag element is like this:
<input id="book_lookup" class="search-query typeahead" data-items="4" type="text"
placeholder="Select here....">
And basically the rest of your code is ok.
Note that here you're doing an ajax request (this requeires jquery) to the /lookup/ view which in turn returns a json object, that should look like this: [name1,name2,name3...]. You can test if the view is working ok by just accessing the view through the explorer like this: /lookup/ and if you see the dictionary displaying correctly there, the server side is ok.
Hope this works for you!
In Paulo's answer, he just has a static list of items to search from, that is why he calls the ajax on load, and gets the list and adds it to the source.
In your case, I think, you need to query whatever the user types, and send it to the server. This can be done by adding the function param in data-source, which gets 2 arguments, query and a callback.
Check here

url should not change on submitting a form

i have this Django application in which when user request for "localhost:8000/time/ ,it is shown html form input.html.
<head>
<!-- paste this in your footer -->
<script type="text/javascript">
$(document).ready(function() {
$('#myForm').submit(function() { // catch the form's submit event
$.ajax({ // create an AJAX call...
data: $(this).serialize(),
type: $(this).attr('POST'), // "post"
url: $(this).attr('/poi/'), // "/poi/"
success: function(response) {
// do something here
}
});
return false;
});
});
</script>
<!-- add jquery or it won't work -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
</head>
<body>
<form action="/poi/" method = "post">
<!---------
first name :<input type ="text" name ="fname">
last name:<input type ="text" name ="lname">
------>
enter a days :<input type ="text" name ="days">
<br>
<input type=submit name="submit" onclick="submit_function(); return false;">
</form>
</body>
when form is submitted user sees response.html page and URL is changed to "localhost:8000/poi/ is shown having
urls.py
urlpatterns = patterns('',
(r'^hello/$', hello),
('^time/$', current_datetime),
('^poi/$', next_datetime),
)
views.py
def current_datetime(request):
return render_to_response('input.html')
def next_datetime(request):
now = datetime.datetime.now()
now_day = now.day
now_month = now.month
now_year = now.year
return render_to_response('response.html', {'now_day': now_day, 'now_month'}}
now i have to do same thing but the url should not change from "localhost:8000/time/ to "localhost:8000/poi/
but it should be "localhost:8000/time/
how to accomplish that?
You have to use ajax to accomplish this
With jquery it would look something like
<form id="myForm"> ... </form> <!-- add an id to your form -->
<!-- paste this in your footer -->
<script type="text/javascript">
$(document).ready(function() {
$('#myForm').submit(function() { // catch the form's submit event
$.ajax({ // create an AJAX call...
data: $(this).serialize(),
type: $(this).attr('method'), // "post"
url: $(this).attr('action'), // "/poi/"
success: function(response) {
// do something here
}
});
return false;
});
});
</script>
<!-- add jquery or it won't work -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
and it should work out of the box
this is with an anonymous function, but you can put the code inside a named one and then add it to the button:
<input type="submit" onclick="submit_function(); return false;" />
it's basically the same