How to get started with Django in Python

How to get started with Django in Python

The first step in any coding endeavor is creating a small, isolated world where your code can thrive. This doesn’t just help in managing your work; it also highlights a vital principle of software development: isolation of dependencies. Think of it as having a small bubble wrapped around your project where the only things that matter are the ones you put inside it.

Let’s say you’re building a simple web application. You might start with a basic project structure. A good way to achieve that is by using a virtual environment. This isolates your Python packages, making sure that they don’t interfere with other projects. You can create a virtual environment using:

python -m venv myenv

Once your environment is created, you can activate it with the following command:

# On Windows
myenvScriptsactivate

# On macOS or Linux
source myenv/bin/activate

Now, you can install any necessary packages without worrying about them conflicting with other projects.

In this tiny world, you can also manage your project files. A suggested structure might look like this:

myproject/
│
├── myenv/             # Virtual environment directory
├── app/               # Application code
│   ├── __init__.py
│   └── views.py
├── requirements.txt   # List of packages to install
└── main.py            # Entry point of the application

By structuring your project this way, you gain clarity on where everything is. Each component has its own space, making it easier to debug and understand how everything fits together.

When you start building, pay attention to how you manage your dependencies. You can list them in a requirements.txt file, which allows others to replicate your environment easily. This file can be generated with:

pip freeze > requirements.txt

Now, anyone who wants to work on your project can simply set up their own virtual environment and install the required packages with:

pip install -r requirements.txt

This practice not only makes your code more manageable, but it also significantly reduces the chances of the classic “it works on my machine” dilemma. By solidifying this tiny world that encapsulates your code and resources, you’re making it easier for yourself and others to collaborate efficiently.

Next, you’ll need to consider what actually constitutes a project versus an app, but first, let’s wrap up the setup…

What in the world is a project and what is an app

In the realm of software development, understanding the distinction between a project and an app is crucial. A project is the overarching container, a manifestation of your ideas and goals. It can consist of multiple apps, libraries, and resources, all working together to achieve a common purpose. Think of it as a grand library where each section represents a different book-each app being a distinct book that contributes to the entire narrative.

On the other hand, an app is a more focused entity. It’s a specific functionality or feature designed to perform a particular task within your project. For example, in a social media platform project, you might have separate apps for user authentication, posting content, and messaging. Each app serves its own purpose but ultimately contributes to the overall functionality of the platform.

To illustrate this, let’s consider a Django project setup. When you create a new Django project, you typically start with the command:

django-admin startproject myproject

This command generates the project structure, including essential files like settings.py, urls.py, and wsgi.py. Your project folder now serves as the container for everything related to your web application.

Next, you can create individual apps within that project. For instance, to create an app for managing user profiles, you’d run:

python manage.py startapp profiles

This command generates a new directory named profiles, housing files like models.py, views.py, and admin.py-all tailored for that specific functionality. Now, within your myproject directory, you can have multiple apps like profiles, posts, and messages, each encapsulating different features of your application.

As you build your application, it’s essential to register your apps in the project’s settings. Open settings.py and add your app to the INSTALLED_APPS list:

INSTALLED_APPS = [
    ...
    'profiles',
    'posts',
    'messages',
]

This registration not only allows Django to recognize your app but also enables critical features like database migrations and URL routing. Each app can have its own models, views, and templates while sharing the same database and other resources defined at the project level.

Understanding this architecture is vital as it impacts how you structure your code and manage your development process. The separation of concerns that comes with defining distinct projects and apps allows for modular development, making it easier to maintain and scale your application as it grows. If you ever need to expand your functionality or even spin off an app to serve a different purpose, the groundwork laid by this structure will allow you to do so with minimal friction.

Next, we’ll dive into how to teach Django about your data without writing a lick of SQL. You might be surprised at how much can be accomplished using Django’s ORM…

Teaching Django about your data without writing a lick of SQL

So you’ve got your project and your apps. Now you need to store some data. You’re probably thinking about firing up a database client and typing out a bunch of CREATE TABLE statements. Stop right there. This is the old way, the painful way, the way of tears and typos. Django has a much, much better system for this, called an Object-Relational Mapper, or ORM. The whole point of an ORM is to let you deal with your database using the language you’re already using: Python.

In Django, you define your database tables as Python classes. These classes are called “models”. Each model class maps to a single database table. Each attribute you define on that class-a string, a number, a date-maps to a column in that table. You’re essentially building a blueprint for your database using familiar Python syntax. It’s a clean, direct translation from the world of objects to the world of relational tables, and it saves you from the drudgery of writing SQL by hand.

Let’s make this concrete. In the posts app we created earlier, open the models.py file. It’s mostly empty. We’re going to define a model for a blog post. It needs a title, some content, an author, and a few timestamps. Here’s how you do it:

from django.db import models
from django.conf import settings
from django.utils import timezone

class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    text = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    published_date = models.DateTimeField(blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.title

Take a good look at that code. There is not a lick of SQL to be found. We’ve defined a Post class that inherits from models.Model. The title is a CharField, which corresponds to a VARCHAR column in SQL. You have to give it a max_length. The text is a TextField, which is for longer blocks of text. The author is a ForeignKey, which is Django’s way of defining a relationship. It links our Post model to Django’s built-in User model, creating a many-to-one relationship (one user can write many posts). The on_delete=models.CASCADE part is important; it tells the database to also delete all of a user’s posts if that user is deleted. It’s a database rule, defined right here in your Python code.

Okay, so you’ve written a Python class. Your database, sitting over there, is completely oblivious to it. How do you get this Python definition translated into an actual database table? This is where Django’s migration system comes in. It’s a brilliant two-step process. First, you ask Django to create a “migration” file.

python manage.py makemigrations posts

When you run this, Django scans the models.py file in your posts app. It compares the models it finds with the current state of the database (or, more accurately, with the set of previous migration files). It sees you’ve created a new Post model and generates a new file, something like posts/migrations/0001_initial.py. This file is not SQL. It’s Python code that describes the changes needed to the database schema in a database-agnostic way. It’s a recipe for creating your Post table.

Now you have the recipe. To actually perform the operation and create the table, you run the migrate command.

python manage.py migrate

This command finds all the migration recipes that haven’t been applied yet and executes them. Django’s ORM generates the correct CREATE TABLE SQL for whatever database you’ve configured in settings.py-be it SQLite, PostgreSQL, or something else-and runs it. And just like that, you have a posts_post table in your database, complete with columns for id, title, text, author_id, and the date fields. You did all of this without writing any database-specific code.

The real beauty of this becomes apparent when you start interacting with your data. You don’t need to write INSERT, SELECT, UPDATE, or DELETE statements. You just work with your Python objects. Want to create a new blog post? You just instantiate your Post class and call its save() method.

# You'll need to run this in the Django shell: python manage.py shell
from django.contrib.auth.models import User
from posts.models import Post

# Assuming you have a user with username 'joel'
user = User.objects.get(username='joel')

# Create a new post object in memory
new_post = Post(author=user, title='The ORM is Magic', text='Seriously, you avoid so much pain.')

# Save it to the database
new_post.save()

That save() call is what triggers Django to generate an INSERT INTO statement and run it on the database. You’ve now defined your data schema and added a record to it, all from the comfort and safety of Python. This abstraction is what makes frameworks like Django so productive. You get to think about your application’s logic, not the tedious and error-prone details of SQL syntax.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *