AJAX username validation in Django - ajax

I want to create asynchronous username validation,
where upon change of the value of the username input, the database is accessed to see if that username is valid for use. So far I have this code, which doesn't seem to work. Please help me in finding out where things went wrong. Thanks!
My HTML:
<div>Username</div>
<input type="text" name="id" id="id">
<div id="idval"></div>
My Script:
<script>
function CheckId() {
$.get('/signup/', {username: $(this).val()},
function(data){
if(data == "True"){
$('#idval').html("You may use this ID");
} else {
$('#idval').html("Unavailable");
}
});
}
function onChange(){
$("#id").change( function() {CheckId()});
}
$(document).ready(onChange);
</script>
My View:
def signup(request):
if request.method == "GET":
p = request.GET.copy()
if p.has_key('username'):
name = p['username']
if User.objects.filter(username__iexact=name):
return HttpResponse(False)
else:
return HttpResponse(True)

in CheckId() $(this).val() isn't going to work. You need $('#id').val()
See this discussion of how the this keyword works

Related

I am not sure if my Vue code is efficient

I am a beginner in Vue and I am wondering if I can get an insight from experienced developers here about my Vue codes. I just want to ask for help to know if my Vue approach is efficient and proper. (Project is running on Laravel)
The Case:
Let us say I have 2 tables in DB
(1) stores
(2) ad_accounts
Then we have 2 web pages to present these tables' data and execute CRUD functions with it
(1) store.blade.php
(2) adaccount.blade.php
Each page is running a Vue component
(1) Stores.vue
(2) AdAccounts.vue
I am using Vuex for store management.
Within store.js, I would have set of actions for CRUD for each vue component.
Now I realized that I have series of actions that actually does the same thing. For example, I have an action to add stores, and another action to add Ad accounts. Their only difference is that they are calling a different Laravel route.
So it seemed to me that my code was unnecessarily long and a bit expensive. To resolve, I decided to write my actions in a form of template. So this is what I did:
In store.js, I created an action for each CRUD function to be used as template
In Stores.vue and AdAccounts.vue, if I need to execute a CRUD function, I would use a method to call the corresponding action from store.js and provide the Laravel route as part of the action's payload
I have states and corresponding getters for returning these states in Stores.vue and AdAccounts.vue
Each action has a dedicated mutation that alters the approriate state
states and getters are mapped in each Vue component in order to access and use them
Is this approach efficient and proper? I have sample methods and actions below for reference.
Stores.vue
<template>
<div>
<form #submit.prevent="addData('stores/add')">
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</template>
<script>
export default {
methods: {
addData: function(url) {
this.payload.url = url
if(
this.payload.requestData.store_name == "" &&
this.payload.requestData.store_token == ""
) {
this.payload.isErr = true;
this.payload.errMsg = "ERROR: Could not continue due to some invalid or missing data. \nPlease check your entries and try again or contact your administrator.";
this.$store.dispatch('addData', this.payload)
}
else {
this.payload.isErr = false;
this.$store.dispatch('addData', this.payload)
this.readDataAll('stores/all', 'store');
}
this.cleanOnModalDismiss(this.$refs.addModal, this.refreshRequestData)
}
}
}
</script>
AdAccounts.vue
<template>
<div>
<form #submit.prevent="addData('ad_accounts/add')">
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</template>
<script>
export default {
methods: {
addData: function(url) {
this.payload.url = url
if(
this.payload.requestData.ad_id == "" &&
this.payload.requestData.ad_name == ""
) {
this.payload.isErr = true;
this.payload.errMsg = "ERROR: Could not continue due to some invalid or missing data. \nPlease check your entries and try again or contact your administrator.";
this.$store.dispatch('addData', this.payload)
}
else {
this.payload.isErr = false;
this.$store.dispatch('addData', this.payload)
this.readDataAll('ad_accounts/all', 'adaccounts');
}
this.cleanOnModalDismiss(this.$refs.addModal, this.refreshRequestData)
}
}
}
</script>
store.js
export default new Vuex.Store({
actions: {
addData (commit, payload) { // insert a record to DB
try {
if(payload.isErr == true) {
commit('SHOW_ERRORS', {messageType: "alert-danger", errorMessage: payload.errMsg});
} else {
axios.post(payload.url, payload.requestData)
.then(response=>{
if(response.status == 200) {
var err_msg = "";
if(response.data.success !== null) {
response.data.messageType = "alert-info"
response.data.actionMessage = response.data.success
commit('ADD_DATA', response.data);
} else {
response.data.messageType = "alert-danger"
for(var i=0; i<response.data.error.length; i++) {
err_msg += response.data.error[i] + "\n"
}
response.data.actionMessage = err_msg
commit('ADD_DATA', response.data);
}
}
else {
commit('SHOW_ERRORS', {messageType: "alert-danger", errorMessage: "ERROR: Connection status set to '" + response.headers.connection + "' due to error " + response.status + " " + response.statusText + ". \nPlease contact your administrator."});
}
})
}
} catch (error) {
commit('SHOW_ERRORS', {messageType: "alert-danger", errorMessage: error})
}
}
}
}

Bootstrap Typeahead with AJAX source (not working)

I'm trying to implement a search bar dropdown using bootstrap v3.0.0 with typeahead.js.
My search bar will take a student's firstname and lastname. I'm using a MYSQL database which consists of a table called practice with afirstname, alastname, aid as columns. The search bar should not only contain the firstname and lastname in the dropdown, but also the id associated with it in a second row. I've read all the examples on the typeahead.js page and I'm unable to do it with ajax call.
Below is the code of my index.php
JS
<script type="text/javascript">
$(document).ready(function() {
$('.cr.typeahead').typeahead({
source: header: '<h3>Select</h3>',
name: 'accounts',
source: function (query, process) {
return $.getJSON(
'localhost/resultly/source.php',
{ query: query },
function (data) {
return process(data);
});
});
});
</script>
HTML:
<body>
<div class="container">
<br/><br/>
<input type="text" name="query" class="form-control cr typeahead" id="firstname" />
<br/><br/>
</div>
</body>
Code for source.php : This should return the firstname and lastname from my database in the form of a json string or object?
<?php
$query = $_POST['query'];
try {
$conn = new PDO('mysql:host=localhost;dbname=practice','root','');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $conn->prepare("SELECT * FROM actualtable WHERE afirstname LIKE '%($query)%'");
$stmt->execute();
}
catch (PDOException $e) {
echo 'ERROR:' . $e->getMessage();
}
foreach ($stmt as $row) {
$afirstname[] = $row['afirstname'];
$alastname[] = $row['alastname'];
}
echo json_encode($afirstname);
echo json_encode($alastname);
?>
result:
http://oi41.tinypic.com/50moi1.jpg
Nothing shows up. I've tried adding a prefetch:
prefetch: {
url: 'localhost/resultly/source.php',
filter: function(data) {
r1 = [];
for (var i = 0; i < data.length; i++) {
r1.push({
value: data[i].afirstname,
tokens: [data[i].afirstname, data[i]alastname],
afirstname: data[i].afirstname,
alastname: data[i].alastname,
template: '<p>{{afirstname}} - {{alastname}}</p>',
});
}
return r1;
}
}
Please do provide a solution or an example which I could refer.
Update:
The source.php should return a list of json encoded data. I debugged by looking at the output that the source.pho created. What I did wrong was whenever I was supposed to put a url I did localhost/source.php instead of just source.php.
Solution provided by Bass Jobsen works and now I have run into another problem.
I'm using
if(isset($_POST['query']))
{ $q_uery = $_POST['query'];
$query = ucfirst(strtolower($q_uery))};
to take the user's data and use it for searching logic
$stmt = $conn->prepare("SELECT * FROM actualtable WHERE afirstname LIKE '%($query)%'");
The updated source.php is http://pastebin.com/T9Q4m10g
I get an error on this line saying Notice: Undefined variable: stmt I guess the $query is not being initialized. How do I get this to work. Thanks.
Update 3
I used prefetch: instead of 'remote:' that did all the matching.
Your return is not correct:
echo json_encode($afirstname);
echo json_encode($alastname);
See for example Twitter TypeAhead.js not updating input
Try echo json_encode((object)$stmt);, see: typeahead.js search from beginng
Update
I tried echo json_encode((object)$stmt);still doesn't work.
Do you use any kind of debugging? What does? source.php return? Try to follow the steps from
typeahead.js search from beginng without the filter.
html:
<div class="demo">
<input class="typeahead" value="" type="text" spellcheck="off" autocomplete="off" placeholder="countries">
</div>
javascript:
$('.typeahead').typeahead({
remote: 'http://testdrive/source.php?q=%QUERY',
limit: 10
});
php (source.php):
<?php
$people = array();
$people[] = array("lastname"=>"Inaw",
"firstname"=>"Dsajhjkdsa");
$people[] = array("lastname"=>"Dsahjk",
"firstname"=>"YYYsgbm");
$people[] = array("lastname"=>"Dasjhdsjka",
"firstname"=>"JHJKGJ");
$datums = array();
foreach($people as $human)
{
$datums[]=(object)array('value'=>$human['firstname'],'tokens'=>array($human['firstname'],$human['lastname']));
}
echo json_encode((object)$datums);
This should work
update2
Thanks, it worked. How do I display 2 or more 'value'?
add some values to your datums in source.php:
foreach($people as $human)
{
$datums[]=(object)array
(
'value'=>$human['firstname'],
'tokens'=>array($human['firstname'],$human['lastname']),
'firstname'=>$human['firstname'],
'lastname'=>$human['lastname']
);
}
firstname and lastname now are field you csn use in your templates
Add a template and template engine to your javascript declaration:
$('.typeahead').typeahead({
remote: 'http://testdrive/source.php?q=%QUERY',
limit: 10,
template: [
'<p>{{firstname}} - {{lastname}}</p>'
].join(''),
engine: Hogan
});
The above make use of https://github.com/twitter/hogan.js. You will have to include the template engine by javascript, for example:
<script src="http://twitter.github.io/typeahead.js/js/hogan-2.0.0.js"></script>
It is working for me. please follow below step.
Please add below Js and give proper reference.
bootstrap3-typeahead
--- Ajax Call ----
$("#cityId").keyup(function () {
var al = $(this).val();
$('#cityId').typeahead({
source: function (valuequery, process) {
var states = [];
return $.ajax({
url: http://localhost:4000/GetcityList,
type: 'POST',
data: { valueType: "", valueFilter: valuequery },
dataType: 'JSON',
success: function (result) {
var resultList = result.map(function (item) {
states.push({
"name": item.Value,
"value": item.Key
});
});
return process(states);
}
});
},
});
});
---- Cs Code ---
public JsonResult SearchKeyValuesByValue(string valueType, string valueFilter)
{
List<KeyValueType> returnValue = SearchKeyValuesByValue(valueType, valueFilter);
return Json(returnValue);
}
Auto suggest of Bootstrap typehead will get accept only "name" and "value" so create reponse accordinly

display login error using Ajax and Grails

I'm developing a little application using Grails + Twitter BootStrap for the UI. In my index page, I have a form to login :
<g:form controller="user" action="login" id="form-login">
<h2>Please, log in</h2>
<g:textField name="userName" placeholder="Email address"/>
<g:passwordField name="password" type="password" placeholder="Password"/>
<button id="submitConnection" type="submit">Connection</button>
</g:form>
Here, is my user controller :
def login(){
String userName = params.userName
String password = params.password
User user = userName ? User.findByUserName(userName) : null
//If login succeed
if(user?.password == password){
session.user = user
redirect(action: 'index')
}
//If login failed
else{
render 'Email or password incorrect.'
}
}
I'm trying to use Ajax through JQuery. I'm not familiar with Ajax/JQuery, so I'm not sure that I'm doing well things. In fact, I would like to do an Ajax request on click on the submit button. So I wrote this in my js :
$('#submitConnection').click(function() {
var request = $.ajax({
url: "/user/login",
data: { userName: "dummy", password: "dummy"}
});
request.done(function ( data ) {
if( data ) {
console.log(data);
}
});
request.fail(function(jqXHR, textStatus) {
alert( "Request failed: " + textStatus );
});
});
I would like when the login fails to fill in a div with an error message like 'login failed' and if it succeeds, just redirect to the index. I think I have to use JQuery to do this. Am I wrong ?
I don't really know what I have to modify/add in my controller to send something to the Ajax.
Thanks in advance for your help.
Best regards.
First, dealing with your controller, sending a redirect back to an ajax request won't really suffice. And when the auth fails, how does your javascript know? So we should adjust your controller code a bit:
def login(){
String userName = params.userName
String password = params.password
User user = userName ? User.findByUserName(userName) : null
//If login succeed
if(user?.password == password){
session.user = user
render(contentType: 'text/json') {
[success: true, message: 'Login successful']
}
}
//If login failed
else{
render(contentType: 'text/json') {
[success: false, message: 'Email or Password incorrect']
}
}
}
Now as to your javascript, I'd start here:
$('#submitConnection').click(function(e) {
e.preventDefault(); // prevents normal event of button submitting form
$.post("/user/login", {userName: "dummy", password: "dummy"}, function(data) {
if (data.success) {
window.location = "some/path";
} else {
$("#error-message").html(data.message).show();
}
});
});
And then your HTML:
<g:form controller="user" action="login" id="form-login">
<h2>Please, log in</h2>
<div id="error-message" class="hide"></div>
<g:textField name="userName" placeholder="Email address"/>
<g:passwordField name="password" type="password" placeholder="Password"/>
<button id="submitConnection" type="submit">Connection</button>
</g:form>

How to pass AJAX arguments to the extbase action?

Now that I managed to get values from the database, I want to specify more what I want to be passed.
From a select box that reacts to the event function below, I want to read out a value (uid of a record) and pass it to my ajaxAction:
var uid;
$('#mySelectBox').change(function() {
arguments = $(this).attr('value');
var uri = '<f:uri.action arguments="{uid: '+uid+'}" action="ajax" controller="Mycontroller1" pageType="89657201" />';
jQuery.getJSON(uri, function(result) {
// do something
});
});
I tried it with arguments, no idea if that is the right way. Additionally, as Marcus Biesioroff suggested, I should save my JS into a separate file, but then I would have to write the uri on my own instead of the Fluid way, right?
My ajaxAction looks like this:
public function ajaxAction($uid) {
$dataFromRepo = $this->myRepository->findByUid($uid);
$resultArray = array(
"field1" => $dataFromRepo->getField1(),
"field2" => $dataFromRepo->getField2(),
"field3" => $dataFromRepo->getField3(),
"field4" => $dataFromRepo->getField4(),
);
return json_encode($resultArray);
}
I'm sure that the uid is not passed correctly, everything else works.
There are some mistakes:
You can't break vievhelper's syntax with JS even if it's placed in view, you need to pass full path of the action from <f:uri.action />
you cannot place this JS in view, because it contains curly brackets there's other description of the issue
you need to call ajax function from external file and pass to it action's link and uid separately, and then add the
in the view:
<script type="text/javascript">
var actionsPathFromViewHelperSetInTheView
= '<f:uri.action action="ajax" controller="Mycontroller1" pageType="89657201" />';
</script>
<script type="text/javascript" src="path/to/ext/Public/yourExternal.js"></script>
<!-- of course this field may/should be created with Fluid's viewhelper -->
<select id="mySelectBox" onchange="performAjaxCall(this)">
<option value="1">Item 1</option>
<option value="2">Item 2</option>
<option value="3">Item 3</option>
</select>
in the yourExternal.js (of course you need to change tx_yourextkey_yourplugin prefix to your own)
function performAjaxCall(selectFieldObj) {
$.ajax({
url: actionsPathFromViewHelperSetInTheView,
data:{
"tx_yourextkey_yourplugin[uid]":selectFieldObj.value
},
success:function (data) {
// do something with your json
alert('Load was performed.');
}
});
}
in your controller:
public function ajaxAction() {
// try to always validate the incoming arguments
if (!$this->request->hasArgument('uid') || intval($this->request->getArgument('uid')) == 0) {
header('HTTP/1.1 400 Bad Request');
return json_encode(array('error'=> 'Bad request'));
}
$uid = intval($this->request->getArgument('uid'));
$dataFromRepo = $this->myRepository->findByUid($uid);
if ($dataFromRepo == null) {
header('HTTP/1.1 404 Not found');
return json_encode(
array('error'=> 'Not found or you have no access or something else... happens...')
);
}
$resultArray = array(
"field1" => $dataFromRepo->getField1(),
// etc...
);
return json_encode($resultArray);
}

http 403 error with django and ajax

I'm working my way through 'Django 1.0 Web Site Development' and encountered a problem when using forms. The server complained about something concerning 'csrf'. I could solve it by adding {% csrf_token %} right after the form-tag. I already read the documentation at djangoproject.com but I have to admit that I don't fully understand what exactly is happening here. I don't use the middleware classes.
The real problem started when I got to ajax. I followed the instructions in the book to the letter but the server started complaining:
"POST /save/?ajax HTTP/1.1" 403 2332
Here is the code that might cause the trouble:
function bookmark_save() {
var item = $(this).parent();
var data = {
url: item.find("#id_url").val(),
title: item.find("#id_title").val(),
tags: item.find("#id_tags").val()
};
$.post("/save/?ajax", data, function (result) {
if (result != "failure") {
item.before($("li", result).get(0));
item.remove();
$("ul.bookmarks .edit").click(bookmark_edit);
}
else {
alert("Failed to validate bookmark before saving.");
}
});
return false;
}
'/save/&ajax' is being handled by
if ajax:
return render_to_response('bookmark_save_form.html', variables)
Here the bookmark_save_form.html:
<form id="save-form" method="post" action="/save/">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="save" />
</form>
As far as I understand things, I have to pass a csrf_token with the POST request. But I don't have a clue how.
Any advise on this would be great.
I am currently working through this book as well and ran into the exact same problem, BTW. Not for the first time either! Essentially what is happening is that the csrf token is not being passed via the Ajax request. So, the short and simple answer is that you need to include the csrf token is your ajax call. This is accomplished via this code block: https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#ajax
jQuery(document).ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
I then included this as a .js file in my user_page.html. After that, I could make Ajax calls with impunity!
I pulled this from a project already done. This is a contact form template. Mind you this is for django. Also please refer to the django book http://www.djangobook.com/en/2.0/ . All my questions have been answered by this book. It goes over everything. This shows exactly how to put in the csrf token (in a template):
<head>
<title>Contact Us</title>
</head>
<body>
<h1>Contact us</h1>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<ul>
{{ form.as_ul }}
</ul>
<input type="submit" value="Submit">
</form>
</body>
Also, change your value to submit instead of save, and instead of /save/ for action use post.....that might make it work.
I am working through the book and just ran into the same problem. Here is the simplest solution, which has the benefit of not disabling Django's csrf protection or having to include decorators or fiddle with utilities like 'ensure_csrf_cookie'. It simply passes the token:
In the .js file you created to hold your custom jquery scripts, add the following pair to your 'data' var in in your bookmark_save() function:
csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].val()
So the resulting bookmark_save function looks like this:
function bookmark_save() {
var item = $(this).parent();
var data = {
url: item.find("#id_url").val(),
title: item.find("#id_title").val(),
tags: item.find("#id_tags").val(),
csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].val()
};
$.post("/save/?ajax", data, function (result) {
if (result != "failure") {
item.before($("li", result).get(0));
item.remove();
$("ul.bookmarks .edit").click(bookmark_edit);
}
else {
alert("Failed to validate bookmark before saving.");
}
});
return false;
}
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def my_view(request):
...
Create a Javascript file. I do not know how to format the code - sorry. Then load it after Jquery.
It is described here

Resources