#In my views.py file
pi1 = None
pis1 = None
def my_func():
#Essentially this function sets a random integer to pi1 and pis1
global pi1, pis1
pi1 = randint(0,9)
pis1 = randint(0,9)
return
def index(request):
my_func()
context = {
"pi1" : pi1,
"pis1" : pis1,
}
return render(request, "index.html", context)
#In the index.html file
<h1>{{ pi1 }}</h1>
<h1>{{ pis1 }}</h1>
I've removed a lot of my code for simplicity, but this is the gist of it. Despite the code that I've posted for my_func, it is a time consuming function that causes index.html to load for awhile when it is accessed. How would I run my_func in the backround using celery and redis so that index.html loads more quickly?
I've read the celery documentation, but I am still having trouble setting up celery and redis. Thank you.
As is said previous, you might not need celery. Here's an example derived from case 2 of this: https://zapier.com/blog/async-celery-example-why-and-how/. It's fully working for me:
from time import sleep
import json
from django.http import HttpResponse
from django.shortcuts import render
def main_view(request):
return render(request, 'index.html')
def ajax_view(request):
sleep(10) #This is whatever work you need
pi1 = "This is pi1" #I just made pi1/pis1 random values
pis1 = "This is pis1"
context = {
"pi1" : pi1,
"pis1" : pis1,
}
data = json.dumps(context)
return HttpResponse(data, content_type='application/json')
My index.html contains:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Main View</title>
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
$(document).ready(function(){
$.ajax({
url: "/test_ajax/",
}).done(function( data) {
$("#pi1").text(data.pi1);
$("#pis1").text(data.pis1);
});
});
</script>
</head>
<body>
<h1 id = "pi1">Loading</h1>
<h1 id = "pis1">Loading</h1>
</body>
</html>
And my urls.py contains:
from django.conf.urls import include, url
from django.contrib import admin
from testDjango.test import main_view, ajax_view
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^test/', main_view),
url(r'^test_ajax/', ajax_view)
]
What happens when I visit localhost:8000/test/ is that I instantly see:
After about 10 seconds, I then see:
The idea is that you return your page instantly and use jquery to fetch the result of the operation whenever that's finished and update your page accordingly. You can add more things like progress bars/loading image etc. For your example, you can do the processing for pi1 and pis in the background and load it into the HTML after that's finished.
You don't need celery here. You can load these values on page with AJAX request. You should create a separate view that will calculate this values and after the index.html is loaded call it with javascript.
Related
import pandas as pd
from django.shortcuts import render
# Create your views here.
def home():
data = pd.read_csv("\\pandadjangoproject\\nmdata.csv", nrows=11)
only_city = data[['name']]
context = {
"data": data.to_html(index=False),
"only_city": only_city.to_html()
}
return request(render, 'home.html', context)
#Here is my HTML Page
<html>
<head>
<title>NM Biggest citys</title>
</head>
<body>
<h1>New Mexicos Largest Citys</h1>
{{only_city|safe}}
</body>
</html>
#I get this error:
TypeError at /
home() takes 0 positional arguments but 1 was given
Request Method: GET
Request URL: http://localhost:8000/
Django Version: 4.0.1
Exception Type: TypeError
Exception Value:
home() takes 0 positional arguments but 1 was given
Looks like the Problem was actually with my csv file it was somehow empty when i copied it from another csv file so i got the original and put it in my django folder with drag and drop.
The other problem i did have was in my view I accidently had return request(render but in django its supposed to be return render(request,
A view function, or view for short, is a Python function that takes a web request and returns a web response.
Add request in your home as
def home(request):
data = pd.read_csv("\\pandadjangoproject\\nmdata.csv", nrows=11)
only_city = data[['name']]
context = {
"data": data.to_html(index=False),
"only_city": only_city.to_html()
}
return render(request, 'home.html', context)
Here is situation I've dealt with. I will try to explain as much as easier to understand.
I want user to click on a button in the website (let's name this site A) which fires an ajax post request to django view. Within this view I have response.set_cookie to set cookie with data that is passed along with ajax post request.
After success response, then I quickly redirect page to different website (let say this site is B). When page loads, I want to access cookies what I've set from site A but cannot access.
Below is my code.
index.html (in site A, where the ajax post request is made)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button onclick=setCookies()>Create Invoice</button>
</body>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script type="text/javascript">
const setCookies = () => {
...some codes...
const xhr = new XMLHttpRequest()
const data = {
'HTTP_LOGIN_TYPE': 'admin',
}
$.ajax(
{
type: 'POST',
url: url, // hits endpoint where sets cookies.
crossDomain: true,
data: data,
success: () => {
window.location.href = to site B
},
error: xhr => {
console.log(xhr.responseText)
}
}
)
}
</script>
</html>
views.py (in site B, where sets the cookies)
from django.http import HttpResponse
from django.conf import settings
from rest_framework.views import APIView
class AuthenticateUser(APIView):
def post(self, request):
data = request.POST
login_type = data['HTTP_LOGIN_TYPE']
if login_type == 'admin':
response = HttpResponse(
'Setting login_type to %s' % login_type)
response.set_cookie(
'login_type', login_type, max_age=604800, domain=settings.SESSION_COOKIE_DOMAIN)
return response
views.py (in site B, redirected from ajax call in index.html, where I want to access cookies)
import re
from django.db import DatabaseError
from rest_framework.response import Response
from rest_framework.renderers import TemplateHTMLRenderer
from rest_framework.views import APIView
class GetInvoice(APIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'student/base.html'
def get(self, request, student_id):
login_type = 'hello'
if 'login_type' in request.COOKIES:
login_type = request.COOKIES['login_type'] # Can't access cookies
... more code ...
FYI, url in index.html and site B's domain are same, though site A and B's domains are different.
I am not sure what am I missing. I've been searching articles, posts, etc for last couple days and tried based on them but no luck.
Correct me if I missed anything.
Thanks in advance.
Because of the Same-origin Policy, you cannot access the cookies for a different domain.
Access to data stored in the browser such as localStorage and
IndexedDB are separated by origin. Each origin gets its own separate
storage, and JavaScript in one origin cannot read from or write to the
storage belonging to another origin.
However, if domain B is a subdomain of A, it will automatically have visibility into the cookies for domain A. If you cannot change the domains, you should redirect to site B with the cookies in the request headers/body.
I am very new to Flask. I have a mysql database and a template. Let's say I have 3 images
<div><img src= pathOfImage id="profile1"/></div>
<div><img src= pathOfImage id="profile2"/></div>
<div><img src= pathOfImage id="profile3"/></div>
The id of each image (profile1,profile2,profile3) is the primary key of the some tables in the database. What I want to do is to find the values of the corresponding attributes of that tuple by using the primary key. Then, load that those values to the template from the tuples.
And, I have the following code in Python:
from flask import *
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
The snippet of HTML code I gave above is in expert.html. I almost of SQL query that was not listed above, data on the second parameter in render_template in route1() is the SQL tuple, which generate all these images and the ID.
I have tried to put a button next to the images, and give id to the button instead. Then, pass the id to the python script as a variable using Ajax, and get the SQL tuple.
However, this isn't the hard part. The hard part is making the new route and loading the content. I have tried make a new route using "app.route" and pass the data into the second parameter of render_template. But, it didn't redirect to a new profile, and the method was called before I even click on the profile.
previously, I used button to retrieve the id:
<html>
<body>
<button id='1'>Button1</button>
<button id='2'>Button2</button>
<button id='3'>Button3</button>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"</script>
<script>
$(document).ready(function() {
$('button').click(function(event) {
var the_id = event.target.id;
$.ajax({
url: "/get_id",
type: "get",
data: {the_id: the_id},
success: function(response) {
},
error: function(xhr) {
}
});
})});
</script>
and, I used these to generate a new template:
import flask
from flask import *
from flaskext.mysql import MySQL
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
#app.route('/get_id')
#app.route('/profile')
def route2():
button_id '"' + flask.request.args.get('the_id') + '"'
//some code here to get the tuples that I need "client_info" and
//"skill_info" variable below
return render_template("profile.html", client_info=client_info,
skill_info=skill_info)
Hope someone would give a fresh start. Thanks in advance!
Instead of passing info by ajax you can pass it through the route url.
experts.html
<div><img src="pathOfImage"></div>
<div><img src="pathOfImage"></div>
<div><img src="pathOfImage"></div>
flask routes
import flask
from flask import *
from flaskext.mysql import MySQL
#app.route("/")
def index():
return render_template("index.html")
#app.route('/experts')
def route1():
return render_template("experts.html", data=data)
#app.route('/profile/<id>')
def route2(id):
# id variable contains user profile id string as per user click
# depending on id set variables client_info and skill_info and render
return render_template("profile.html", client_info=client_info, skill_info=skill_info)
{% for profile in profiles %}
<img src="{{profile.img}}">
{% endfor %}
...I guess? maybe?
I have a method which sends the data to HTML page direclt without any request.
views.py
def SendSentence():
sentence = "Hello World"
html = render_to_string('Display.html', Context({'Sentence': sentence}))
return HttpResponse(html)
Display.html
<html>
<head>
</head>
<body>
{% csrf_token %}
The data is ...{{ Sentence }}...
</body>
</html>
Kindly let me know Is this possible? or let me know how to get the response directly from the view.py to a html page when it is called
From docs:
A view function, or view for short, is simply a Python function that takes a Web request and returns a Web response.
request is required argument for a view function. So by definition, you cannot use SendSentence() as a view.
You can define SendSentence() as:
def SendSentence(request):
# do not do anything with request
sentence = "Hello World"
html = render_to_string('Display.html', Context({'Sentence': sentence}))
return HttpResponse(html)
However, the standard way to render a template is:
def SendSentence(request):
sentence = "Hello World"
return render(request, 'Display.html', dict(Sentence=sentence))
I'm trying to host a website off a Beaglebone Black using lighttpd and web.py. Any post request creates Error 413 - Request Entity Too Large. I am very new to web development, so I apologize if I've used the wrong terminology. To be clear, I am not attempting to upload any file of any kind. I created a simple page, test, to illustrate the error. My code:
First, Monitor.py:
#!/usr/bin/env python
import web
import Model
from Account import Account
from Forgot import Forgot
from Login import Login
from Reset import Reset
from Subscribe import Subscribe
from Success import Success
from Status import Status
from Test import Test
urls = ('/', 'Status',
'/test', 'Test',
'/account', 'Account',
'/forgot', 'Forgot',
'/login', 'Login',
'/reset/(\d+)', 'Reset',
'/success', 'Success',
'/subscribe', 'Subscribe',
)
render = web.template.render('templates')
app = web.application(urls, globals())
web.config.debug = False
session = Model.create_session(app)
if __name__ == '__main__':
app.run()
Now, Test.py:
#!/usr/bin/env python
import web
import Model
render = web.template.render('templates')
class Test:
def GET(self):
return render.test()
def POST(self):
i = web.input()
raise web.seeother('/test')
Now, the html file, located in the templates folder:
$def with()
<html>
<head>
<link rel="stylesheet" href="static/stylesheet.css" type="text/css" media="screen" charset="utf-8"/>
<title>Account Page</title>
</head>
<body>
div>
<form action="/test" method="POST">
<table class="std-element">
<tr>
<th>
<input type="text" name="example_text">
</th>
</tr>
</table>
</form>
</div>
</body>
</html>
The relevant portion of the model file:
session = None
def create_session(app):
global session
session = web.session.Session(app, web.session.DiskStore('sessions'), initializer={'username':default_username})
session['username'] = default_username
return session
def get_session():
global session
return session
And, finally, the lighttpd.config file:
server.modules = (
"mod_access",
"mod_accesslog",
"mod_alias",
"mod_compress",
)
server.document-root = "/var/www/"
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )
server.errorlog = "/var/log/lighttpd/error.log"
server.pid-file = "/var/run/lighttpd.pid"
server.username = "www-data"
server.groupname = "www-data"
server.port = 80
server.breakagelog = "/var/log/lighttpd/breakage.log"
server.max-request-size=100000000
server.uploads-dirs=("/mnt")
server.network-backend="write"
## Use ipv6 if available
#include_shell "/usr/share/lighttpd/use-ipv6.pl"
compress.cache-dir = "/var/cache/lighttpd/compress/"
compress.filetype = ( "application/x-javascript", "text/css", "text/html", "text/plain" )
include_shell "/usr/share/lighttpd/create-mime.assign.pl"
include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
server.max-request-size=100000000 is way too large. It is measured in KB. Internally, lighttpd left-shifts that number 10 bits, which, in your version of lighttpd, results in any POST being compared with 0 and rejected because it is too large. This has been fixed in lighttpd 1.4.40, but you should probably reduce that limit anyway. Having a 100 TB (!) request size limit is probably not going to protect your Beaglebone. Try this: server.max-request-size=1024 will set a 1 MB limit on POST requests. (Again, that config directive is in KB)