How can I change header when user is logged in django? - javascript

I have two headers header.html and headersuccess.html . I user is logged in, I need to change the header.html as headersuccess.html. How can I able to implement that?
My views.py is.. By this I am going to loginsuccess.html.. So, if login is success I need to change header from header.html to hadersuccess.html
def logsuccess(request):
if('loggedIn' in request.session):
id = request.session['uid'];
return render(request,"loginsuccess.html",{'uid':id});
else:
return render(request,"failed.html",{});
I am getting uid using this. I am using html and vue js for displaying.

You can do this in the view:
def logsuccess(request):
if request.user.is_authenticated():
id = request.user.id
return render(request, "loginsuccess.html", {'uid': id})
else:
return render(request, "failed.html", {})
You'll probably also want to read up on PEP-8 to follow Python coding conventions. Good luck!

Related

How to connect JavaScript to Python script with Flask?

I created a website with HTML/CSS. I also used Javascript for events (click on button, ...).
Now I want to connect a Python script with it and more importantly, return the results from my Python functions to my website and display (use) them there.
Consider something like this: I have a website with an input field and a button. If you click on the button, a Python script should run which returns if the input is an odd or even number (of course you don't need Python for this specific case, but that's what I want to do).
From my research I believe Flask is the library to be used for this, but I really don't know how to do it. I found very few examples. I would really appreciate if someone could implement the above example or tell me how to do it exactly.
I know there are already some questions about that concept here online, but as I said, with very few examples.
You're right about Flask being a good solution for this and there are examples and tutorials everywhere. If what you want is just to run a specific function on a button press and get something back in javascript, I've put a quick example is below.
# app.py
from flask import Flask, render_template
from flask import jsonify
app = Flask(__name__)
# Display your index page
#app.route("/")
def index():
return render_template('index.html')
# A function to add two numbers
#app.route("/add")
def add():
a = request.args.get('a')
b = request.args.get('b')
return jsonify({"result": a+b})
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
This can then be run with python app.py and make sure your index.html is in the same directory. Then you should be able to go to http://127.0.0.1/ and see your page load.
This implements a function which adds two numbers, this can be called in your javascript by calling http://127.0.0.1/add?a=10&b=20. This should then return {"result": 30}.
You can grab this in your javascript using the code below and place this code in your buttons on click callback.
let first = 10;
let second = 20;
fetch('http://127.0.0.1/add?a='+first+'&b='+second)
.then((response) => {
return response.json();
})
.then((myJson) => {
console.log("When I add "+first+" and "+second+" I get: " + myJson.result);
});
This should be the barebone basics, but once you can submit data to Flask and get data back, you now have an interface to run things in Python.
Edit: Full Front-end example
https://jsfiddle.net/4bv805L6/
I really appreciate time spent on this answer. But the answer did not help me in the way I needed it. At that point I had no clue what to do, but since thenbI figured it out some time ago and I thought I should share my solution here:
That's app.py:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/stick', methods=['GET', 'POST'])
def stick():
if request.method == 'POST':
result = request.form['string1'] + request.form['string2']
return render_template('index.html', result=result)
else:
return render_template('index.html')
if __name__ == "__main__":
app.run()
And that's index.html (put in the folder templates):
<!DOCTYPE html>
<html>
<body>
<h3> Stick two strings </h3>
<form action="{{ url_for('stick') }}" method="post">
<input type="text" name="string1">
<input type="text" name="string2">
<input type="submit" value="Go!">
<p id="result"></p>
</form>
<script>
document.getElementById("result").innerHTML = "{{result}}"
</script>
</body>
</html>
In the terminal, type in python app.py and it should work.

How to refresh part of a Django page with AJAX?

I am deploying a website using Django. There is an application called 'forum', supporting a discussion forum on my website.
The url of the discussion forum is 'XXX.com/forum/roomY'. I want to refresh a div id = ''chat'', which includes a message list, on this page when users click a refresh button. I want to use AJAX to do that.
But I find that I could not call the function updatestatementlist(request) to retrieve the updated message list so it can be passed to the on this page.
/forum/views.py def updatestatementlist(request):
log.debug("call statementlist function")
statements = Statement.objects.filter(discussion=discussion)
return render(request, 'forum/statementlist.html', {
'statements': statements
})
I cannot see the log info so I think by clicking the button I fail to call this function.
The main html page of the discussion forum is /forum/discussion.html, which is under the template folder. I extract the html code within the div id = "chat" to a separate html /forum/statementlist.html as suggested here and several other SO posts.
/forum/discussion.html
<button id = "Refresh"> Refresh </button>
<div id="chat">
{% include 'forum/statementlist.html' %}
</div>
/forum/statementlist.html
{% load mptt_tags %}
{% recursetree statements %}
// display each statement
{% endrecursetree %}
forum.js
//When users click the refresh button
$("#Refresh").on("click", function(event){
alert("Refresh clicked")
$.ajax({
url: '',
type: "GET",
success: function(data) {
alert("success")
var html = $(data).filter('#chat').html();
$('#chat').html(html);
}
});
});
I also tried a few other url in this AJAX request: {% url updatestatementlist %}, {% url 'updatestatementlist' %}. But then I think it should be set to empty because I don't want to be redirected to another url. The discussion forum has a url of 'XXX.com/forum/roomY', by clicking the refresh button on this page I only want to refresh the div and fetch an updated statement list from the server.
BTW, I can see the two alerts after I click the button.
/forum/urls.py
urlpatterns = [
...
url(r'^(?P<label>[\w-]{,50})/$', views.discussion_forum, name='discussion_forum'),
url(r'^(?P<label>[\w-]{,50})/$', views.statementlist, name='statementlist'),
]
/forum/views.py def discussion_forum() is used to load all the information when the user first arrives at this forum.
I guess my problem might be that 1) the AJAX is wrong; 2) the url is wrong so that the updatestatementlist() can not be called.
Can anyone help me with that? Thanks a lot! Let me know if you need any other information!
Packages related:
Django==1.9.3
django-mptt==0.8.7
On the client side, Set your request header to X-Requested-With to XMLHttpRequest, Django use this specific header to determine whether it is a Ajax Request:
Here is the a snippet from Django source code:
https://docs.djangoproject.com/en/2.2/_modules/django/http/request/#HttpRequest.is_ajax
def is_ajax(self):
return self.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
After defining this header, you need to add one logic layer into your view function.
def your_view_func(request, *args, **kwargs):
if request.is_ajax():
...
return render(request, <your_ajax_template>)
return render(request, <your_normal_template>)
Updated:
I prefer the raw XMLHttpRequest API, if you use Jquery, add the berforeSend property.
$.ajax({
type: "GET",
beforeSend: function(request) {
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
},
...
});
Why X-Requested-With but not HTTP_X_REQUESTED_WITH?
HTTP headers in the request are converted to META keys by converting all characters to uppercase, replacing any hyphens with underscores and adding an HTTP_ prefix to the name.
https://docs.djangoproject.com/en/2.2/ref/request-response/#django.http.HttpRequest.META

#app.route not working without redirection

This function is working perfectly if I do a redirect to another page #app.route('/results') but I'm struggling to make it work in the same page without reloading :
#app.route('/')
def static_file():
return app.send_static_file('index.html')
#app.route('/')
def results():
headers = {
'X-ApiKey': 'xxxxxxxxxxxxxxxx',
}
data = {'data': request.args.get('data')}
results = requests.post('https://apiv2.indico.io/personality', headers=headers, data=data)
return results.text
I'd like to display the results of the api call in the same page (below the input box)
<form action="" onsubmit="return false";>
<strong> Try It <br><br>
</strong><br>
<input type="text" name="data"><br><br>
<input type="submit" onclick="showResults();">
<label id:Results>Your Result: </label>
<p><span id='display'></span></p>
</form>
I've also added some JS:
<script language="JavaScript">
function showResults() {
document.getElementById('display').innerHTML =
document.getElementById("Results").value;
}
</script>
What's wrong with my code? I'm using Flask framework.
If I understood you correctly, what you want to achieve is to have RESTful API written in Flask microframework, which would allow you to obtain some results and display on your page without reloading. If so, your approach is wrong.
Firstly, you can't route multiple functions with common URL:
#app.route('/common_route')
def foo():
pass
#app.route('/common_route')
def bar():
pass
It is impossible to determine which function did you want to be invoked if you load http://yourwebsite/common_route.
In order to avoid page reloading, you should rather use Flask-RESTful module and implement an API for obtaining results.
import flask-restful
class Results(Resource):
def __init__(self):
super(Results)
#for GET requests
def get(self):
#your code here
pass
#for POST requests
def post(self):
#your code here
pass
api = Api(app)
api.add_resource(Results(),'/api/results')
Then you can obtain your results f.e. with JS & jQuery code: https://www.w3schools.com/jquery/jquery_ajax_get_post.asp

Using list from views in Django 1.8.1 as an array in javascript template

I have a piece of code in views.py that gets the file names from a directory:
def imgArray(request):
filepath = STATIC_PATH+"\\images"
imageArray=[]
ext='.jpg'
for i in os.listdir(filepath):
if(os.path.splitext(i)[1] == ext):
imageArray.append( i )
context = {'imageArray': imageArray}
print context
return render(request, 'imgpage/add_category.html',context)
def add_category(request):
# A HTTP POST?
if request.method == 'POST':
#Do some actions
else:
# If the request was not a POST, display the form to enter details.
imageArray = imgArray(request)
return render(request, 'imgpage/add_category.html')
I want to use this array of image files in javascript. I want to use the array of file names so that I can use js to change image source.
The print context statement yields the following output in the python console:
{'imageArray': ['image0.jpg', 'image1.jpg', 'image2.jpg', 'image3.jpg', 'image4.
jpg', 'image5.jpg', 'image6.jpg', 'image7.jpg', 'image8.jpg', 'image9.jpg']}
But I am not able to access the imageArray at all in the template. Here are the scripts I tried to test if the array has been passed, in the template html file:
In add_category.html file:
{% for img in imageArray %}
<li>{{ img|safe }}</li>
<li>{{ img }}</li>
<p>img</p>
{% endfor %}
Also, note that the "img" inside <p> tags are also not rendered on the screen.
<script type="text/javascript">
var images = "{{imageArray|safe}}";
console.log(images);
console.log("imgx="+images[1]);
document.getElementsByTagName("img")[0].src = DJANGO_STATIC_URL+images[2];
</script>
In the above script, the first console log prints empty line in the console, while the 2nd prints "imgx=undefined"
Please suggest me ways I can use the python list as JS array. I use Django 1.8.1, but the service I would host on uses 1.7.x. So something that would work on both would be great.
You have a very peculiar structure here. imageArray() is a view, which returns a full HttpResponse; but you call it from within another view, add_category. What's more, you do nothing at all with the result; it is thrown away and never passed anywhere. So, naturally, it's always going to be blank in the template.
I'm not sure exactly what you're doing, so it's hard to know what you really want here. But I suspect that imageArray() should be a normal utility method, which simply returns a list of images:
def imgArray():
filepath = os.path.join(STATIC_PATH, "\\images")
images =[f for f in os.listdir(filepath) if f.endswith('.jpg')]
return images
Then you need to actually do something with that value in your add_category function:
def add_category(request):
...
else:
imageArray = imgArray()
return render(request, 'imgpage/add_category.html', {imageArray: imageArray})
So here is what I did:
views.py
#importing json
import json
from django.core.serializers.json import DjangoJSONEncoder
def imgArray(request):
filepath = STATIC_PATH+"\\images"
imageArray=[]
ext='.jpg'
for i in os.listdir(filepath):
if(os.path.splitext(i)[1] == ext):
imageArray.append( i )
json_list = json.dumps(list(imageArray), cls=DjangoJSONEncoder)
return json_list
def add_category(request):
# A HTTP POST?
if request.method == 'POST':
#Do something
else:
# If the request was not a POST, display the form to enter details.
imageArray = imgArray(request)
context = {'imageArray': imageArray}
return render(request, 'imgpage/add_category.html',context)
return render(request, 'imgpage/add_category.html')
And in add_category.html:
<script type="text/javascript">
var images = {{imageArray|safe}};
document.getElementsByTagName("img")[0].src = DJANGO_STATIC_URL+"images/"+images[1];
</script>
Hope this helps someone :)
Cheers!

Having trouble handling AJAX with Django Class Based View

I've been trying to switch my codes from Django function based view to class based view, but I'm having trouble understanding how to handle AJAX in Django CBV.
For example, suppose that I have this live search feature in my Django blog project.
(sorry, I tried to make it as simple as possible.)
urls.py
url(r'^search/$', search_page),
forms.py
class SearchForm(forms.Form):
query = forms.CharField()
entire_search_page.html
<form id="search-form" method="get" action=".">
{{form.as_p}}
<input type="submit" value="search" />
</form>
<div id="search-results">
{% include "just_the_result.html" %}
</div>
just_the_result.html
{% for post in post_list %}
<li>{{ post.title }}</li>
views.py
def search_page(request):
form = SearchForm()
post_list = []
if 'query' in request.GET:
form = SearchForm({'query': query})
post_list = Post.objects.filter(title__icontains=query)
if request.GET.has_key('ajax'):
variables = RequestContext(request, {
'post_list': post_list,
})
return render_to_response('just_the_result.html', variables)
else:
variables = RequestContext(request, {
'form': form,
'post_list': post_list,
})
return render_to_response('entire_search_page.html', variables)
search.js
$(document).ready(function() {
$("#search-form").submit(search_submit);
});
function search_submit() {
var query = $("#id_query").val();
$("#search-results").load(
"/search/?ajax&query=" + encodeURIComponent(query)
);
return false;
}
So basically, I'm showing the entire search page when the request is normal, while only showing the "just_the_result.html" if the request is AJAX. This works fine when I run the server, but I want to change this view to Class Based View.
This is what I have so far:
views.py
class PostSearch(ListView):
model = Post
template_name = 'app_blog/search.html'
context_object_name = 'post_list'
def get_queryset(self):
queryset = super(PostSearch, self).get_queryset()
query = self.request.GET.get('query')
if query:
return queryset.filter(title__icontains=query)
else:
return queryset
I guess this works correctly when the request is normal. However, I have no idea what to do when the request is an AJAX request! In the function based view, I could just return different templates and variables depending on whether the request is AJAX or not, but I don't think this is necessary or even possible in CBV. Also, one more question. I've been reading about RESTful design lately. Is my code above considered as "RESTful"?? I have trouble understanding how REST API is used exactly.
There are a lot of solutions to this problem, just search around:
http://django-braces.readthedocs.org/en/latest/other.html#ajaxresponsemixin
https://docs.djangoproject.com/en/1.5/topics/class-based-views/mixins/#more-than-just-html
Using Django class-based views, how can I return a different template if request.is_ajax

Categories

Resources