Pass javascript variable to views.py - django

I really need some help on this subject, which seems easy, but i cant get myself to figure out the problem.
I understand that using ajax is the best way to pass a variable from a template to a view.
Is what i have done good, or would you recommend i try something different ?
function updateArea(e) {
var data = draw.getAll();
var answer = document.getElementById('calculated-area');
if (data.features.length > 0) {
var area = turf.area(data);
// restrict to area to 2 decimal points
var rounded_area = Math.round(area*100)/100;
answer.innerHTML = '<p><strong>' + rounded_area + '</strong></p><p>square meters</p>';
var convertedData = 'text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
document.getElementById('export').setAttribute('href', 'data:' + convertedData);
document.getElementById('export').setAttribute('download','data.geojson');
} else {
answer.innerHTML = '';
if (e.type !== 'draw.delete') alert("Use the draw tools to draw a polygon!");
}
}
I want to take the area variable and convertedData variable and pass them to a view.
So after some searching and trial and error, here is what I tried to do using Ajax.
When I run this i get no errors, but i get nothing in my database.
template.html
<form id="areaform" method="POST">
{% csrf_token %}
<input type="submit" name="area" value=""/>
</form>
$(document).on('submit', '#areaform',function(e) {
e.preventDefault();
$.ajax({
type: 'POST',
url:'fertisatmap/area',
data:{
name: $('#area').val(),
},
sucess:function(){}
});
});
urls.py
path('fertisatmap/area', fertisat_views.fertisatareaview, name='fertisat-area'),
views.py
def fertisatareaview(request):
if request.method == "POST":
area = request.POST['area']
Fertidb.objects.create(
area = area)
return HttpResponse('')

Related

Django template tag URL is not working in JavaScript

I want to add an edit button and delete image dynamically to table, but it is showing error
Page Not Found at
Request URL: http://127.0.0.1:8000/%7B%25%20url%20'expense-edit'%20expense.id%20%25%7D
here is js file
const searchField = document.querySelector("#searchField");
const tableOutput = document.querySelector(".table-output");
const appTable = document.querySelector(".app-table");
const paginationContainer = document.querySelector(".pagination-container");
tableOutput.style.display = 'none';
const noResults = document.querySelector(".no-results");
const tbody = document.querySelector(".table-body");
searchField.addEventListener('keyup', (e) => {
const searchValue = e.target.value;
if (searchValue.trim().length > 0) {
paginationContainer.style.display = "none";
tbody.innerHTML = "";
fetch("http://127.0.0.1:8000/search-expenses", {
body: JSON.stringify({ searchText: searchValue }),
method: "POST",
})
.then((res) => res.json())
.then((data) => {
console.log("data", data);
appTable.style.display = "none";
tableOutput.style.display = "block";
console.log("data.length", data.length);
if (data.length === 0) {
noResults.style.display = "block";
tableOutput.style.display = "none";
}
else {
noResults.style.display = "none";
data.forEach((item) => {
tbody.innerHTML += `
<tr>
<td>${item.amount}</td>
<td>${item.category}</td>
<td>${item.description}</td>
<td>${item.date}</td>
<td>Edit<img src="{% static 'img/delete.png' %}" width="35" height="35"/></td>
</tr>`;
});
}
});
}
else {
noResults.style.display = "none";
tableOutput.style.display = "none";
appTable.style.display = "block";
paginationContainer.style.display = "block";
}
});
urls.py
from django.urls import path
from . import views
from django.views.decorators.csrf import csrf_exempt
urlpatterns = [
path('', views.home, name="home"),
path('expenses', views.index, name='expenses'),
path('add-expenses', views.add_expenses, name='add-expenses'),
path('edit-expense/<int:id>', views.expense_edit, name='expense-edit'),
path('expense-delete/<int:id>', views.delete_expense, name='expense-delete'),
path('search-expenses', csrf_exempt(views.search_expenses), name='search_expenses'),
path('expense_category_summary', views.expense_category_summary, name="expense_category_summary"),
path('stats', views.stats_view, name="stats"),
path('export_csv', views.export_csv, name="export-csv"),
path('export_excel', views.export_excel, name="export-excel"),
path('export_pdf', views.export_pdf, name="export-pdf"),
]
I want to add a button that has a link to the next page through JavaScript using the Django URL template tag. thanks in advance
When you write {% url 'expense-edit' expense.id %}, you're using a Django-specific "language" called Django template language which means that the mentioned syntax can only be "understood" by Django templates.
What you're doing here is loading a separate JavaScript file in which the Django template syntax simply won't work because when browser comes to the point to evaluate that file, {% url 'expense-edit' expense.id %} will look just another string literal, and not what you would expect to.
It should work if you inline your JavaScript example directly into the Django template.
So there is two possible Hacks to do this:
One is putting the written script in your tenplate file as:
<script type="text/javascript">
const searchField = document.querySelector("#searchField");
const tableOutput = document.querySelector(".table-output");
...
</script>
The issue with this approach is the scope of variables as you may not want to declare things globally so it could be considered an easy approach, but not necessarily the best solution.
So the other solution is to change the name of file from script.js to script.js.html and include in your desired template as :
...
{% include "my_app/script.js.html" %}
Instead of this:
Edit<img src="{% static 'img/delete.png' %}" width="35" height="35"/></td>
Try this way:
Edit
<img src="{% static 'img/delete.png' %}" width="35" height="35"/></td>

How to Post csv file in simple Html into Django api?

I tried post FormData using "angular Js" and then using Directly post html to django api But It Will be failure , Anyone Tried it and Known It Please Tell me your answer it is the full code i tried out :
html:
<form action="http://localhost:55555/collaboratoradmin/test/upload_driver" method="post" enctype="multipart/form-data">
<input type="file" id="file" name="csv_file" accept=".csv"
onchange="angular.element(this).scope().getFileDetails(this)" />
<button type="submit" ng-click="uploadFiles()">upload</button>
Angular Js:
$scope.getFileDetails = function (e) {
$scope.files = [];
$scope.$apply(function () {
var file = e.files[0];
filename = '';
if ('name' in file)
filename = file.name;
else
filename = file.fileName;
});
};
$scope.uploadFiles = function () {
//FILL FormData WITH FILE DETAILS.
// ADD LISTENERS.
var objXhr = new XMLHttpRequest();
objXhr.addEventListener("progress", updateProgress, false);
objXhr.addEventListener("load", transferComplete, false);
// SEND FILE DETAILS TO THE API.
objXhr.open('POST', endpoint + '/collaboratoradmin/test/upload_driver', true);
var fd = new FormData();
fd.append("filename", filename);
fd.append("csv_file", file);
objXhr.send(fd);
}
// UPDATE PROGRESS BAR.
function updateProgress(e) {
if (e.lengthComputable) {
document.getElementById('pro').setAttribute('value', e.loaded);
document.getElementById('pro').setAttribute('max', e.total);
}
}
// CONFIRMATION.
function transferComplete(e) {
alert("Files uploaded successfully.");
}
Django api:
#api_view(['POST'])
def upload_driver(request):
if request.POST and request.FILES:
csvfile = request.FILES['csv_file']
dialect = csv.Sniffer().sniff(codecs.EncodedFile(csvfile, "utf-8").read(1024))
csvfile.open()
reader = csv.reader(codecs.EncodedFile(csvfile, "utf-8"), delimiter=',', dialect=dialect)
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('myproject.myapp.views.list'))
print(list1)

angularjs not responding the GET method

i am relatively new in django and angualarJs.The problem is that angularJs is not responding the get method properly.I have a webpage developed by django where i have a search field.For the execution of search i use a angularJs functionality that is ng-submit and write angularJs code to return value using get method.May be i made a mistake here.you can see my code... here is my template which containing the angularJs also...
<div class="navbar navbar-default " ng-controller="NavCtrl">
<form action="" class="navbar-form navbar-right" ng-submit="search()">
<input class="form-control col-lg-8" type="text" placeholder="Search" ng-model="term"></input>
</form>
</div>
<script>
app.controller("NavCtrl", ['$scope', '$http', '$location', '$q', '$timeout',
function NavCtrl($scope, $http, $location, $q, $timeout) {
$scope.results = ["Test"];
$scope.term = "";
$scope.reqs = "5";
$scope.pics = "45";
$scope.ddata = "asdasd";
$scope.ddata = $http.post("{% url 'get-nav-info' %}").success(
function (result) {
//$scope.reqs = result.data.data.num_request;
//$scope.pics = result.data.data.num_photo;
return result.data;
}
);
//$scope.reqs = $scope.ddata.num_request;
//$scope.pics = $scope.ddata.num_photo;
$scope.search = function () {
//alert("test");
//$location.absUrl("{% url 'search-term-show' %}").search({'term':$scope.term}).apply();
//$location.path("{% url 'search-term-show' %}").search({'term':$scope.term}).apply();
$http.get("{% url 'search-term-show' %}?term=" + $scope.term).success(function (result) {
return result.data;
});
//$scope.$apply();
}
}
]);
</script>
now the problem is that while i press enter ,there is no result,but if i manually write this URL which is http://www.kothay.com/searchphoto/?term=a in the address bar then the result is showing .In mention,this url is the that url which should be appear in the address bar when i press the enter to search my photos.But with the enter press its not appearing in the address bar and that's why the results are not showing.I hope you can understand what i am trying to say.May be there is a mistake in my code.Please help me to fix this problem.
You are doing thing wrong.
1st, the success is a defer of get, so return result.data and returns it to the get deferred and there it goes to the heaven. So if you would like to keep the current architecture it should look more like this
$scope.search = [];
getsearch = function () {
$http.get("{% url 'search-term-show' %}?term=" + $scope.term).success(function (result) {
$scope.search = result.data;
});
};
getsearch();
2nd that can still not update your UI cuz if the ctrl function is over and the digest is over before your response it wont update your UI cuz its in another scope (not $scope, but the programmatically term scope). The solution to this is to put your data in a service and in your ctr just do.
function ctrl($scope, myservice){
$scope.data = myservice;
}
ng-repeat="x in data.results"
Here is a full tutorial http://bresleveloper.blogspot.co.il/2013/08/breslevelopers-angularjs-tutorial.html
And last thing its just a good practice to always have .error(...)

How to pass django ajax data to template?

I'm trying to pass a 2d array into a template via ajax. I managed to get the data from the server on click, but I don't know how I can handle that data inside a template. For instance, if I put the returned 'data' into a div then it just lists the first column. How to access specific data with, for instance:
{% for printers in printer_list %}
{{ printer.email }}
{% endfor %}
Javascript:
$(".printersToggle").click(function() {
$.get("/ajax", function(data) {
/* What goes here? */
});
});
views.py:
def ajax_test(request):
if request.is_ajax():
printer_list = User.objects.all()
else:
printer_list = "Not ajax"
return HttpResponse(printer_list)
# Am I doing this bit right?
urls.py:
url(r'^ajax$','website.views.ajax_test'),
Views.py
Below we are receiving an AJAX POST and filtering an object based on 'VarID', and building a list of dictionaries that each contain an OptionID, OptionValue, and OptionLabel value. Finally, you should convert whatever list or dict or combo that you want in json.
def currentoptions(request):
if request.is_ajax():
currentOptions = Option.objects.filter(VariableID=int(request.POST['VarID']))
response = []
for i in currentOptions:
vallabel = {}
vallabel['OptionID'] = i.id
vallabel['OptionValue'] = i.Value
vallabel['OptionLabel'] = i.Label
response.append(vallabel)
json = simplejson.dumps(response)
return HttpResponse(json, mimetype="text/json")
else:
pass
Javascript needed for CSRF reasons.
<script type="text/javascript">
jQuery(document).ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
</script>
Javascript for your specific AJAX request.
To display the values from the dicts in the lists we are iterating through the returned data on success of the AJAX request. The JS functions are done with jQuery.
function AddOptions(VarID){
$.ajax({
type:"POST",
url:"{% url builder.views.currentoptions %}",
data: {VarID: VarID},
success: function(data){
$('#OptionTable > tbody > tr').remove();
$.each(data, function(index) {
$('#OptionTable > tbody:last').append('<tr id=Option_'+data[index].OptionID+'><td>'+data[index].OptionValue+'</td><td>'+data[index].OptionLabel+'</td><td><i class="icon icon-remove"></i>');
});
}
});
}
This has to be done using javascript. Once the template is generated on the server and the page is displayed in the visitors web browser it is nothing more than HTML with JavaScript. In order to manipulate the page you need to use JavaScript.

getting a user-inputed variable in django template wihtout using forms

I have a django template which also has a div element that takes in a user_inputed value.
When the value is entered, I call a javascript function say onSubmit(user_input)
<input type="text" class= "inputtext" onKeyPress="return onSubmit(this.value)">
Now in this onSubmit() function which now has the user-inputted value user_input, I want to be able to use url patterns to a direct to a view, like
function onSubmit(user_input) {window.location = "{% url myview user_input %}";}
The problem here is that since user_input is empty when the template is loaded, the url-view reverse lookup gives an error. Is there a way to trigger this lookup only when the onSubmit function is called.
I know form is an alternative, but it just feels like it'll be an overkill for this situation.
You can get the URL via AJAX:
views.py:
def get_url(request):
name = request.GET.get('name')
args = reguest.GET.get('args', [])
kwargs = request.GET.get('kwargs', {})
try:
url = django.core.urlresolvers.reverse(name, args=args, kwargs=kwargs)
except NoReverseMatch:
url = None
return django.http.HttpResponse(url)
urls.py
#...
('^url$', get_url)
#...
js:
function onSubmit(user_input) {
var args = [user_input];
jQuery.get('/url', {'args': args}, function(data) {
var url = data;
if (url) {
window.location = url;
} else {
alert('fail');
}
});
}
Alternatively, if your URL rule is simple enough, you can use some placeholder when resolving and URL, and before submitting the form you should replace it with real input:
var fakeUrl = '{% url myview "%s%" %}';
function onSubmit(user_input) {
window.location = fakeUrl.replace('%s%', user_input);
}