Tutorial: Learning the DB-API and ORM
Posted: March 20th, 2010 | Author: Adam | Filed under: Django, Python, programming | No Comments »So far in the tutorial we’ve started our project, setup the database, enabled the admin interface, created models for our blog. We’re going to slow down on actually developing our blog and talk about exactly how we get to the data we’ve stored in the database so far. The Admin Interface is great but, it doesn’t provide good programtic access to the data. Let’s open up a python shell but, we’re going to do it a special way when working with Django. From the command line in our root project directory (blog/)
$ python manage.py shell Python 2.5 (r25:51918, Sep 19 2006, 08:49:13) [GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>>
Now this might look like a normal Python shell because, well it is. We’ve just loaded up some stuff in the background like path information to make our lives a bit easier. Now we have two models that we created in the application “main”. Let’s load those up in the shell.
>>> from main.models import Category >>> from main.models import BlogPost
Before we get too deep here, I want to mention that everything that we do in the shell we can do in our application. It’s the same thing. So any manipulation we make here we can use the exact same code anywhere in our application. The shell is a great way to test out ideas and algorithms before we put that code into our application. We have our two models loaded up lets play with the built in “objects” Manager.
>>> BlogPost.objects.all() [<BlogPost: Our First Post>] >>> Category.objects.all() [<Category: Books>]
For both of our models we are calling the function all() in the object manager. This will return a special Django object called a QuerySet. These are very powerful objects which we’ll see in a second. Let’s get all of the posts for a specific category.
>>> Category.objects.all() [<Category: Books>] >>> cat = Category.objects.all()[0] >>> cat <Category: Books>
Now even though objects.all() returns an object called a QuerySet it also works just like a standard array. So I’ve just taken the first element of the array “[0]” and assigned it to cat. So now we have a variable “cat” which contains one of our Categories called “Books”. We can see that the category has a Name which is called “Books”. Remember when we defined our __unicode__ object back in the create our models part. This is why python is calling our object . If we hadn’t defined the __unicode__ function python would print out our object like this:<Category: Category object>
Now that we have a specific category lets find all the blog posts associated with that category. I’m going to show you two different ways of doing this just show you two different new things.
>>> BlogPost.objects.filter(Category=cat) [<BlogPost: Our First Post>] >>> all_blog_posts = BlogPost.objects.all() >>> all_blog_posts [<BlogPost: Our First Post>] >>> all_blog_posts.filter(Category=cat) [<BlogPost: Our First Post>]
In the first line of code we are taking the same BlogPost.objects but, instead of calling all() we are calling filter. Filter is a function where we can compare any field from our model declaration in models.py and find only things that match that comparison. So here we are finding all the BlogPost that have a Category=cat (which is Category: Books).
The second example we are taking all the objects from BlogPost and putting them into all_blog_posts. Now this is a QuerySet object we mentioned before. It has the same methods as all of our model’s. So I can simple just filter that QuerySet for all of the posts that are in the Category : Books. The result of BOTH of those examples is still a QuerySet so I can filter them again, and again. There are a lot of functions in QuerySet’s that are very cool. We only touch on a very of them here. For a more in depth look goto our Quick Reference: QuerySets
So we’ve seen the basic ways to retrieve objects. Let’s create a new BlogPost from the shell.
>>> from django.contrib.auth.models import User >>> User.objects.all() [<User: DeGizmo>] >>> degizmo = User.objects.all()[0] >>> new_post = BlogPost() >>> new_post.Title = "blog post from the shell" >>> new_post.Category = cat >>> new_post.Slug = "this-slug-shell" >>> new_post.PostText = "this is the text of the blog post!" >>> new_post.Author = degizmo >>> new_post.save() >>> BlogPost.objects.all() [<BlogPost: Our First Post>, <BlogPost: blog post from the shell>]
The first thing we did was import the model “User” which we used before when we declared our model. Then I selected myself (the only user) and assigned it to the variable “adam”.
Now I created a new BlogPost object called new_post and went through each field in the model and assigned it a value. Then I called the function .save() which saves the new object to our database. Which you can see when we look at all of the objects stored in BlogPost. Go check the admin interface and you’ll see our new BlogPost right there along side of the rest of them.
Let’s say we want to change the title of that blog post for some reason (maybe we don’t like the capitalization).
>>> BlogPost.objects.all() [<BlogPost: Our First Post>, <BlogPost: blog post from the shell>] >>> BlogPost.objects.get(Title="blog post from the shell") <BlogPost: blog post from the shell> >>> edit = BlogPost.objects.get(Title="blog post from the shell") >>> edit.Title = "Blog Post From The Shell!" >>> edit.save() >>> BlogPost.objects.all() [<BlogPost: Our First Post>, <BlogPost: Blog Post From The Shell!>]
So once again we look at all of our BlogPost objects. This time I use a different function called get. This function doesn’t return a QuerySet but, just a single object from the database. It works the same way as filter, you tell it which field you want to compare in the database and it will return the right object. I just used the post title we want to change. Once I have stored the right post in the variable “edit” I edit the field “Title” then save it to back to the database with the function call save()
Maybe we don’t like that post at all anymore so let’s delete it.
>>> BlogPost.objects.all() [<BlogPost: Our First Post>, <BlogPost: Blog Post From The Shell!>] >>> edit = BlogPost.objects.get(Title="Blog Post From The Shell!") >>> edit <BlogPost: Blog Post From The Shell!> >>> edit.delete() >>> BlogPost.objects.all() [<BlogPost: Our First Post>]
I got the BlogPost I wanted the same way as before using the “get” function, stored it in the variable edit. Then just called the function delete()
From the console we’ve returned all the categories, blog posts, posts just for a category, a single blog post, edited a blog post and deleted a blog post. Without writing a single line of SQL. Odds are you’ll almost never have to write a single line of SQL while working in Django unless you have some really complex models.
Now that we know how to get data out of the database let’s write our first view
Leave a Reply