Django Models: Basics
Tags: django, webdev, backend, programming
Published: 2023-04-09 21:00:09

Hi there! Today we're going to talk about Django models. Now, when we talk about Django models, we're talking about something that's really important to Django web applications.

So, what is a Django model? It's basically a fancy word for a way to represent information in a database. Think of it like a blueprint for a table in a database. When you create a Django model, you're telling Django what kind of information you want to store in your database, and how you want to store it.

Why is this important? Well, Django models make it really easy to work with databases. You can use Python code to do things like create, read, update, and delete information in your database. This is really helpful because it means you don't have to write SQL code directly, which can be really tricky.

So let's say you're building a web application for a library, and you want to create a model for books. Here's an example of what that might look like:


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

Now, let's break this down a bit. The first thing we're doing is importing the models module from Django. This is important because it gives us access to all the tools we need to create our model.

Next, we define our Book model. This is a Python class that inherits from the models.Model class. This is important because it tells Django that this is a model that we want to store in our database.

Inside the Book class, we define three fields: name, is_available, and pages. These fields correspond to columns in the database table that Django will create for us. We use the models.CharField, models.BooleanField, and models.IntegerField classes to specify the type of each field.

For example, the name field is a CharField, which means it will store text. We also use the max_length argument to specify that we want to limit the length of the text to 200 characters. The is_available field is a BooleanField, which means it will store either True or False. We use the default argument to specify that we want the default value to be True. Finally, the pages field is an IntegerField, which means it will store whole numbers.

We also define a str method for our Book class. This is just a fancy way of saying that we want to define how our Book objects should be represented as strings. In this case, we want to use the name field as the string representation.

Now, let's talk about relationships between models. There are three main types of relationships in Django: one-to-one, one-to-many, and many-to-many.

## **One-To-One Relationship

**In a one-to-one relationship, each instance of one model corresponds to exactly one instance of another model. For example, let's say we have a User model and a Profile model. Each user would have exactly one profile, and each profile would correspond to exactly one user. Here's an example of what that might look like:


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

In this example, we define a Profile model that has a one-to-one relationship with the built-in User model in Django. We use the OneToOneField class to define this relationship. We also define a bio field that will store some text about the user.

## **One-to-many Relationship

**In a one-to-many relationship, each instance of one model can be linked to multiple instances of another model. For example, a blog post model might be linked to multiple comments.

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

In this example, we have a Post model and a Comment model. Each comment is linked to exactly one post via a ForeignKey relationship. The on_delete=models.CASCADE argument specifies that if a post is deleted, all corresponding comments will also be deleted.

## **Many-to-many Relationship

**in a many-to-many relationship, instances of one model can be linked to multiple instances of another model, and vice versa. For example, a Student model might be linked to multiple Course models, and each Course model might be linked to multiple Student models.

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


In this example, we have a Student model and a Course model. Each student can be linked to multiple courses via a ManyToManyField relationship. Similarly, each course can be linked to multiple students.

## **Django Model Meta class

**The Django models Meta class provides a way to specify metadata about a model that is not a field. This class is optional and is used to provide additional information about the model, such as ordering, database table name, and verbose name. Here are some best practices for using the Meta class:


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

**Specify the database table name**: By default, Django creates a database table name by combining the app and model names. You can override this behaviour by specifying a db_table attribute in the Meta class. This can be useful if you want to use a different table name or schema for your model.

**Define ordering**: You can define the default ordering for a model using the ordering attribute in the Meta class. This can be a string or a list of strings that specify the fields to order by. For example, ordering = [‘-date_created’] would order the model by the date_created field in descending order.

**Set verbose name and plural name**: The verbose_name and verbose_name_plural attributes in the Meta class can be used to specify human-readable names for your model. These names are used in the Django admin and other places where the model is displayed.

**Use abstract models:** If you have multiple models that share a lot of fields and behaviour, you can use an abstract model to define the common fields and behaviour. Abstract models are not created in the database but can be used as the base for other models. You can specify an abstract model by setting the abstract attribute in the Meta class to True.

By using the Meta class in your Django models, you can provide additional information about your models and make them more flexible and reusable.


## **Model Abstract

**In Django, an abstract model is a model that doesn’t create any database table of its own but provides common fields and methods that can be inherited by other models. Abstract models can be used to avoid code duplication and provide common functionality across multiple models.


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

In the above example, we define an abstract model _TimeStampedModel_ that provides created_at and updated_at fields. We then define our Book and Author models, which inherit from the TimeStampedModel. This allows us to add created_at and updated_at fields to both models without repeating the field definitions and related code.

By setting abstract=True in the Meta class of the TimeStampedModel, we tell Django that this is an abstract model that doesn’t create its database table.

Note that when defining an abstract model, it’s important to set abstract=True in the Meta class and not to include any db_table or app_label attributes, as this can cause problems with Django’s database schema generation.

**

### Django Model Methods

**In Django models, a method is a function that is defined within the class and can be called on an instance of the class. These methods can be used to perform various operations related to the model.

There are many methods available in Django models, including:

**__str__:** Returns a string representation of the model instance.

**save: **Saves the model instance to the database.

**delete: **Deletes the model instance from the database.

**full_clean: **Performs model validation and raises a ValidationError if there are any errors.

**get_absolute_url:** Returns the URL for the detail view of the model instance.

**clean: **Performs additional model validation.

**validate_unique:** Checks for unique constraints on the model.

In addition to these built-in methods, you can define your methods in a Django model to perform custom operations on the model data.

For example overriding the save() method:

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

In this example, we import the slugify function from Django.utils.text to generate a slug from the book’s name. We then override the save() method to check if the slug field has been set (i.e., whether the book is being saved for the first time). If the slug is empty, we generate one by calling slugify() on the book’s name. Finally, we call the superclass implementation of save() to save the model instance to the database.

This is just one example of how you can override the save() method in Django. The possibilities are endless, and you can customize this method to fit your specific needs.

**Common Best Practices
**When it comes to writing good Django models, there are a few best practices to keep in mind. These practices can help ensure that your models are easy to read, understand, and maintain. Let’s dive into some of them:

Use naming conventions: Django has a set of naming conventions that are widely used across the community. For example, model names should be singular and in CamelCase, while field names should be lowercase and separated by underscores. Following these conventions can make your code more readable and easier to understand.
Keep models simple: It’s important to keep your models simple and focused on a single responsibility. Avoid adding too many fields or methods to a single model, and consider breaking up complex models into smaller, more focused ones. This can make your code more modular and easier to test.
Add constraints: Constraints can help ensure data integrity by preventing invalid data from being stored in the database. Consider adding constraints such as unique, null, and default to your models where appropriate.
Test models thoroughly: Writing tests for your models can help catch errors early and ensure that your code works as expected. Test each field and method of your model to ensure that they work as intended. Also, consider using tools like Django’s TestCase and pytest-django to simplify testing.
By following these best practices, you can write clean, maintainable Django models that are easy to work with and less errors.


Full documentation for Django models: https://docs.djangoproject.com/en/4.2/topics/db/models/

If you found this article helpful, please consider giving it a heart and sharing it with others who may benefit. Happy Coding!