Part 2: Comprehensive Guide to Django Models
Tags: webdev, django, python, beginners
Published: 2024-05-07 03:40:58

In our ongoing series, [part 1](https://dev.to/kihuni/part-1-getting-started-with-django-an-introduction-1b7d) introduced Django. Now, we delve into Django Models, the essence of your project's data.

This guide will lead you through:
```
- Setting up your Django Environment

- Understanding Django Models

- Defining Your Models

- Understanding Attributes and Field Options of models

- Managing Migrations

- Establishing Relationships between django models

- How to Query the Database(Leveraging Django ORM)
```

<u>1.Setting up your Django Environment</u>

Before Django installation, ensure Python is installed, as Django relies on it. Follow official Python documentation to install Python suitable for your OS.

Once Python is installed, it's recommended to use a virtual environment for dependency isolation. In your terminal, create a folder named task_management_system, then activate a virtual environment:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ryewdkxclxr0wo82det.png)

After activating your virtual environment, install Django:

![shell](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t6amb9e6vnaan3kx07bi.png)


Verify Django installation:

```
django-admin --version

```

_Creating your first Django project:_

Create your project in the task_management_system folder:

```
django-admin startproject taskMgntSystem .

```

To verify installation, run the development server:

```
python manage.py runserver

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owqv8vp0f2zgidnyef4g.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ic01eyyo4eijzyn8eq6.png)


_Creating your first app in Django_

Create an app named tasks:

```
python manage.py startapp tasks

```

After creating the project and application, the project structure will look like this:

```
task_management_systems/
├── db.sqlite3
├── manage.py
├── taskMgntSystem/
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── tasks/
    ├── migrations/
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── models.py
    ├── tests.py
    └── views.py

```



<u>2. Understanding Django Models</u>

In Django's MVT pattern, models are central. They define your data's structure and relationships, acting as blueprints for application data.

<u>3. Defining Your Models</u>

Django models let you define different types of data to be saved. Each model class represents a specific kind of object, like a user, a product, a task, or a blog post. For example, in a task management system application, you can create a Task model class to represent individual tasks.

We create our models in the `models.py` file:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nts5nvrv4ghjamwdj1fb.png)

<u>4.Understanding Attributes and Field Options of models</u>

_Attributes/fields_

Attributes or fields are crucial components of a model as they represent the properties of your data. These fields can include CharField for text, TextFields, DateTimeField for dates, or ForeignKey for relationships with other models. In the case of our blog post example, the Task model would contain attributes such as title(Charfield), description(TextField), due_date(DateField), completed(BooleanField),created_at(DateTimeField), assigned_to(ForeignKey), and created_by(ForeignKey).

_fields options_

Field options offer you the ability to personalize the behavior and traits of each field. Below are some common field options:

- max_length: This option defines the maximum length allowed for a CharField or TextField.

- auto_now_add: By using this option, the field will automatically be set to the current date and time when the object is created.

- default: This option allows you to set a default value for the field in case no value is specified.

- null: This option determines whether the field can be left empty (null) in the database.

- blank: This option determines whether the field is required to be filled in forms.


5. Managing Migrations

When you define your models for the first time, you need to tell django where to locate your models before applying migrations. To do this edit the `setting.py` file and add the module that contains your `model.py` to the installed_apps section. In our case, the django app will reside in the `tasks.model`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ywkmqb72mw08rhtok9zv.png)

After registering your module to the `setting.py` follow this steps to generate and apply migrations:

1. `python manage.py makemigrations`:

This command analyzes the current state of your models and compares it to the state of the database. It then generates the necessary migration files in the migrations directory of each app


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ady1mf1wwlx5opkexz5s.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wuphl96pn5nx3tzqwcqv.png)

2. `python manage.py migrate`

This command applies the above migrations to the database. It will execute the pending migrations, updating the database schema to reflect the current state of your models.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0wtvr1dadzmhe4z9jl7l.png)

<u>6. Establishing Relationships between django models</u>

Django models enable you to establish relationships between different data entities. In Django, you can define relationships like One-to-One, ForeignKey, or ManyToMany relationships to represent connections between models.

_- One-to-One relationship:_

In django, a one-to-one relationship is established using `OneToOneField`. It represents a unique, one-to-one relationship between two models.

Think of a scenario where you have two entities: User and UserProfile. Each user should have exactly one profile and each profile should be associated with only one user


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rshpwrzp8v8z8tekjvdk.png)

_-  Foreign Key Relationship:_

A ForeignKey, also known as a one-to-many relationship, allows each record in one table to be linked to many records in another table. However, each record in the second table can only be associated with one record in the first table.

In our tasks example, we have the `assigned_to` attribute that has a one-to-many relationship. Each task can be associated with (or "assigned to") one user.

<u>- Many-to-Many relationship:</u>

In a many-to-many relationship, a record in one table can have multiple links to records in another table, and vice versa. For example, consider the situation where we have students and courses. A student can enroll in multiple courses, and a course can have multiple students enrolled.

In this scenario, each student in the Student model is represented by a unique record with a name field. On the other hand, in the Course model, we define a name field to represent the name of the course. 

```
from django.db import models

class Student(models.Model):
    name = models.CharField(max_length=100)
    courses = models.ManyToManyField('Course', related_name='students')

    def __str__(self):
        return self.name

class Course(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

```
<u>7. - How to Query the Database(Leveraging Django ORM)</u>

Django ORM simplifies database interactions by providing a Pythonic interface for performing CRUD (Create, Read, Update, Delete) operations.

To create and Query objects using Django ORM, we need to first access the shell and import the `Task` model.

_- accessing shell:_

```
# accessing shell
python manage.py shell

```
_- Import the Task Model:_

```
# Import the Task Model
from tasks.models import Task

```

_- Creating a new task:_

```
# Creating a new task
new_task = Task.objects.create(
    title='Example Task',
    description='This is an example task.',
    due_date='2024-04-30',
    completed=False
)
```
_- Querying tasks:_

```
# Querying tasks

incomplete_tasks = Task.objects.filter(completed=False)

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pi70n5h5zhmp5ensuobg.png)

_In the above code:_

We create a new task using the `create()` method of the Task model.
We query all incomplete tasks using the `filter()` method, which returns a queryset of tasks where the completed field is False.

_- Updating a Task:_

```
# Updating a task
task_to_update = Task.objects.get(title='Example Task')
task_to_update.description = 'Updated description'
task_to_update.save()

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d43ufc0mdztwwh69hqxe.png)


_- Deleting a Task:_

```
# Deleting a task
task_to_delete = Task.objects.get(title='Example Task')
task_to_delete.delete()

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2iqj8rl1kxwm0a8rvos.png)

_In the above examples:_

- We update a task by retrieving it using get() and then modifying its attributes before calling save() to persist the changes.

- We delete a task by retrieving it using get() and then calling the delete() method on the object.

<u>Resources:</u>

For further exploration, refer to the [official Django models documentation](https://docs.djangoproject.com/en/5.0/topics/db/models/).

In summary, Django models form the backbone of MVC architecture, organizing and interconnecting application data. They provide a structured approach to data management, enhancing code organization and scalability.

Stay tuned for our upcoming series, where we'll explore Django views.