Models in Django

A model is the sole, authoritative source of your data’s information. It comprises both the fields and the actions needed by the data stored. As a convention, one model maps to a single table in the database.

The fundamentals:

  • Each model is a Python class with a Django subclass -django.db.models.Model
  • Each model attribute corresponds to a database field.
  • Django provides an automatically built database-access API as a result of all of this;

Example

In this model example, we explore a Student with a first_name and last_name field names:

from django.db import models

class Student(models.Model):
  first_name = models.CharField(max_length=30)
  last_name = models.CharField(max_length=30)
  age = models.IntegerField(max_length=10)

The model’s fields are the last_name, age, and first_name in the case above. These fields appear as attributes of the class maps to columns in the database.

The above Student model would create a database table similar to the one below:

CREATE TABLE school_student (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL,
"age" varchar(30) NOT NULL,);

The table’s name, school_student, is derived automatically from model metadata, although it is changeable. In addition, an id field is added by default, but this behavior is alterable.

Although the CREATE TABLE SQL in this example is formatted in MySQL syntax, it’s important to note that Django employs SQL suited to the database backend selected in your settings file.

Making use of models

After defining your models, you’ll need to tell Django that you’ll be using them. You can do this by updating your settings file and adding the module’s name that includes your models to the INSTALLED_APPS in the setting.py file.

If your application’s models are stored in the module schoolapp.models, which is the package structure established for an application by the manage.py startapp script, INSTALLED_APPS should include the following:

INSTALLED_APPS = [
#…
'schoolapp,'
#…
]

Ensure to execute manage.py migrate after adding new apps to INSTALLED_APPS. In addition, you can run the following command to create the necessary migrations.

python manage.py makemigrations

Fields

The list of database fields defined by a model is the most significant – and the only – portion of the model. Class characteristics define which fields are available. Choose field names that don’t clash with the model API, such as clean, save, or delete.

Examples:

from django.db import models

class Class(models.Model):
  first_name = models.CharField(max_length=50)
  last_name = models.CharField(max_length=50)
  instrument = models.CharField(max_length=100)
  
class Student(models.Model):
  current_class = models.ForeignKey(Class, on_delete=models.CASCADE)
  name = models.CharField(max_length=100)
  reg_date = models.DateField()
  dob = models.DateField()

Types of fields

Each field should be an instance of the Field class in your model. The class types are essential to Django concerning the following concepts:

The column type specifies the data type to be stored in the database. For instance, when you want to render a field in a form, e.g., input type=” text,” it is the default HTML widget to utilize.

Validation requirements are utilized in Django’s admin and automatically generated forms. Django has many built-in field types; the whole list is found in the model field reference. If Django’s built-in fields aren’t sufficient, you can easily add your own.

Field Options

Each field accepts a defined set of field parameters. For example, the max length option in CharField and its subclasses sets the size of the VARCHAR field in the database that is responsible for storing the data.

There’s also a set of standard arguments available to all field types. All of these things are optional. The reference goes into great detail about them, but here’s a quick rundown of the most commonly utilized ones:

null

If null is set to True, Django can store values that appear as empty in the database as NULL. However, note that the default behavior is setting the value to False.

blank

Just like in null, the default value is False. But if it is set to True, then it means that the value can be blank.

Please do not confuse this with null because they are different. The difference between null and blank is that null is strictly database-related, whereas blank is strictly validation-related. If blank=True is set for a field, form validation will allow an empty value to be entered. If blank=False is set for a field, it will be needed.

Choices

The choices field can be filled with a sequence of 2-tuples. If it has been set, the selection box widget will
have options limited to the ones provided. It is no longer the usual text field.

STREAMS_IN_SCHOOL = [
    ('E', 'East'),
    ('W', 'West'),
    ('N', 'North'),
    ('S', 'South'),
]

The value recorded in the database is the first element in each tuple. The form widget in the field displays the second element. The used method displays a value for a field with choices given a model instance. Consider the following scenario:

from django.db import models

class Student(models.Model):
    STUDENT_HEIGHT = (
        ('S', 'Short'),
        ('M', 'Medium'),
        ('T', 'Tall'),
    )
    name = models.CharField(max_length=60)
    s_height = models.CharField(max_length=1, choices=STUDENT_HEIGHT)

Enumeration classes additionally define options:

from django.db import models

class AcademicPerformance(models.Model):
  PositionType = models.TextChoices('PositionType', 'EXCELLENT GOOD AVERAGE')
  name = models.CharField(max_length=60)
  medal = models.CharField(blank=True, choices=PositionType.choices, max_length=10)

default

It refers to the default value of a given field. The latter is either a value or a callable object. If it is the last-mentioned, its invoking happens upon creating a new object.

help text

help text is vital for two reasons. First, it appears on your form widgets to guide or help. Secondly, it is used in the documentation of your project.

primary key

A field is known as a primary key if the primary key value has been set to True.

Django will automatically add an IntegerField to contain the primary key if you don’t provide a primary key and set its value to True for any fields in your model. Thus, it is not a must-do thing to explicitly set the primary key value unless you wish to change the default primary-key behavior.

The primary key is a read-only field. When you modify the primary key value on an existing object and save it, a new object is produced alongside the previous one. Consider the following scenario:

from django.db import models

class Student(models.Model):
  adm = models.CharField(max_length=100, primary_key=True)
  
student = Student.objects.create(name='Ann')
student.name = 'Tom'
student.save()
Student.objects.values_list('name', flat=True)

unique

If set to True, it will hold unique data only throughout the table. These are merely quick summaries of the most frequent field selections.

Primary key fields that are automatically generated

Django assigns an auto-incrementing primary key to each model by default, with the type individually defined per app in AppConfig.default_auto_field. Alternatively, it is set globally in the DEFAULT_AUTO_FIELD parameter. The default use case is as follows:

id = models.BigAutoField(primary_key=True)

Verbose Field names

Except for ForeignKey, ManyToManyField, and OneToOneField, each field type accepts an optional initial positional argument — a long name. If the verbose name isn’t specified, Django will build it using the field’s attribute name, converting underscores to spaces.

The verbose name in this case is,

age = models.CharField("students age", max_length=30)

Relationships

Relational databases’ strength depends on their ability to link tables together. The three most popular forms of database relationships are many-to-one, many-to-many, and one-to-one, and Django provides means to define them.

one-to-many

Use django.db.models to define a many-to-one relationship. You utilize it the same way as any other Field type: adding it to your model’s class attribute.

A positional argument is required for ForeignKey: the class to which the model is linked.

Use the following definitions if a Student model has a StudentClass – that is, a StudentClass has several students, but each Student only has one Class – for example:

from django.db import models

class StudentClass(models.Model):
  # …
  pass

class Student(models.Model):
  student = models.ForeignKey(StudentClass, on_delete=models.CASCADE)
  # …

Many-to-many

Use the ManyToManyField to define a many-to-many relationship. You utilize it the same way as any other Field type: adding it to your model’s class attribute.

A positional argument is required by ManyToManyField: the class to which the model belongs.

For instance, if a Student includes many Teacher objects, a Teacher can teach many students, and each Student is related to multiple teachers.

from django.db import models

class Teacher(models.Model):
  # …
  pass

class Student(models.Model):
  # …
  teachers = models.ManyToManyField(Teacher)

You can also create recursive connections (an object having a many-to-many relationship to itself) and relationships to models that haven’t been specified yet, much like you can with ForeignKey.

The name of a ManyToManyField (teachers in the example above) should be a plural describing the set of related model objects, although this isn’t needed. It doesn’t matter which model contains the ManyToManyField; nevertheless, you should only use it in one of the models.

One-to-one

Use OneToOneField to specify a one-to-one relationship. You utilize it the same way as any other Field type: adding it to your model’s class attribute.

When an object’s primary key “extends” another object in any way, this is very valuable. A positional argument is required by OneToOneField: the class to which the model belongs.

For example, while creating the database of “students,” you would include basic information such as an address, phone number, and so on. Instead of repeating yourself and recreating those fields in the StudentHealth model, you might make StudentHealth have an OneToOneField to Students. You’d generally manage this using inheritance, which entails an implicit one-to-one link.

Key takeaways:

  • OneToOneField fields also accept an optional parent link argument.
  • OneToOneField classes used to be the primary key on a model by default. It is no longer the case. But you can still use the primary key argument manually if you want. As a result, it’s now feasible to have several OneToOneField fields on a single model.

Restrictions on field names

Model field names are subject to various constraints in Django. For example,

A reserved Python word cannot be used as a field name since this would result in a Python syntax error. Consider the following scenario:

class Student(models.Model):
  pass = models.IntegerField() # 'pass' is a reserved word!

Due to how Django’s query lookup syntax works, a field name cannot have more than one underscore in a row. Consider the following scenario:

class Student(models.Model):
  first_name = models.IntegerField() # 'first_name' has two underscores!

For similar reasons, a field name cannot finish in an underscore.

These restrictions are circumvented because your field name does not have to match the name of a database column. That is because Django escapes all database table and column names in every underlying SQL query, SQL reserved words like join, where, and select are allowed as model field names. It employs the quoting syntax of the database engine you’re using.

custom fields

You can come up with your field class if one of the standard model fields is not covering your needs sufficiently or if you want to employ some less popular database column kinds. The process of creating custom model fields covers everything you need to know about generating your fields.

meta options

Use an inner class Meta to give your model metadata, like this:

class student(models.Model):
  first_name = models.CharField(max_length=50)
  last_name = models.CharField(max_length=50)
  
  class Meta:
      ordering = ['first_name']
      app_label = 'student_app'
      proxy = True
      verbose_name = "MZ-stu"

Ordering choices (ordering), database table name (db_table), and human-readable single and plural names (verbose_name and verbose_name_plural) are examples of model metadata. None of these are essential, and adding the Meta class to a model is optional.

model attributes

Objects

The Manager is the most crucial feature of a model. It’s the interface via which Django models get database query operations and obtain instances from the database. The default name objects if no custom Manager is defined. Model classes, not model instances, are the only way to access managers.

Methods in Models

To add custom “row-level” functionality to your objects, define custom methods on a model. Model methods should act on a specific model instance, whereas Manager methods execute “table-wide” things.

It is a valuable strategy for encapsulating business logic in a single location – the model.

This model, for example, has a few unique methods:

from django.db import models

class Student(models.Model):
  first_name = models.CharField(max_length=50)
  last_name = models.CharField(max_length=50)
  birth_date = models.DateField()

  def birth_boomer_status(self):
      "Returns the students baby-boomer status."
      import datetime
      if self.birth_date < datetime.date(1938, 6, 1):
          return "Pre-boomer"
      elif self.birth_date < datetime.date(1960, 6, 1):
          return "Baby boomer"
      else:
          return "Post-boomer"

  @property
  def students_name(self):
      "Returns the students full name."
      return '%%s %%s' %% (self.first_name, self.last_name)

below – but there are a few that you should define practically every time:

str()

A “magic method” in Python returns the string representation of any object. Python and Django will utilize this when a model instance needs to be coerced like in a plain string. It is most noticeable when an object is displayed in an interactive console or the admin.

You should always declare this function because the default isn’t beneficial.

get_absolute_url()

It instructs Django on how to generate an object’s URL. Django uses it in its admin interface to find a URL for an item. Any object with a URL that uniquely identifies this function should be defined.

Overriding model methods that have already been declared

You’ll want to customize another set of model methods that encapsulate many database actions. You’ll frequently wish to alter the behavior of save() and delete(). You can override these methods and any other model method to change behavior.

If you want something to happen every time you save an object, overriding the built-in methods is an everyday use case. For instance, for a list of the parameters that save() allows, check the documentation for save():

from django.db import models

class Student(models.Model):
  name = models.CharField(max_length=100)
  tagline = models.TextField()

  def save(self, *args, **kwargs):
      do_something()
      super().save(*args, **kwargs)  # Call the "real" save() method.
      do_something_else()

It is also possible to prevent saving:

from django.db import models

class Student(models.Model):
  name = models.CharField(max_length=100)
  tagline = models.TextField()

  def save(self, *args, **kwargs):
      if self.name == " Brian ":
          return # Brian cannot exist as a student!
      else:
          super().save(*args, **kwargs)  # Call the "real" save() method.

It’s critical to remember to invoke the superclass method — that’s the superclass method super().save(*args, **kwargs) business – verify that the object is saved to the database. If you forget to call the superclass function, the default behavior will not occur, and the database will remain unaffected.

It’s also crucial to pass the arguments that can be supplied to the model method across – this is what the *args, **kwargs bit does. Django will occasionally add new parameters to built-in model methods to expand their capabilities. When you use *args and **kwargs in your method declarations, you can rest assured that your code will handle those arguments when they are added.

On bulk operations, overridden model methods are not called.

When deleting objects in bulk with a QuerySet or due to a cascading delete, each item’s delete() function is not always executed. You can use either pre_delete or post_delete signals to ensure that specific delete logic is executed. In some cases, you can use both.

There isn’t a fix because save(), pre_save, and post_save aren’t called when creating or modifying objects in bulk.

Similar Posts

Leave a Reply

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