Monday, June 9, 2014

The SaaS methodology

Hey guys! This one's not a tutorial. So just sit back with a cup of coffee and relax. I assure you this is going to be fun.
Up until now we've seen two names associated with programming in Django. The first one is Web Design, which is very mundane. Any Tom, Dick and Harry can visit a CMS like Wordpress nowadays and make a website for themselves.
Then we saw the slightly more colorful and yet highly misunderstood name Web Application Design, or simply Web App Design.
I'm finally going to tell you a name that is not only prestigious, but one that will blow your mind whole. It's SaaS, or Software as a Service.
I'll give you a minute to let the awesomeness sink in.
Done?
Good.
Yes, Django programming falls under software. People think that software only means the ones we open on our computers.
The Service in SaaS is not service as in social service. It means the service you provide to computers.
SaaS pieces are hosted on servers and can be accessed from anywhere with an Internet connection. They may be free or charged. The charged ones are called Proprietary Software. Also note that the free ones are not called Open Source. That's completely different. Open Source is when the underlying code is visible to the general public. Proprietary software may also be Open Source.
Furthermore, SaaS may be for only a company or organization in general or may be publicly usable. In the first case, it is hosted on indigenous servers, whose access is restricted to only within that organization. In the second, they would normally be hosted on a global server.
So how does SaaS make money? There are many models currently employed:
  • Developers can charge on a time basis (i.e. weekly, monthly, fortnightly etc) that will enable the users unlimited utility out of the software.
  • They may charge a small amount every time the software is used, which then limits the usage. This one sometimes is a bigger money maker.
  • They may also charge a very high one time price, which would transfer the ownership of the software to the buyer. The developers may further charge on maintenance and repairs.
So why did I write this article? When I first found this out several months ago while talking to my Dad (very wise man), it made me develop in Django in more earnest, all the while thinking, "Hey! I'm developing software!"
SaaS is also used while talking about RoR (Ruby on Rails). Currently the number of Rails developers greatly outnumber that of Django.
So I guess I'm hoping that by reading this article more people will be encouraged to become Django coders. Forget Sparta, we'll stand in front of Rails developers and say "THIS IS DJANGO!!".
(I have absolutely nothing against Rails or its developers by the way)
Cheers!

Sunday, June 8, 2014

An important thing

Hey guys! This is an important one. This had me stymied for a day and a half. Do not forget to commit the changes before closing the connection in the particular view if that view contains any of insert, update or delete queries. It doesn't matter with select queries, but for the aforementioned it is a must.

Friday, June 6, 2014

Displaying images

As I mentioned in a previous post, <img src = ""> does not work in Django. I mean, it does work, and that's how we are going to display images, but it doesn't work if you give local machine addresses like /home/foo/bar or C:/images/foo/bar. This is actually a good thing. Django has a very sophisticated method of handling images and other files, often called as static files.
If you open your settings.py file, you'll see two URLs: STATIC_URL and MEDIA_URL. These can be used to render static files and media in general.
Now there are two ways of doing this:
  • Using the in-built {{ STATIC_URL }} or {{ MEDIA_URL }} variables. But as I have not posted about Django's templating language, we'll put this one on the back burner. But rest assured, once you understand the templating language, how to use these will be self-evident.
  • Using full URLs, including the values specified in {{ STATIC_URL }} and {{ MEDIA_URL }}. 
We'll be using the second method. The only disadvantage of this method is that if the directory containing static files changes then you have to make sure that change reflects in all templates. In the first case, this would happen automatically.

Let's assume you're running your website on localhost, i.e. http://127.0.0.1/ and you want to render an image on the URL http://127.0.0.1/home. Let's also assume that the .html file behind this webpage is called home.html (wow, that's a lot of assuming).

Anyway, change into your project directory, and create a folder called static. Store all your images here. Let's assume (not again!) that you have an image called garden.jpg in the static folder, which you want to display on the homepage.

So instead of giving local machine paths, you give the path in the form of a URL.

<img src  = "http://127.0.0.1/static/garden.jpg">

Now, to validate this, open your settings.py file, and make the following changes.

STATIC_ROOT = "/foo/bar/mysite/static"
STATIC_URL = "/static/"

This will tell Django that when http://127.0.0.1/static/ (or STATIC_URL) is accessed, the path in STATIC_ROOT is to be checked.

That's all for now! Two things before we part:
  • I'm still working on the templating tutorial, to make it concise as it is a very vast topic. Once I come up with it, we'll investigate the {{ STATIC_URL }} and {{ MEDIA_URL }} business.
  • What we did here with static can also be done with media. They are two objects of the same file displaying facility, giving us more customizability. To use media, just replace static with media in all of the code above.
Cheers!

Tuesday, June 3, 2014

Backing up

Backing up your files is extremely important. If the server you've hosted your site on crashes and you don't have a copy of the files then your goose is cooked. You'll have to start from scratch.
I've written the code for backing up files and your MySQL database. Here's the link:

https://github.com/AgentK1729/File-Backup

In case you have an SQLite database, there's no need to back up the database as shown in the code, there'll be a readymade .db file. Just copy it somewhere reliable.

Troubleshooting

More often than not, your site will generate an error that will cripple its functioning. This is not a bad thing, however. Not only does it let you grow as a programmer, but also it is said that if your code executes the first time without any errors, you're not a good programmer!
I'm currently developing a commercial website and this happened to me today. I did some resizing and suddenly all my webpages showed the same message: 'Unhandled Exception'.
After hours of hunting down the source, I discovered that I deleted two apps but forgot to remove them from the INSTALLED_APPS in the settings.py.
The point of this story is that such things happen to everyone without exception. The important thing is to not panic. Here's what you do:

  • Close your eyes and take a deep breath.
  • Recall the last point where it was working.
  • Retrace the steps you took from that point till now and evaluate what might have caused the error.
The error can also be caused by some very insignificant things, which make you want to kick yourself.
  • The one I described.
  • Forgetting to 'Reload' the site in case you have hosted it on a server.
  • Not saving a file you made changes to.
So guys, remember two very important things:
  • The fact that you got an unidentifiable error means you're a better programmer than you think, because you managed to screw up a system like never before.
  • DO NOT PANIC.
Follow these two and you'll be an awesome programmer.
Cheers!

Tuesday, May 13, 2014

A break from the tutorial: Intuitive stuff

Hey guys! Let's take a break from the bombarding of information, and let's do something interesting. Let's talk about some of the features that are taken for granted in all the giant websites. You may already have noticed them. If not, double back and check them out. We'll also see how to implement them in your website.

The "Keep me logged in":
Many websites like Facebook and Gmail offer this option at the time of login. What it does is even if you close the browser/tab/window, the next time you open it it opens on your homepage. Even more fascinating, if you try to log in from some other device it you're not logged in, and you even get an alert that someone tried to access your account from an unknown location. Let's see how this is done in steps:

  • When you log in, cookies with your username are stored in your browser. If you close it and reopen it, and access that site again, it checks for that-site-specific cookies. If they are there, they take you to your homepage. Else, you're redirected to the login page.
  • To prevent multiple people accessing the account at the same type, the session is logged in to the database. The username/email is unique, so only one session of that name can be logged in to the database. If another one tries, it captures the IP address, denies it access and warns the user. (We'll see how to track IP addresses in the next article)
  • When you log in, it notes down your IP address. It is added to the list of addresses from which you frequently access that site.
  • On log out, it deletes the cookies and logs you out of the database.

The "Display n search results":
This is very easy. Just maintain a count of how many results are wanted. Assume the form method is GET:
count = int (request.GET['count'])
temp = 0
for row in cur/cur.fetchall ():
    if temp == count:
        break
    else:
        print row[0]
        temp += 1


Opening a new tab on hyperlink or button press:
For hyperlink: <a href = "foo/bar.html" target = "_blank">
For button press: <form action = "/foo/" method = "GET" target = "_blank">

The target = "_blank" does the trick. Note that it have to be inserted into form attributes and not the button's.

That's it for today! Tell me if I missed anything.
Cheers!




Friday, May 9, 2014

Custom queries III: MySQL

Ok, we saw how to connect to an SQLite database in Python. Now let's see MySQL. There's only a small difference in syntax, but it's significant. The steps, however, are the same.

Import the library
import MySQLdb as ms

Note: The as specifies an alternate name for the library. In this case, I won't have to type MySQLdb again and again. I'll just type ms.

Establish a connection
conn = ms.connect (host, username, password, database_name)

If you're running this on a machine, normally host is localhost. You'll have to create a root user, which you'll have to see how to do in your particular OS on the Internet. Provide that username and password. Then execute the command create database db_name and use this database as the fourth field.

Exhausted? So am I. I know it's a lot of effort, but trust me, the results are totally worth it.

Create a cursor as usual
cur = conn.cursor ()

Remember I said %s doesn't work in SQLite? Well, that's the only thing that works here. Let's write a query.

query = "select name from employee where empid = %s" % empid

READ THIS VERY CAREFULLY:
Now, empid is an integer, but you still have to pass is as a string. Assume empid is 1234. The query then becomes:
select name from employee where empid = 1234

Let's look at a query where we need to pass a string.
query = "select empid from employee where name = '%s'" % name

Notice the difference? %s from the first query is replace by '%s' in the second. Assume name is Douglas. The query now becomes:
select empid from employee where name = 'Douglas'

Don't worry if you're confused, go through the paragraph once again. Let it sink in.

OK, NOW RELAX AND ENJOY THE REMAINING PART.

Ok, the rest is pretty much the same.

cur.execute (query)
for row in cur.fetchall ():
    print row[0]

for row in cur: in SQLite is replaced by cur.fetchall (): in MySQL.

Alternatively, you can also use cur.fetchone () if you're sure only one row is going to be returned (for primary keys) or just want it that way.

Hope I didn't miss anything. If I did, please comment. The remaining things are the same for both SQLite and MySQL. Don't forget to commit and close the connection once the job is done.
Cheers!