Django meta class

A metaclass is a class whose instance is a class. It defines the behavior of classes and their instances, a class decorator. In the Django web framework, a meta class is used to define an extra option for a model or forms so that other classes withing the web app know the capabilities of the model. The meta class is referenced during the definition of the object instance before you define the class itself.

 Pythons support metaclasses in ways that other programming languages don’t. You can define custom metaclasses. In many cases, it isn’t much necessary to define these custom classes, but if you have used the Django web framework before, then you know metaclasses are important in models and forms.

If you work with python then you’ve used metaclasses without knowing it. Many Python programmers don’t stress about metaclasses in their code. However, you might find yourself having to use a metaclass.

Uses of Metaclasses in Python

  • proxies
  • Adding new methods
  • Property creation
  • Resource locking 
  • Profiling and logging

Defining a Metaclass in Python

A metaclass is defined as you define a normal class in Python but inheriting from type instead of object.

class HelloMeta(type):
    def __new__(cls, classname, superclasses, attributedict):
         print("class name: ", classname)
         print("super classes: ", superclasses)
         print("attribute: ", attributedict)

Let’s use the HelloMeta class example in the following example.

class A:
    pass
class Hello(A, metaclass=HelloMeta):
    pass
.................................
Result:
classname:  Hello
super classes:  (<class '__main__.A'>,)
attributedict:  {'__module__': '__main__', '__qualname__': 'Hello'}

We can go on and implement some useful and complicated metaclasses but this post is not about metaclasses in python but in the Django web framework.

Metaclasses in Django Models and Forms

In Django, we use a metaclass for defining extra attributes of either our model or form classes. The Meta API in Django helps other parts of the app to know the capabilities of each model.

What is class meta in Django

A metaclass in Django is a class attached to every model class of form class. It defines table name, verbose names, permissions, class nature (Whether abstract or not), default managers for the model, ordering when instances are called and many more other examples.

Metaclasses appear so much in the Django framework and you have to use them in your models and also your forms.

Simple Django Metaclass Example

A typical Django model class look like this:

class Student(models.Model):
     name = models.CharField(_('Student name'))
     .....................................
     class Meta:
         db_table = "dzd_students"
         verbose_name = _("Student")
         verbose_name_plural = _("Students")

We created a data model for Students and named it dzd_students [db_table], and the “Student” verbose name (human-readable name of the student instance)  using [verbose_name] and the plural for the verbose name. Our Meta class helped us name the instance object of the student class and also enabled us to name our database table for the model we just created.

Meta Options in Django

Let’s explore all the possible Django Metaclass fields you can use in your application.

abstract

Abstract option in Django models allows you to create a base model class with common fields and then let the other model classes inherit the abstract class.

If abstract is set to true then the class is an abstract class and can be inherited.

class ModelName(models.Model):
      ........................
      class Meta:
           abstact = true

Let’s explore an example of using an abstract class in Django. The following example contacts two classes the first one is the base model class which is going to be inherited by other models.

class BaseUser(models.Model):
      name = models.CharField()
      surname = models.CharField()
      dob = models.CharField()

      class Meta:
           abstact = true
class Teacher(BaseUser):
      grade = models.CharField()
      teaching_class = models.CharField()
      motto = models.CharFields()  
class Student(BaseUser):
      teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)

The Student and the Teacher model have the same “name, surname, dob” fields and so no reason to repeat them in each model. So the best solution is to define a base class with the common fields and let the Teacher and Student model inherit from it.

This is a comprehensive example of abstract classes in the Django framework. You can try new tricks and more fields in your base abstract class and child model classes.

db_table

The db_table meta field is used to name the database table created by the model. By default, Django automatically generates a table name using the model name and the application name that contains the model. Django joins the app label and the model’s class name.

The db_table meta option is then used to override the default Django app_label + model class name. Let’s see how the db_table meta option works with an example

class User(models.Model):
      name = models.CharField()
      surname = models.CharField()
      dob = models.CharField()

      class Meta:
           db_table = "bufjf_user"

With the db_table option, you can customize the database table names the way you want.

db_tablespace

A tablespace is a location where the actual data is stored. It offers an abstraction layer between the physical and logical layout of the database. In Django, you can define your own db_tablespace in the Django meta class option of every database model. Let’s explore one example:

class ExampleTableSpace:
    name = models.CharField(max_length=7)
    ....................................
    class Meta:
        db_tablespace = "mytables"

managed

If you set manage=True, the default setting, Django will manage your database table’s lifecycle. Django will create a database table with the migration command. If your model is backed by a database view, and you don’t want to issue a CREATE_TABLE instruction on migration, you can set the managed option to false. If you haven’t used the option, you can leave it as default.