Working with Databases in Django Using PostgreSQL
Tags: webdev, beginners, python, devops
Published: 2024-07-02 15:29:07

# Introduction

Django simplifies database interaction with its Object-Relational Mapping (ORM) system, enabling Python code to be used for working with databases instead of writing SQL. This guide provides essential information on using PostgreSQL in Django, from database setup to performing CRUD operations.

## Setting Up the Database

### Database Configuration

- Installing PostgreSQL: Ensure that PostgreSQL is installed on your system. If you're new to Postgres, here's a guide to help you get started: [Getting Started with PostgreSQL](https://www.postgresqltutorial.com/postgresql-getting-started/).
- Installing psycopg2: Install the PostgreSQL adapter for Python.

```python
pip install psycopg2-binary
```

- Configure your database settings in the settings.py file.

```python
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}
```

## Defining Models

### Creating a Model

A model in Django is a Python class that subclasses `django.db.models.Model` and defines fields and behaviors of the data you're storing.

For example:

```python
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    birth_date = models.DateField()
```

### Fields

Field Types: Django provides various field types to map Python types to PostgreSQL columns.
- CharField: Stores text data with a maximum length.
- IntegerField: Stores integer values.
- DateField: Stores dates.
- ForeignKey: Defines a many-to-one relationship.

### Meta Class

The Meta class inside a model contains metadata options.

Example:

```python
class Author(models.Model):
    name = models.CharField(max_length=100)
    birth_date = models.DateField()

    class Meta:
        ordering = ['name']
```

- ordering: Orders query results by the specified fields.

## Migrating the Database

- Create Migrations: Generate migration files based on your models.

```
python manage.py makemigrations
```

- Apply Migrations: Apply the migration files to update your database schema.

```
python manage.py migrate
```

## CRUD Operations

### Creating Records

- Using the ORM: Create new records by instantiating a model and calling the save() method.

```
# python manage.py shell

from postgress_database.models import Author 

author = Author(name='John Doe', birth_date='1980-01-01')
author.save()

```

### Reading Records

QuerySet API: Retrieve records using methods like `all()`, `filter()`, `get()`, etc.

Example:

```
authors = Author.objects.all()
author = Author.objects.get(id=1)
filtered_authors = Author.objects.filter(name__icontains='john')

```

### Updating Records

- Modifying and Saving: Update records by modifying model instances and calling save().

```
author = Author.objects.get(id=1)
author.name = 'Jane Doe'
author.save()

```

### Deleting Records

Delete Method: Remove records using the delete() method.

```
author = Author.objects.get(id=1)
author.delete()

```

## QuerySet Methods

### Common Methods

- all(): Returns all records.
```
authors = Author.objects.all()

```

- filter(): Returns records matching the given criteria.

```
filtered_authors = Author.objects.filter(name__icontains='john')

```

- exclude(): Excludes records matching the given criteria.

```
non_john_authors = Author.objects.exclude(name__icontains='john')

```

- order_by(): Orders records by the specified field.

```
ordered_authors = Author.objects.order_by('name')

```

- values(): Returns a QuerySet of dictionaries instead of model instances.

```
author_values = Author.objects.values('name', 'birth_date')

```

## Relationships

### One-to-Many Relationships

- ForeignKey: Define a many-to-one relationship using [ForeignKey](https://docs.djangoproject.com/en/5.0/topics/db/examples/many_to_one/)

```
class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

```

### Many-to-Many Relationships

- ManyToManyField: Define a [many-to-many relationship](https://docs.djangoproject.com/en/5.0/topics/db/examples/many_to_many/).

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

class Book(models.Model):
    title = models.CharField(max_length=200)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

```

### One-to-One Relationships

- OneToOneField: Define a [one-to-one relationship](https://docs.djangoproject.com/en/5.0/topics/db/examples/one_to_one/).

```
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField()

```

## Conclusion

Working with databases in Django involves understanding how to configure your database, define models, and perform CRUD operations efficiently. Using PostgreSQL with Django's ORM simplifies these tasks, allowing you to write Python code instead of SQL queries. This guide provides a foundational understanding.