Ajax to login users...callback function not working - django

This is my second foray into Ajax and I'm not quite sure how to pull this off.
So I have a modal window that opens when an anonymous user attempts to perform a certain task. The window contains a user signup form that I then $.post to my Django login view. If username/password are valid, user is logged in an status code of 1 is returned as the response. IF not, a status of 0 is returned.
When I try to do it outside of js, it works. However, within my script, it fails. I think that it has to do with the response content_type and how I'm interpreting it. I'm not sure.
def login_async(request):
if request.method=='POST' and len(request.POST['username'])<20 and len(request.POST['password'])<20:
username=request.POST.get('username', '') #probably need to script tags here
password=request.POST.get('password', '')
user=auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request,user)
status=1
response=HttpResponse()
response['Content_Type']="text/html"
response.write(status)
return response
else:
status=0
response=HttpResponse()
response['Content_Type']="text/html"
response.write(status)
return response
$('input#login').click(function(event){
$.post("/login_async/", {username:$('input[name=username]').val(), password:$('input[name=password]').val()}, //could also use $(this).serialize() here to capture all form inputs
function(data){
if(data==1){
$('#login').dialog("close");
}
});
});
What's the problem here? I initially tried to return the response as JSON but I couldn't figure out how to make serialize.serializers("json",status) work. I kept getting an error.
One last question...
If I get a valid status (user is signed in), that will influence the behavior of modal windows on the page. The modal windows open based on logged in status. If a user is signed in, one set of windows open on a click event, and vice versa. This toggle is dependent on Django context {% user.is_authenticated %}.
That context renders only once right, on page load? Can I do anything to communicate the status change to the modal windows that's secure from easy hacks?

It should be Content-Type. If that doesn't fix your problem, try adding a dataType parameter at the end of the $.post call.
$.post("/login_async/", {}, function(data){
// fancy stuff
}, "html");

Yeah I thought it over more and realized that I should just unbind the existing click event handlers on the modal windows and then bind new event handlers depending on the ajax response.
I love programming

Related

How do I check if a user has entered the URL from another website in Django?

I want an effect to be applied when a user is entering my website. So therefore I want to check for when a user is coming from outside my website so the effect isnt getting applied when the user is surfing through different urls inside the website, but only when the user is coming from outside my website
You can't really check for where a user has come from specifically. You can check if the user has just arrived on your site by setting a session variable when they load one of your pages. You can check for it before you set it, and if they don't have it, then they have just arrived and you can apply your effect. There's some good examples of how sessions work here: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Sessions
There's a couple of ways to handle this. If you are using function based views, you can just create a separate util function and include it at the top of every page, eg,
utils.py
def first_visit(request):
"""returns the answer to the question 'first visit for session?'
make sure SESSION_EXPIRE_AT_BROWSER_CLOSE set to False in settings for persistance"""
if request.session['first_visit']:
#this is not the first session because the session variable is used.
return False
else:
#This is the first visit
...#do something
#set the session variable so you only do the above once
request.session[first_visit'] = True
return True
views.py
from utils.py import first_visit
def show_page(request):
first_visit = first_visit(request)
This approach gives you some control. For example, you may not want to run it on pages that require login, because you will already have run it on the login page.
Otherwise, the best approach depends on what will happen on the first visit. If you want just to update a template (eg, perhaps to show a message or run a script on th epage) you can use a context processor which gives you extra context for your templates. If you want to interrupt the request, perhaps to redirect it to a separate page, you can create a simple piece of middleware.
docs for middleware
docs for context processors
You may also be able to handle this entirely by javascript. This uses localStorage to store whether or not this is the user's first visit to the site and displays the loading area for 5 seconds if there is nothing in localStorage. You can include this in your base template so it runs on every page.
function showMain() {
document.getElementByID("loading").style.display = "none";
document.getElementByID("main").style.display = "block";
}
const secondVisit = localStorage.getItem("secondVisit");
if (!secondVisit) {
//show loading screen
document.getElementByID("loading").style.display = "block";
document.getElementByID("main").style.display = "none";
setTimeout(5000, showMain)
localStorage.setItem("secondVisit", "true" );
} else {
showMain()
}

Flask POST request and javascript

Is it possible to POST data with flask_sqlalchemy and prevent a page reload?
I have a webpage with a form. The form only appears after a function, activated by an onclick event, is run. I want my user to be able to submit information using the form, and see the form only empty and the rest of the page remain unchanged.
I have already tried return '', 204 but this does not fix the issue.
Use Javascript or jQuery:
Javascript example:
function resetFormPause() {
myVar = setTimeout(resetForm, 250);
}
function resetForm() {
document.getElementById('form').reset();
}
Add onclick='resetFormPause()' to your submit button and use <form id='form'>.
We use setTimeout() to allow the data to be sent. If we merely add the resetForm() function, we will delete the data that we want to send. If we have small text to send, 250ms is plenty of time. If we have larger data, then we use the same idea, but we have to (a) allow more time, or (b) use an event to trigger the execution of resetForm().

How to know the url path from a view function of another url in django?

I have a set of URLs:
/home/
/register/
/login/
/puzzle/<pk>
All of the first 3 urls can make a request to the last url.
Is it possible to know which urls are calling the /puzzle/<pk>, from the view function attached to it?
Edit
So the problem is it's a puzzle game and every user has a level. If he completes a certain level only then he can proceed to the next level. Therefore, if a user has completed level 3, I'll always show him the html page with the url /puzzle/4.
The flow is :
A user registers. His level is 0. As soon as he registers he'll be redirected to puzzle/1/
A user logs in. If he has completed level x, as soon as he logs in he'll be redirected to /puzzle/x+1.
I've handled these 2 types.
But the problem is, say the user is in the page /puzzle/1/. Now if he manually changes the url to /puzzle/2/, from the view function attached to /puzzle/<pk>/, how can I handle the above case?
I believe you're looking for request.resolver_match. You could access the view name with request.resolver_match.view_name
Edit:
If I understand your model correctly, you need some logic like the following. You'll need to adjust the view name and params in reverse.
def view(request, puzzle_level):
if puzzle_level != request.user.level_completed + 1:
return redirect(
reverse(
'puzzle_view_name',
kwargs={'puzzle_level': request.user.level_completed + 1},
)
)
...

Rails controllers, rendering view from different controller, saving form inputs and error messages

Two controllers: Users and Tasks.
Main page for Users = Users/user_id.
Form on main page used to input data into tasks model.
This process handled by the Tasks Controller.
Successful input: redirect and load tasks from database, OK, all working.
Unsuccessful input, just need to refresh main page so we keep form input and specialised (non-flash) error messages
I can't seem to get the Tasks Controller to deliver the original page. Error is Missing template users/1(which is the correct syntax if I were to visit in my browser).
Should I be calling an action and passing params? Any help for this beginner would be really appreciated.
def create
#task = current_user.tasks.build(task_params)
if #task.save
flash[:success] = "New task created!"
redirect_to user_url(current_user)
else
flash[:error] = "Task not saved! Please see guidance by form labels"
render "users/#{current_user.id}"
end
end
private
def task_params
params.require(:task).permit(:label, :address, :content)
end
end
users/1 is not a template, it's a path. users/show is the template in this case.
mind that the only reason to use render is to render a template in the scope of your current controller action rather than the normal one.
i.e. you probably need to have #user etc set, or the users/show template will be upset about missing variables.
In this case it might be easier just to redirect_to user_path(id) and allow the users/#show controller action set up the #user variable etc.

How to check user is authenticated properly in Django and Backbone.js

I want to build single page application using Backbone.js and Django.
For checking user is authenticated or not,
I wrote a method get_identity method in django side.
If request.user.is_authenticated is true it returns request.user.id otherwise it returns Http404
In backbone side, I defined a User model and periodically make ajax call to get_identity.
I think it is the most straightforward way to check user is authenticated or not.
For learning single page application, I want to do this operation more sensible and efficient than this way if it is possible.
So what is your advice about this? When I search Django+Backbone.js + User Authentication, I couldn't find any satisfactory result and I really wonder how people do this simple operation.
Any help or idea will be appreciated.
(By the way I tried to read cookie periodically but HttpOnly True flagged cookies are not reacheable in client side.)
Django views.py
def get_identity(request):
if not request.user.is_authenticated():
raise Http404
return HttpResponse(json.dumps({'identity':request.user.id}), mimetype="application/json")
Backbone.js side.
updateUser:function(){
var $self=this;
$.ajaxSetup({async:false});
$.get(
'/get_identity',
function(response){
// update model...
$self.user.id =response.identity;
//check user every five minutes...
$self.user.fetch({success: function() {
$self.user.set('is_authenticated',true);
setTimeout($self.updateUser, 1000*60*1);
}
},this);
}).fail(function(){
//clear model
$self.user.clear().set($self.user.defaults);
setTimeout($self.updateUser, 1000*60*1);
});
$.ajaxSetup({async:true});
}
I had var is_authenticated = {{request.user.is_authenticated}}; in my base.html
and used the global variable to check.
I'm in pursuit of better solution (because this breaks when you start caching).
But you might find it useful.