2

I want to send a very basic post request using AJAX to the same url. It should take the username and check it against the DB to see if a user with that name exists already, returning a string to that effect. There is something wrong with the javascript function that is sending the request:

function usernameCheck(){
$.post("http://omnicloud.me/signup", 
  {username: $("#username").value}, 
  function(response){
    if(response=="true"){
       $('#passAlert').innerHTML("Sorry, that username is already taken")
    }
});

return !($('#passAlert').value == "Sorry, that username is already taken")
}

If the person is just loading the signup view, it returns the page, otherwise, it is being called to check for a user existing:

def signup(request):
    if request.method == 'GET':
        return render_to_response('signup.html', context_instance=RequestContext(request))
    else: 
    #query db for user with username provided in POST, return if it exists
        user = User.objects.get(username=request.POST["username"]) 
        if user is not None:
            return HttpResponse("true")
        else:
            return HttpResponse("false")

Is there anything you can see as to why the JS is being ignored? Firebug found nothing.

Chris
  • 11,819
  • 19
  • 91
  • 145
  • possible duplicate of [GET return undefined value out function](http://stackoverflow.com/questions/6762010/get-return-undefined-value-out-function) – Quentin Nov 22 '11 at 08:18
  • Moreover what is that: `$("username").value`? Should be something like `$('#username').val()` or `$('.username').val()` etc. – dfsq Nov 22 '11 at 08:21
  • Chris, basically there are two errors: you are closing the $.post statement a bit too soon and the response has to be compared to 'true'. Check my answer below. That's all! – zequinha-bsb Nov 22 '11 at 08:49

3 Answers3

5

Ajax means "Asynchronous JavaScript and XML" so it does not wait for $.post to finish but just goes on within your code.

To solve this issue you have to use a callback function:

http://api.jquery.com/jQuery.post/

jQuery.post( url [, data] [, success(data, textStatus, jqXHR)] [, dataType] )

url A string containing the URL to which the request is sent.

data A map or string that is sent to the server with the request.

success(data, textStatus, jqXHR) A callback function that is executed if the request succeeds.

dataType The type of data expected from the server. Default: Intelligent Guess (xml, json, script, or html).

Sample:

function usernameCheck(){
    $.post("http://omnicloud.me/signup", 
      {username: $("#username").val()}, 
      function(response){
        if(response=="true"){
           $('#passAlert').html("Sorry, that username is already taken")
        }
    });
}

You might also pass an anonymous callback:

function usernameCheck(successCallback){
    $.post("http://omnicloud.me/signup", 
      {username: $("#username").val()}, 
      function(response){
       if(response=="true") successCallback();
    });
}

// Somewhere else in your code:

usernameCheck(function(){
  $('#passAlert').html("Sorry, that username is already taken")
});
jantimon
  • 36,840
  • 23
  • 122
  • 185
  • so to save the response I would define `var exists` above the post, then put a simple function that just assigns the value to exists? – Chris Nov 22 '11 at 08:20
  • On a sidenote, it also looks like the JQuery selectors and methods are wrong. I'm guessing it should be `$("#username").val()` – njr101 Nov 22 '11 at 08:23
  • `if(exists){` is executed before the ajax request is complete – jantimon Nov 22 '11 at 08:24
  • @Ghommy how can I make sure that it waits for a response? I would throw the rest of the code into the callback function, but then it would just return from that function and not checkUsername(). I updated the code with your advice. – Chris Nov 22 '11 at 08:25
  • You can make your queries synchronous, so that they wait for the return - but async stuff is much nicer. Here: http://stackoverflow.com/questions/133310/how-can-i-get-jquery-to-perform-a-synchronous-rather-than-asynchronous-ajax-re – Spacedman Nov 22 '11 at 10:16
3

First, you have some problems in your view. You need to check whether the POST is from AJAX or a standard POST; otherwise, you won't be able to actually add the user later. (Really the AJAX part should be it's own view, since it really isn't part of the signup process per se, but rather a validation check. Later, you might actually want create a user via AJAX, and you wouldn't be able to because the view wouldn't be able to distinguish between the two different AJAX requests).

Next, get doesn't return None when the object doesn't exist; it raises an ObjectDoesNotExist exception. So, your if statement there won't work; you must use a try block instead.

I've updated your view below, accordingly:

def signup(request):
    if request.method == 'GET':
        return render_to_response('signup.html', context_instance=RequestContext(request))
    elif request.is_ajax(): 
        # query db for user with username provided in POST, return if it exists
        try:
            user = User.objects.get(username=request.POST["username"]) 
        except User.DoesNotExist:
            return HttpResponse("false")
        else:
            return HttpResponse("true")
    else:
        # Normal post, add new user
Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • Ah, well I had an adduser view to handle user creation, but I guess this works better! I wouldn't have to create them using AJAX because they'd have to be redirected to their profile anyway, but I will keep that in mind! Thanks! – Chris Nov 22 '11 at 16:14
-2

EDIT: make sure the response sends back a STRING true or a STRING false

EDIT: the response IS SENDING BACK A STRING true or A STRING false

function usernameCheck(){
    var exists;
    $.post("http://omnicloud.me/signup", { username: $("#username").val() }, 
      function(response){
         exists = (response == 'true');
         if(exists){
             $('#passAlert').innHTML = "Sorry, that username is already taken";
             return false;
         } else {
             return true;
         }
    });
zequinha-bsb
  • 719
  • 4
  • 10
  • the method usernameCheck won't return true/false – jantimon Nov 22 '11 at 08:39
  • That answer is not helping at all, because obviously the person asking the question and the one giving this answer both need to better understand asynchronicity (see Ghommey answer). – matehat Nov 22 '11 at 16:14