How to define Django view - javascript

I am trying to develop a chatbot using Django and depending on the user's input, various python scripts need to be run.
Having the project structure (presented below), is there a way to call the news.py in chatbot.js?
I have tried with an ajax request:
$.ajax({
type: "POST",
url: "news/",
data: { }
}).done(function( o ) {
print('success')
});
and defined news/ in my urls.py
url('news/', getNews)
where getNews is defined in my views
from artemis.static.marketdata.news import scrape
class getNews():
scrape()
but I get a 500 error saying that TypeError: object() takes no parameters
Traceback:
Internal Server Error: /news/
Traceback (most recent call last):
File "C:\Users\user\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\exception.py", line 41, in inner
response = get_response(request)
File "C:\Users\user\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\user\AppData\Local\Programs\Python\Python36\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
TypeError: object() takes no parameters
What would be the preferable approach in this case?
Any tip would be greatly appreciated!

Django has "function" view and "class" view.
You are defining class getNews(). So you have to choose use "function" view or "class" view.
To use function view, change "class" to "def":
from django.http import HttpResponse
def getNews(request):
result = scrape()
return HttpResponse(result)
To use class view, define the "getNews()" in correct way.
in view:
from django.views import View
from django.http import HttpResponse
class NewsView(View):
...
def get(self, request, *args, **kwargs):
result = scrape()
return HttpResponse(result)
in urls.py:
from views import NewsView
...
url(r'^news/$', NewsView.as_view()),

I think your class declaration is wrong.
class getNews(object):
def __init__(self, *args, **kwargs):
# continue here
def scrape(self):
# continue here
New-style classes inherit from object, not from NoneType.
Note: this answer addresses a code error in the source, nothing to do with django, just python syntax.
Samuel Chen's answer addresses how you create a view in django. A django view is a new-style class, derived from django.views.View. It contains methods corresponding to the HTTP methods (i.e. get, post, put etc.).

Related

How to render template sent as response from Flask app in ajax?

I'm working with Python Flask application that uses basic html and javascript for the web part.
I'm sending data from UI to the backend using ajax post request.
After processing of data, from the Python flask app I'm returning the response with render_template. But I'm not able to understand how that can be rendered using ajax on the web browser.
The python flask API returns this:
#app.route("/execution_pipeline", methods=['POST', 'GET'])
def execution_pipeline():
try:
if request.method == 'POST':
inputMap = request.get_json()
print(inputMap)
###I have my code here###
return render_template('demo.html', location=minio_results_file_location)
except ReferenceError as e:
return "It is a {} Provide proper referaece of file path"
The "demo.html" is a template in the code directory which i want to load on successful execution
And The ajax function is as follows:
$.ajax({
type: "POST",
url: "execution_pipeline",
data: JSON.stringify(data),
contentType : "application/json",
success: function(response) {
window.location.href = response.redirect;
}
});
But on the web page, where we try to load this Ajax response, i'm getting URL not found.
Is there any solution to this?Or am i doing anything wrong?
Import jsonify and url_for from flask:
from flask import jsonify, url_for
And try returning like this to the ajax call:
#app.route("/execution_pipeline", methods=['POST', 'GET'])
def execution_pipeline():
try:
if request.method == 'POST':
inputMap = request.get_json()
print(inputMap)
###I have my code here###
return jsonify({'redirect': url_for('demo.html', location=minio_results_file_location)})
except ReferenceError as e:
return "It is a {} Provide proper referaece of file path"

Getting data from existing sqlite DB into webpage

I have desktop application which creates SqLite DB.
I would like to use that data to make reports on a local static web page.
However I'm not sure how to go about connecting to an existing DB - I understand there are security issues with this.
is this possible with JavaScript ? and how would i go about this ?
One option is to pass the data from the templates like so:
def index(request):
# Calculate your precious data here, for example using the django.core.serializers class:
data = serializers.serialize('json', FooModel.objects.all())
return render(request, 'templates/index.html', {'data': data})
Then in your templates/index.html you could do something like this:
<script>
window.data = {{data|default:"{}"|safe}};
</script>
Check out the safe filter.
This way, you get all your data from backend to frontend with your initial request without creating any additional requests, or communicating with your DB directly with JS.
Another option is using fetch:
You could create a view (you could use Django REST framework but that's up to what you're trying to use it for, the main idea remains the same anyway):
from django.http import HttpResponseNotAllowed, JsonResponse
from django.core import serializers
from .models import FooModel # for example
def myview(request):
if request.method != "POST":
return HttpResponseNotAllowed(['POST'], "Only POST is allowed to this URL.")
# Get your precious data, let's use the same example as before:
data = serializers.serialize('json', FooModel.objects.all())
return JsonResponse(data)
Register it in your urls.py:
urlpatterns = [
...
path('api/retrievepreciousdata', views.myview),
...
]
And then we can use fetch to retrieve it:
fetch("/api/retrievepreciousdata", {
method: "POST",
headers: {
//For CSRF protection:
//I use `js-cookie` to get the cookies, it's up to you really
"X-CSRFToken": Cookies.get("csrftoken"),
"X-Requested-With": "XMLHttpRequest",
},
}).then(response => {
if(!response.ok) {
console.log("Dang it, the response isn't OK... Response code is", response.status);
}
return response.json()
}).then(json => {
console.log("I did it! My precious data is:", json);
}).catch(e => {
console.log("Dang it, something went wrong while retrieving my precious data:", e);
});
If you are looking for a way to read data from SQLlite Db from a static webpage I suggest you read the following thread Is it possible to access an SQLite database from JavaScript?
Try this also SQL.js (its mention in the above thread)

Updating info on html page using Ajax in Django

I have a problem with Ajax and how can I update info on my HTML page without reloading it.
So, I have a function in my views.py file:
def index(request):
some stuff
context = {
some stuff
}
return render(request, "header.html", context)
And I just use variables from {context} in my header.html file. And the question is - how can I perform index function and send new variables to my header.html file without reloading it?
First, create a new endpoint to get the desired data in whichever format. I prefer JSON.
New endpoint:
# views.py
from django.http import JsonResponse
def new_endpoint(request):
"""Returns `JsonResponse` object"""
# you can change the request method in the following condition.
# I dont know what you're dealing with.
if request.is_ajax() and request.method == 'GET':
# main logic here setting the value of resp_data
resp_data = {
'html': 'stuff',
# more data
}
return JsonResponse(resp_data, status=200)
Then, you need to code the AJAX part calling this endpoint with the method, data, headers, etc. and finally, define the success callback method to get the desired data.
AJAX:
var data = {};
$.ajax({
url: '/your-new-endpoint-url',
type: 'GET',
data: data,
dataType: 'json',
success: function(resp) {
$('#changingElement').html(resp.html);
}
});
You can send any type of data from this new endpoint to change whatever element's html text or class name or styles, etc.

Passing a JSON string to django using JQuery and Ajax

I'm a bit new to Django and trying to understand it. Currently, I'm creating a network topology visualiser (think routers and switches connected together). It works fine and all of the data is saved in a javascript object.
I want to have the ability to, when a user clicks a button, send this javascript object to django so that it can be parsed and handled appropriately. I did a lot of research and found a bunch of similar implementation which use a combination of JQuery and ajax to POST a JSON string. This is some of my code currently:
mainapp/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^NetworkTopology/', include('OpenAutomation.NetworkTopology.urls')),
url(r'^NetworkTopology/json/', include('OpenAutomation.NetworkTopology.urls')),
url(r'^admin/', admin.site.urls),
]
NetworkTopology/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^json/$', views.returnjson, name='returnjson'),
]
NetworkTopology/views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response
def index(request):
return render_to_response('index.html')
def returnjson(request):
if request.is_ajax():
request_data = request.POST
print("Raw Data: " + request_data.body)
return HttpResponse("OK")
JavaScript function (return JSON button is pressed):
function returnJsonTop(){
$(document).ready(function() {
$.ajax({
method: 'POST',
url: '/NetworkTopology/json',
dataType: 'json',
data: JSON.stringify(nodes.get(),null,4),
success: function (data) {
//this gets called when server returns an OK response
alert("it worked!");
},
error: function (data) {
alert("it didnt work");
}
});
});
}
In my index template, I have created a button which calls the returnJsonTop() function when it is pressed:
<button id="submitJson" onclick="returnJsonTop();">Deploy</button>
Currently, when I press the Deploy button, I just get the 'it didn't work' alert that has been setup to handle an errors. I'd really appreciate someone pointing me in the right direction here. I suspect the issue is in my urls.py files but I've tried various combinations of urls without any luck.
You're trying to access body on request.POST. But body is an attribute directly of the request. Your code should be:
request_data = request.body
print("Raw Data: " + request_data)
Also note, in your Javascript that $(document).ready line makes no sense there; you should remove it.
For those reading this later, this is what I did:
mainapp/urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^NetworkTopology/', include('OpenAutomation.NetworkTopology.urls')),
url(r'^admin/', admin.site.urls),
]
NetworkTopology/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^json/$', views.returnjson, name='returnjson'),
]
NetworkTopology/views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.views.decorators.csrf import csrf_exempt
def index(request):
return render_to_response('index.html')
#csrf_exempt
def returnjson(request):
if request.is_ajax():
request_data = request.POST
print("Raw Data: " + str(request_data))
return HttpResponse("OK")
I was getting a 403 error so I added '#csrf_exempt'. I'll probably change this to handle it properly afterwards.
Return JSON function:
function returnJsonTop(){
$.ajax({
method: 'POST',
url: '/NetworkTopology/json/',
dataType: 'json',
data: JSON.stringify(nodes.get(),null,4)
});
}
First of all you dont even need to use all this in your ajax call
data: JSON.stringify(nodes.get(),null,4),
replace by
data: nodes.get(),
should be enough as long as this method returns a valid json object
Second one, I ´d strongly recommend you to use a framework to help you to parse JSON
Python have may, but to illustrate this example, I've used django rest framework, which is a very good one.
from django.shortcuts import render
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
import json
import controllers#this class belongs to my business logic layer, you can encapsulate yours and use instead of it
#in this solution you must create a pre-parser to handle responses
class JSONResponse(HttpResponse):
"""
An HttpResponse that renders its content into JSON.
"""
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
#csrf_exempt # this is for prevent invasions
def login(request):
#this one here handle your jquery post data into a valid json object in python represented by a Dict
envelopin = json.loads(request.body)
# here we pass the dict inside my business controll logic routine which also responds with a valid Python Dict
envelopout = controllers.login(envelopin)
# and for last, we use our pre-parser Class to make your response be handled by jquery as valid json
return JSONResponse(envelopout)
and that is it, you success jQuery data variable, will hold the envelopout json object, in the same shape as it has inside yor django-python code.
hope this help

Post throwing 500 error

I'm writing a small app. Here is the code snippet.
Javascript:
<script type="text/javascript">
function filldata()
{
var sample = document.getElementById("filter-select").value;
jQuery.support.cors = true;
$.post("/test",{"filter_type":sample},function(data,status)
{
alert(data);
});
}
</script>
Flask Code:
#app.route('/test', methods=['POST'])
def test(str):
return str
It is giving me 500 internal error.
When I run this in debug mode, it is saying:
test() takes exactly one argument(zero given)
Your code:
#app.route('/test',methods=['POST'])
def test(str):
return str
Expect a variable named str in input.
With flask, when defining route the arguments of the function represent the url variables:
# the url have a parameter
#app.route('/user/<id>',methods=['GET'])
def test(id): # we get it here
return user.fromId(id)
To retrieve querystring you can use request.args. And to get body request.data or request.json if you are sending json.
from flask import request
#app.route('/test',methods=['POST'])
def test():
return request.data
You need to parse argument from Flask's request object
from flask import request
#app.route('/test',methods=['POST'])
def test():
return request.form.get('filter_type')
See quickstart for more info
In your Flask code snippet, you have added an argument, but arguments are only sent if you change the URL to /test/<str:str>. Since it is a POST request, you can access the data by using request.json.

Categories

Resources