Learning Django by Example(3): Just works
django pythonIn the last post, we succeeded to post the Javascript objects via JSON to the server, the data is to be serialized to the database in this section.
Before we move on, let’s remove some bumps in our way, the database scheme is modified in this way:
class Book(models.Model):
isbn = models.CharField(maxlength=10, primary_key=True)
pub_date = models.DateField('data published')
The reasoning lies in that AWS returns ISBN-10 as ASIN, we may take advantage of
this. Another fix is to replace DateTimeField
with DateField
for pub_date
.
Django does not support
seamless database scheme refactory
so far. So we just dropped the database and re-generate it as described in the
tutorial. The username/password for new database is set as admin/gelman
as
common practice.
It is quite annoying that a 500 error returned without any reason, Django server ate the exception due to the nature of Web server. We could wrap the suspicious buggy code with try/except block like this:
try :
// database access
except :
print sys.exc_info()[0]
Well, InterfaceError or IntegrityError may suggest bugs in the database operations, but where? Interactive shells are our best friends, you can either use pdb or the shell provided by the Django.
Oh, my fault, I forgot the return value of get_or_create
is a tuple, instead
of the object; and for many to many relation, we could not simply set a list as
its value, we need to use add
method after the object is constructed:
for item in simplejson.loads(request.POST['items']):
publisher, created = Publisher.objects.get_or_create(name=item['publisher'])
authors = [Author.objects.get_or_create(name=au) for au in item['authors']]
authors = [author for (author, created) in authors];
y,m,d = [int(x) for x in item['pub_date'].split('-')]
pub_date = date(y, m, d)
book, created = Book.objects.get_or_create(isbn=item['isbn'], name=item['title'],
pages=300, pub_date=pub_date, publisher=publisher)
book.authors.add(*authors)
#print sys.exc_info()[0]
return HttpResponseRedirect('/admin/library/book/')
At the exit, we just redirect the browser to a new URL.
It seems the database is updated, but the page is not redirected. Since the POST
operation is launched in an AJAX request, we need to send JSON object as the
response. In server side, simplejson.dump
is used:
xhr = {'succeed': [], 'failed': []};
for item in simplejson.loads(request.POST['items']):
# ... ....
try :
book, created = Book.objects.get_or_create(isbn=item['isbn'], name=item['title'],
pages=300, pub_date=pub_date, publisher=publisher)
book.authors.add(*authors)
except :
xhr['failed'].append(item['title'])
xhr['succeed'].append(item['title'])
return HttpResponse(simplejson.dumps(xhr), mimetype='text/javascript');
In client side, we evaluate the JSON string then populate the DOM nodes:
dojo
.xhrPost({
url: dojo.byId("book_form").action,
content: { items: dojo.toJson(formdata) },
})
.addCallback(function (response) {
var result = dojo.fromJson(response);
var messages = dojo.query("ul[@class=messagelist]")[0];
dojo.forEach(result.failed, function (item) {
var msg = document.createElement("li");
msg.innerHTML =
"<li><em>" + item + "</em> <strong>failed</strong> to add.</li>";
messages.appendChild(msg);
});
dojo.forEach(result.succeed, function (item) {
var msg = document.createElement("li");
msg.innerHTML = "<em>" + item + "</em> successfully added.";
messages.appendChild(msg);
});
});
The final result looks like this:
Check r19 for details.