Why not see if you like Django? (Mega-post Edition!)

As mentioned, I’ve been learning more Python in recent months. As more of an end-user app developer, I am also regularly drawn to technologies that allow me to create regular applications for regular users. Python is great for automation and security scripts, but what ABOUT regular applications for regular people (e.g. business apps)?

image

If you are coming to my blog, there is a decent chance you are a .NET developer. If so, I specifically encourage you to give this a whirl. In today’s topsy-turvy world, it never hurts to be a polyglot and to be familiar with more technologies. Why I suggest this one in particular, is because it’s ridiculous! This represents a VERY low barrier-to-entry. It’s very easy to get started, there are fantastic resources, and best of all, it’s a remarkably powerful language and technology. You can accomplish so, so much with so little code. It also runs on everything (Windows, Mac, Linux, Raspberry Pi, mainframe, etc).

In fact, not only would I recommend that you check this out, I challenge you to read the Linux/Mac approach below. That will likely give you a better understanding of the guts (and maybe you pick up a little Linux along the way?). But even on Linux or Mac, you can still use Visual Studio Code, which is a great IDE and kind of familiar. Then later, if you want, you can stay on Windows and work in regular Visual Studio, which is a really good IDE for Python too – using Python Tools for Visual Studio (PTVS).

So, as you can see – on many fronts, and for many, many reasons, I think it’s a good idea to give this whirl and see if you like it, maybe?!

The Django Framework:
The de facto product I kept running into while researching web frameworks for Python, was Django. Man-alive, people are in LOVE with this framework… fanboy, much? Little did I know, I would quickly turn into a fan too!

What is it? It’s a Python web-ish framework which does (more or less) MVC, but it also has an Object Relational Mapping (ORM) component too (like Entity Framework) which is downright ridiculous! This isn’t just some random framework though, this has become the standard for me to compare things against. For example, .NET has a lot of “ceremony” in it’s languages. Meaning, there are many, many ritualistic things you need to do: strong-typing, argument validation, detailed structured exception handling. Although those things are good, and believe me, my OCD loves that structure, there is actually another reasonable way to do things.

What if I told you that you could produce the nearly identical website to your ASP.NET MVC website, which is just as robust – with probably 10-25% of the code it would take for ASP.NET? That also means I could get that site up in probably 1/4 of the time too. You’re reaction would likely be: “at what cost?” and that cost is “ceremony”.  There are conventions with Python and with Django which make most of the rituals unnecessary because the program will fail in a predictable way… which is why you have all of that ceremony in .NET, right? Second, Django in particular does “what you’d probably need anyway”, by default. This means that you can set up your ORM and database stuff with a ridiculously small amount of code – I mean like with a few lines of code you’ll have complete CRUD capabilities.

I’m getting ahead of myself, let me show you some of the highlights and see if I can start to sell you on the idea…

The MVC-ish structure:
This is a little bit wonky. Although this is more-or-less an MVC framework, they call the View a template, and they call the Controller a view. This takes some getting used-to. After learning more about this, I kind of see why, but it would’ve been better if they stuck with the industry standard. That, by the way, is pretty much the only negative thing I have to say about this!

For the Models – you modify your models.py and define any data structures you want to use. If you want to use the built-in ORM and Admin site (described below), and believe me you do – you should inherit and set them up like this (here is the complete example I’m referencing):

class Customer(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    first_name = models.CharField(max_length=100, verbose_name=”First Name”, help_text=”Please enter a first name for this customer.”)
    last_name = models.CharField(max_length=100)
    address1 = models.CharField(max_length=100, blank=True)
    address2 = models.CharField(max_length=100, blank=True)
    city = models.CharField(max_length=100, blank=True)
    state_code = models.CharField(max_length=2, default=’FL’, choices=STATE_CODE_CHOICES, blank=True)
    postal_code = models.CharField(max_length=100, blank=True)
    created_by = models.ForeignKey(User)

the idea here is you tell Django about your data structure. In fact, for things like first_name, you can set all sorts of things. Why that is really cool, is that it will generate a database table for you, with this explicit information. But even better, is there is an Admin site (see below) which will use these details to build a proper, automatic UI for viewing and editing this data – including referencing dropdowns for foreign key relationships.

Two other very interesting items to note from above is state_code, which gets it’s values from a list. Not only is this properly set up in the database, it also makes the Admin site work correctly where it shows the available values in a dropdown – all automatically.

Lastly, look at that created_by, note that says this field is a foreign key reference to an item in the User table. Again, not only does it create this like a many-to-one relationship to the User table, the Admin app, as you’ll takes full advantage of this and puts all of the users in a dropdown – all automatically.

For now, just understand that your models go into one models.py file, and that they need to inherit from Model. Also understand this will generate and update your database – and that database can be anything. By default, and in the sample provided here, it’s a Sqlite file. However, it could be MySQL, MongoDB, etc.

For the View (a.k.a. “template”) – this is where you render your model to HTML. The way you would have a “master page”, or template file is to create an HTML file for that, typically case base.html. Then, in your content pages (templates), you do something like this:

{% extends ‘base.html’ %}

        {% block content %}
<h1>main home</h1>

   

{{ message }}

        {% endblock %}

Note that the “extends” is what tells this page to go inject the “content” block into the “content” block in base.html, and load the rest of base.html around it. If you do look at that base.html, that might help this make more sense. This is quite similar to “master pages” in ASP.NET WebForms, if that helps. The main things to understand here are how the master page concept works, and that if you want to reference a model or any data that was passed to this template, you use the double-handlebars style syntax, like {{ message }}.

For the Controller (a.k.a. “view”) – similar to ASP.NET MVC, this is a combination of routing rules and actual code that gets run. For the routing rules, you’d modify urls.py, which has entries like this:

urlpatterns = [
    url(r’^admin/’, include(admin.site.urls)),
    url(r’^$’, ‘main.views.home’, name=”main_home”),
    url(r’^account/$’, ‘main.views.account’, name=”main_account”)
]

As an example, the 2nd item matches the URL to a regular expression of “^$” (which is basically, and empty request URL), then it loads the main.views.home “view” (think: MVC controller). Each of these work similarly, you’d configure what URL you want to load which views. So, let’s look at the code now that handles that URL request, look at views.py, and you’ll see things like this:

def home(request):
    return render(request, “main/home.html”, { ‘message’: “test message”})

@login_required
def account(request):
    return render(request, “main/account.html”, { ‘message’: “test message”})

The first example of “def home” IS that “main.views.home” which was referenced above. All that function does is attempt to render “main/home.html”, our partial “template” – and we’ll also send “message” to that page to render too. That “model” could be anything.

The second example is very similar, but note that it is decorated with an @login_required attribute, called a “decorator” in Python. That ties in with Django’s authentication framework and will not let the user navigate to that URL until they are logged in.

Putting it all together… imagine you navigate to /, well the urls.py will match that request with it’s regular expression, and call the “main.views.home” function (the “view”), which renders “main/home.html” (the “template”), and also hands off data to that template to render. The template loads, and is able to then render the model that is was given. That’s the basic gist of the workflow of page requests in Django.

The ORM stuff and the Admin site:
Two aspects of Django that I just giggled-at, was the Object Relational Mapping (ORM) and the built-in admin site. The ORM stuff is where you define the “models” in code, that is, basically what a “table” of data would be in a database, and the ORM just magically creates and updates the database accordingly. Very, very little “ceremony” and the default behavior is what you’d want. You can override how it works, but it already works the way you’d want!

Working with the ORM

STEP 1: Create your models – as discussed, modify the models.py file and create/modify classes and properties within, for whatever data structures you need.

STEP 2: Migrate your changes – go to the command line and run “manage.py makemigrations”, then “manage.py migrate” to push those changes to the database.

STEP 3: No, wait, there is no step 3, it’s that simple. If you are wondering if you could do database-first? I don’t know, I’m still a newb. So this code-first approach is going to be GREAT for your small projects and for agile/nimble companies, but it’s probably going to not-work at your typical enterprise/megacorp.  :-/

Working with the Admin site

The “admin site” is this module you can easily add which automatically creates proper Create-Read-Update-Delete (CRUD) screens for ALL of tables/models in your database. This includes input validation, and relations – like creating a dropdown which has values from another table. All completely correct, and all automatic. I was absolutely dumb-struck when I saw this in action. Again, you can override or change any part of this – but what it does out of the box is pretty perfect.

STEP 1: Uncomment all of the “admin” stuff in urls.py, settings.py, and the admin.py of your main app.

STEP 2: Tell Django about the models you want the Admin site to manage. Open admin.py and register a model like this:

from django.contrib import admin
from .models import Customer

# Register your models here.
admin.site.register(Customer)

STEP 3: Navigate to the /Admin/ URL of your site and be amazed. For the model we defined above, look what it created, automatically!

image

image

image

There are several significant things to note here:

  1. I didn’t write any of this. I told Django about my model, in detail, and it built a form WITH validation and dropdowns.
  2. Note the First Name, Last Name, and Created By are bolded – because they are mandatory (as defined in the models.py).
  3. Note that First Name has “First Name:” for a label, and a description – both of which I specified in the model definition in models.py.
  4. Note that State Code is a dropdown of all of the available values I gave it.
  5. Note that Created By, which I specified as a ForeignKey to the User table, Django created and populated the dropdown automatically.

Now, this isn’t just a “starting place” for CRUD operations, this is a production-ready site with field validation and everything:

image

as you can see, this is a full-featured site that is automatically available to you. All you need is that ONE line of code to tell Django about your model, and you get this Admin website for free!

A quick crash course…
Now, it’s not practical for me to describe an entire web technology in one blog post. However, I want to highlight some of the impressive things – AND one of the impressive things is that these technologies work just as simply, and completely on Windows, Mac OS, and Linux! So, wouldn’t it be cool to see Django hosted in all of these environments? Well, I’ll cover Linux and Windows in this post, in some detail…

From-Scratch on Linux:
I did this on Ubuntu, so this should work on any Debian-based distribution (maybe even a Raspberry Pi, did someone say?!). Non-Debian solutions would just be different with how you install python, really. So let’s dig in:

Install Python and Pip – it’s probably already installed, but try:

$ sudo apt-get install python
$ sudo apt-get install python-pip

Install VirtualEnv – this may or may not be installed. This will allow you to create a “virtual environment” in which to run your app. This basically means that you can choose your default version of python, install packages to your application (instead of to the whole computer), and that virtual environment will be usable on other computers too – they need only “activate” it. You check in this environment to source control, which makes the whole app pretty portable to any platform which supports Python.

First, let’s make sure it’s installed:

$ sudo pip install virtualenv

Use VirtualEnv – to start, navigate into the directory above where you want your project – for example /home/rseder/projects/ (or ~ always refers to your home directory, so ~/projects/ works too). First, for backwards compatibility and because it’s been around for a long time, Python 2.x is likely the default interpreter. To verify, type:

$ python –version

that likely returns version 2.7. In this case, we want to use the newer stuff. So, to find out where python3 is installed, we can do this:

$ which python2
$ which python3

this will tell you the location of each of those. We will use this to set up our virtual environment specifically with this command:

$ virtualenv -p /usr/bin/python3 division42pos

that will set up pointers to the python executables and other necessary files. You might notice there is now a bin and lib folder. So, you have that environment, this “bubble” in which your application runs, but how do you get into this bubble? You “activate” it, like this:

$ . division42pos/bin/activate

and you will see your prompt now changes to include the virtual environment:

(division42pos) $

One other important thing to note, look at that funny syntax when we called activate, you type a “.” then space, then “activate” (including the path). I still don’t understand how/where that syntax works, but it does. You get a funny error if you just call activate directly. At this point, you are “inside” of your virtual environment. This means that if you use pip to install packages, it will install them only to this project, in this virtual environment.

Install Django – we need to get the libraries for Django, which we can use pip to install:

$ pip install django

For this particular example, I have installed Django v1.8.3.

Creating an empty Django project – first, you may wish to ensure you have Django installed correctly. To verify this, you can type:

$ python -c “import django; print(django.get_version())”

it should return the version number. Next, we can use the “django-admin” app to give us a starter template. Because Django is already installed, this will already be in our path. So, from the parent directory where you’d like store the website, run:

$ django-admin startproject division42pos

where division42pos is the name of your site or project. POS stands for “point of sale”, just as an example. You will then see you have a subdirectory for your project.

Most-importantly, you might notice there is a “manage.py” in that folder. That is the main “executable” script you will use to do pretty much anything with the Django environment.

Start the development server – you can now start the development web server and see a working site. To do that, run:

$ ./manage.py runserver

You should see some output like this:

image

Now, you can navigate to http://127.0.0.1:8000/ in a browser and you’ll see the standard Django landing page:

image

This is where the story starts to take a slightly-bad turn (compared to what we’re do in Windows). You have to do some things on your own from here. What you have here is a completely empty website. Django likes to break up pieces of functionality of a website into “apps”. Each “app” will have it’s own routing, it’s own models, etc. With that said, you could arguably just do everything under a “main” app. So, let’s at least start with that. From the root of your project, run:

$ manage.py startapp main

within that app, you can now start fleshing out the application.

Wrapping up – as discussed, it’s impossible to cover the entire technology in one post, but I did want to include some real startup stuff. Now, using the example above, I fleshed out a working site on Ubuntu, and using Visual Studio Code on Ubuntu, I checked in my source to GitHub:

image

(top left: manage.py runserver; bottom: browser open to that web server; right: Visual Studio Code with Python project open)

It’s worth mentioning about what IDE you’d use on Linux. The go-to for everyone is Sublime, but honestly, Visual Studio Code (which is free), is an EXCELLENT alternative. I’ve had zero problems with it – plus it integrates very nicely with Git.

Example Source (viewing) – if you just want to view the source to this site, I’ve put it to GitHub, here:

Example working site with bootstrap, simple auth, and admin site – using this technique
https://github.com/SamplesAndDemos/division42pos1

the directories within directories stuff is a little zany. That might be my 2nd pet peeve with Django. However, once you get the hang of it, it sort of makes sense?

Example Source (trying for yourself) – in theory, you should be able to pull this source down. Create a directory (on any platform that has Python and Git installed), and run:

$ git clone https://github.com/SamplesAndDemos/division42pos1

then, you need to “activate” that Virtual Environment, so:

$ . division42pos1/src/division42pos/bin/activate

then, if you want to start the web server and try it out:

$ division42pos1/src/division42pos/division42pos/manage.py runserver

If all went according to plan, you should see a development web server start up in the console and it should list a URL – navigate to that URL. You can log in with rseder/password. You can also navigate to /admin/ in the website to get to the admin site too.

BONUS ROUND – What about on a Mac too? I know I said I wasn’t going to cover MacOS X, but what would it take to run this on one? Well, I installed Python3.x from www.python.org, did a pip install of django and django-crispy-forms, did a git clone of the repository above, an “activate”, then a “manage.py runserver” and voila:

image

(top left: manage.py runserver; bottom: browser open to that web server; right: Visual Studio Code with Python project open)

So, this is exactly the same functioning website, but running on MacOS. You might notice that I again use Visual Studio Code here too, so I have a similar editing/IDE environment across Linux and Mac too! That’s pretty amazing, is it not?!

From-Scratch on Windows (using Visual Studio and PTVS):
Hopefully you read or at least skimmed the Linux version above. I say that because I started with Python Tools for Visual Studio (PTVS), but was kind of lost. That’s because there are quite a few conventions in Django that you learn when you do it the “manual” way, and that aren’t intuitive on their own.

So why do things differently on Windows, you may ask. Well, primarily because Visual Studio has VERY good support for Python. As you know, having a good IDE is a big part of writing code. On Windows, Visual Studio (with PTVS installed), is an excellent IDE – although it has it’s idiosyncrasies.

Ok – so here’s where the story takes a very good turn: once you do get a hang of the conventions, Django is (dare I say) even easier than it already is when you use the VS + PTVS + Windows approach. For this example, I’m using Windows 10 RTM, VS2015, and the latest PTVS.

First philosophically, it’s interesting to me that Python is a first-class-citizen in Visual Studio – Microsoft has completely embraced this language and platform. So, having Visual Studio for your IDE is going to be a good thing! OK, so where do start? First, here is a quick video of what PTVS is and some of the key features:

Installing Python and PTVS – since VS2015 just came out last week, I’m pretty sure PTVS is now an install option, but I’m not certain. You can tell by clicking File –> New Project in Visual Studio, go to the Python node and see if you templates like this:

image

if you don’t have that, then you can install PTVS from here:

http://microsoft.github.io/PTVS/

Starting with a Django project – from the screenshot above, if you create a new project, and choose “Django Web Project”, that will give you a pretty good starting place, and you’ll notice (if you followed along with the Linux example above), that the default project structure is already there:

image

Create a virtual environment – knowing what we now know about virtualenv, we probably want to create a virtual environment, just to be explicit with our project. To do that, right-click on “Python Environments” in Solution Explorer and choose “Add virtual environment”. You can take the default of “env”, or have it match your project name:

image

but wait, see that “error message” in the middle of the screen that doesn’t look like an error message? PTVS is installed, but Python isn’t. We need to navigate to www.python.org and install Python (3.x) for Windows:

image

image

At this point, you have Python installed and you can go back in Visual Studio. You’ll see that there is a default environment setup, and now you can create your own virtualenv’s if you want:

image

Nuget vs requirements.txt – in .NET, we use Nuget to get “packages” to add to our project. In Python/Django, we read or write to requirements.txt for this. So, after you install a package – or when you are restoring a project, you can use this feature for something akin of “Nuget package restore”:

image

Start the development server – that should be pretty much all you need. Hit F5 to start debugging and you should see the development server spin up, and then a web page open to to the start page:

image

Working with the Visual Studio project – one thing that is pretty great is that the Django project template already comes with a Bootstrap 3 and a decent starting layout. It already comes with the ability to log in – where the username and hashed password are stored in your database. To set up the first, default user, run:

migrate.py syncdb

and follow the prompts. Then, if you want to see the /Admin site working, uncomment any of the commented items in settings.py, urls.py, and you’ll need to create a new file called admin.py in your main app. In there, you tell it about your models:

from django.contrib import admin
from .models import Customer

# Register your models here.
admin.site.register(Customer)

then, you’ll see that you can log into the site:

image

and that the Admin site is there with all of the CRUD functionality for your tables:

image

As you can see, there are some things which are specific to Visual Studio, but it’s basically the same Django that works on Linux and Mac.

Working with manage.py – as we learned over on Linux, manage.py is pretty much the main program we work with. Although there are some right-click features in Solution Explorer, in Visual Studio, I find these to be pretty clunky. Instead, just open a command-line and the syntax is exactly the same as Linux and MacOS. For example, here is me application database migrations via “manage.py migrate”:

image

Example source – if you’d like to view the source of this similar project, but one created with PTVS, you can see it here or clone it with Git to bring it down and try it:

Example working site with bootstrap, simple auth, and admin site – using this technique
https://github.com/SamplesAndDemos/division42pos2

The default username/password is rseder/password.

Learning Django:
In reading the above, this probably was not super-clear, but it at least exposes you to the concepts, generally, how Django works. How do you learn Django? How do you start? Well, that’s actually the easy part! There are excellent resources available online which will have you up and running in just a couple of hours of webcasts.

To start, here are two REALLY excellent resources – they both start you off from the ground-floor, assuming you don’t know anything about Django, and nothing/little about Python:

  1. Pluralsight: Django Fundamentals (requires subscription – around 3 hours of content)
    http://www.pluralsight.com/courses/django-fundamentals 
  2. Microsoft Virtual Academy: Developing websites using Python and Django (free – around 4 hours of content)
    https://www.microsoftvirtualacademy.com/en-US/training-courses/developing-websites-using-python-and-django-11415 
  3. PVTS 2.0: A quick overview
    https://www.youtube.com/watch?v=JNNAOypc6Ek

By the end of each, you’ll feel pretty confident about how the technology works, and you’ll likely be inspired by how effective of a technology it is. Both of these are excellent, easy-to-follow and assume you have little to no experience with either Python or Django.

The MVA one is what I watched first, which impressed me so much, then I watched the Pluralsight one which went into more detail, and impressed me even more!

Next, this may surprise you, but the Django documentation is quite excellent. For example, they have very detailed, clear walkthroughs on how to do pretty much everything. See here: https://docs.djangoproject.com/. They walk you through the whole process and these alone could have you with a working site in just a couple of hours – again, very low ceremony.

Lastly, I haven’t been stuck on a problem for more than a few minutes. 100% of the time that I ran into a problem, a quick Google search had the answer quickly. On StackOverflow in particular, there are tons of questions and high-quality answers. I argue that the biggest frustration while learning a new technology is being stuck for hours on what turn out to be small or simple things. With Django, it was really smooth-sailing. Consider that I knew absolutely nothing of this technology a few weeks ago!

Bottom Line:
I’ve been extremely impressed by Django – on so many levels. It’s very easy to learn, ridiculously powerful, and requires so little code to do a lot. Best of all is finding answers has consistently been very easy. Type in a few words in google and the first few links have the answer EVERY time.

How sold on this am I? Well, I’m still a newb with this technology and there is still a lot I don’t know. For example, as of this writing, I have no idea how to deploy it and also which web servers it would run on and what those configurations would be. With that said though, I am actively working on at least one website right now which will have social logins, be Bootstrap-based (for now), and will use Django for data access probably to MySQL. So, during the process of bringing that live, I’ll incidentally learn the other missing pieces. So, I’m sold enough to try to bring a site to production using it.

Maybe it would be helpful to look at this from an upside/downside perspective:

Pros

  • You can learn, develop, and use everything you see here, for FREE. Python and Django are free/open source, Visual Studio Community with PVTS is free, Visual Studio Code (on Linux or Mac for example) are free. The only “cost” here, is time.
  • Can crank out a full-featured site extremely quickly with very little code (low ceremony).
  • The Admin site automatically gives you production-ready CRUD screens, saving you tons of time.
  • Documentation is excellent and it’s very quick and easy to find answers.
  • This works on pretty much every kind of modern computer; you can build and/or deploy Django to pretty much anything.

Cons

  • If this is new to you, there is a learning curve – but not unreasonable at all.
  • I don’t know yet how difficult it will be to deploy to a web server.
  • I don’t know lots of things yet: how is load-balancing done? can you do database-first ORM? how secure is this security model? etc…

Despite my ignorance, I’m very much sold on this from everything I’ve seen and experienced so far. It’s a really powerful, fun, simple technology that lets me be very productive with very little effort. Have I sold you on taking a look at Django?

Posted in Apple Stuff, Computers and Internet, Development Tools, Django, Entity Framework, General, Infrastructure, Linux, New Technology, Open Source, Professional Development, Python, Uncategorized, Visual Studio
One comment on “Why not see if you like Django? (Mega-post Edition!)
  1. […] since I first dug into this last year – this framework continues to amaze me. The idea is that you can basically define your database […]

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
Categories

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 2 other followers

%d bloggers like this: