Getting Started with Django

Virtual Environment

Once your GitHub repository is set up and you're working on it locally, your first step is to create a virtual environment. This is essential for two key reasons; it prevents changes to your system's files or libraries, and ensures you can easily track all project-specific library requirements when it's time to deploy your website. This is done with the following command in the terminal:

python -m venv venv

This will create a venv folder in your project, which will be visible in the file explorer. Be sure to add this folder to your .gitignore file to avoid cluttering your repository with unnecessary files.

To activate your virtual environment, enter the following command in the terminal:

.\venv\Scripts\activate

A green (venv) will appear before your directory path, indicating the virtual environment is active. Keep in mind, this indicator may not show in new terminal windows, but the virtual environment remains active as long as it's visible in the main terminal. With the virtual environment active, any packages you download from your VSCode terminal will be installed only within the environment, keeping the rest of your PC clean and unaffected.

To deactivate your virtual environment, enter the following command in the terminal:

deactivate

Be sure to check that the virtual environment is active each work session you start.

Installing Django

With your virtual environment activated, install Django using:

pip3 install django

To install a specific version, append the version number after django with ==. For example, to install Django 4.2.5:

pip3 install django==4.2.5

You can even upgrade or downgrade your version of django if required using the --upgrade django command specifying the version that you want to upgrade (or downgrade) to. Please note, even if you're downgrading, the command is still “--upgrade", but your version number would be a previous version than your current one, such as.

pip3 install --upgrade django==3.2.21

To check the currently installed version of django, run:

python -m django --version

Don't forget to update your requirements.txt file as we have installed (or modified) a package:

pip3 freeze --local > requirements.txt

With Django fully installed, we can now create our project. First, ensure you're in the desired project directory (the project directory that has the venv, README.md etc inside), then run:

django-admin startproject project_name .

Replace project_name with your actual project name. For example, if you're building a cupcake shop website, use:

django-admin startproject cupcake_shop .

The trailing dot (.) specifies that Django should create the project in the current directory.

Did it Work?

Good question, you've made a change to your files by starting the project and it doesn't look like any errors occurred, but how can we check that everything is working as expecting? First look at the file explorer for your project, you should notice a couple of new things. A manage.py file should be there and a folder with your project name containing the following:

  • __init__.py - Marks this directory as a package for import.
  • settings.py - Contains global settings, including debug mode, database configuration, and template locations.
  • urls.py - Manages URL routing
  • wsgi.py - Handles communication between the web server and your Django application.

For me, this looked like:

For due diligence, in the terminal try running the website with:

python manage.py runserver

You should see something like:

(venv) PS C:\Users\user\pathtoproject> python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
January 30, 2025 - 08:24:41
Django version 5.1.5, using settings 'webdevelopment.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

If you see the something similar to the above, that's good news. We can ignore the part about migrations for now, as we will address that in a coming step. The main points to note are the web address for the development server and how to quit the server. Either copy the web address in it's entirety and paste into your web browser or ctrl+click it to open your site. If everything has gone to plan you should see the following:

Now if you look back in your terminal on VSCode you might see:

Not Found: /favicon.ico
[30/Jan/2025 08:36:10] "GET /favicon.ico HTTP/1.1" 404 2216

It's not great to see an error this early on, but this is entirely normal. Django is just reminding us that it cannot find a favicon, but we haven't tried to add one yet so there's none to be found.

To close the server running your website, just use the keyboard shortcut CTRL+C inside your terminal.

Migrations

Making a full-stack website can be complex and making small changes in one place, if not correctly implemented, can spell disaster across the back-end of the website affect functionality and user experience. To streamline this, Django implements migrations to manage changes to a database schema. In future you will need to implement them when changing models so that they are applied correctly to the database. When doing so, Django stores the changes and lets you apply them seamlessly to the database without data loss. For now the big change that we have made is creating our project, so we will need to run the initial migrations and I propose the following series of commands to ensure that we mitigate errors and keep to best practices:

python manage.py showmigrations

This a list of all migration files for each app, indicating which have been applied ([X]) and which are pending ([ ]).

An example for the initial migration would look like:

 [ ] 0001_initial
 [ ] 0002_logentry_remove_auto_add
 [ ] 0003_logentry_add_action_flag_choices
auth
 [ ] 0001_initial
 [ ] 0002_alter_permission_name_max_length
 [ ] 0003_alter_user_email_max_length
 [ ] 0004_alter_user_username_opts
 [ ] 0005_alter_user_last_login_null
 [ ] 0006_require_contenttypes_0002
 [ ] 0007_alter_validators_add_error_messages
 [ ] 0008_alter_user_username_max_length
 [ ] 0009_alter_user_last_name_max_length
 [ ] 0010_alter_group_name_max_length
 [ ] 0011_update_proxy_permissions
 [ ] 0012_alter_user_first_name_max_length
contenttypes
 [ ] 0001_initial
 [ ] 0002_remove_content_type_name
sessions
 [ ] 0001_initial

Then do:

python manage.py makemigrations --dry-run

The appended --dry-run lets us simulate the migration creation without actually generating files, so we can see changes and check that no errors will occur. For the initial migration there should be no changes detected.

Next up is:

python manage.py makemigrations

This creates migration files based on model changes, but does not apply them to the database yet.

python manage.py migrate --plan

Shows a list pending migrations for apps describing what will be applied, helping us review changes before execution. This would look something like:

Planned operations:
contenttypes.0001_initial
    Create model ContentType
    Alter unique_together for contenttype (1 constraint(s))
auth.0001_initial
    Create model Permission
    Create model Group
    Create model User
admin.0001_initial
    Create model LogEntry
admin.0002_logentry_remove_auto_add
    Alter field action_time on logentry
admin.0003_logentry_add_action_flag_choices
    Alter field action_flag on logentry
contenttypes.0002_remove_content_type_name
    Change Meta options on contenttype
    Alter field name on contenttype
    Raw Python operation
    Remove field name from contenttype
auth.0002_alter_permission_name_max_length
    Alter field name on permission
auth.0003_alter_user_email_max_length
    Alter field email on user
auth.0004_alter_user_username_opts
    Alter field username on user
auth.0005_alter_user_last_login_null
    Alter field last_login on user
auth.0006_require_contenttypes_0002
auth.0007_alter_validators_add_error_messages
    Alter field username on user
auth.0008_alter_user_username_max_length
    Alter field username on user
auth.0009_alter_user_last_name_max_length
    Alter field last_name on user
auth.0010_alter_group_name_max_length
    Alter field name on group
auth.0011_update_proxy_permissions
    Raw Python operation ->     Update the content_type of prox…
auth.0012_alter_user_first_name_max_length
    Alter field first_name on user
sessions.0001_initial
    Create model Session

Then finally:

python manage.py migrate

This applies all pending migrations, updating the database schema according to the migration files. This looks like:

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

Creating a Superuser

The final recommended stage in setting up the project is to create yourself a superuser account. A huge advantage of using Django is its admin interface allowing you to create/edit/review the connected database through a browser window and update in real time. The benefits and usability of which are discussed in the admin section.

Creating a superuser to access this interface is straightforward, simply run the following command in the terminal:

python manage.py createsuperuser

The first check that is made is whether the User model is set up and migrated correctly. This was done in our initial migration step and should fly by unless the migrations haven't been previously migrated.

It will prompt you for a username or to leave blank to use the suggested username taken from the user in the project pathway, then an email address, and then a password and a password confirmation. If the password does not meet Django's default security requirements you may have to enter a stronger password.

To log into the admin page, run the website again using python manage.py runserver and open the website link and add /admin to the end of the URL. Log in with your chosen details and have a little look around. It's pretty bare at the moment but by clicking on the 'Users' link you should see your superuser details along with a green tick under the staff status.

Common .gitignore Files

File/Folder Reason
*.sqlite3 Prevent SQLite database files being tracked by GitHub, as it contains local data that is either not relevant to the development or potentially sensitive.
__pycache__ Contains files generated by the python interpreter which are recreated as needed, so is removed from the version control in order to decrease the size and clutter of the repository.
venv It has the virtual environment information including paths and configurations that won't work for other developers or environments. So it was added to .gitignore to reduce redundancy and clutter in the repository.