Creating the content models

The Content model of our courses application contains a generic relation to associate different types of content to it. We will create a different model for each type of content. All content models will have some fields in common and additional fields to store custom data. We are going to create an abstract model that provides the common fields for all content models.

Edit the models.py file of the courses application and add the following code to it:

class ItemBase(models.Model):
owner = models.ForeignKey(User,
related_name='%(class)s_related',
on_delete=models.CASCADE)
title = models.CharField(max_length=250)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)

class Meta:
abstract = True

def __str__(self):
return self.title

class Text(ItemBase):
content = models.TextField()

class File(ItemBase):
file = models.FileField(upload_to='files')

class Image(ItemBase):
file = models.FileField(upload_to='images')

class Video(ItemBase):
url = models.URLField()

In this code, we define an abstract model named ItemBase. Therefore, we have set abstract=True in its Meta class. In this model, we define the owner, title, created, and updated fields. These common fields will be used for all types of content. The owner field allows us to store which user created the content. Since this field is defined in an abstract class, we need different related_name for each sub-model. Django allows us to specify a placeholder for the model class name in the related_name attribute as %(class)s. By doing so, related_name for each child model will be generated automatically. Since we use '%(class)s_related' as related_name, the reverse relation for child models will be text_relatedfile_related, image_related, and video_related respectively.

We have defined four different content models, which inherit from the ItemBase abstract model. These are as follows:

  • Text: To store text content
  • File: To store files, such as PDF
  • Image: To store image files
  • Video: To store videos; we use an URLField field to provide a video URL in order to embed it

Each child model contains the fields defined in the ItemBase class in addition to its own fields. A database table will be created for the Text, File, Image, and Video models respectively. There will be no database table associated to the ItemBase model since it is an abstract model.

Edit the Content model you created previously and modify its content_type field as follows:

content_type = models.ForeignKey(ContentType,
on_delete=models.CASCADE,
limit_choices_to={'model__in':(
'text',

'video',
'image',
'file')})

We add a limit_choices_to argument to limit the ContentType objects that can be used for the generic relationship. We use the model__in field lookup to filter the query to the ContentType objects with a model attribute that is 'text', 'video', 'image', or 'file'.

Let's create a migration to include the new models we have added. Run the following command from the command line:

python manage.py makemigrations

You will see the following output:

Migrations for 'courses':
courses/migrations/0002_content_file_image_text_video.py
- Create model Content
- Create model File
- Create model Image
- Create model Text
- Create model Video

Then, run the following command to apply the new migration:

python manage.py migrate

The output you see should end with the following line:

Applying courses.0002_content_file_image_text_video... OK

We have created models that are suitable to add diverse content to the course modules. However, there is still something missing in our models. The course modules and contents should follow a particular order. We need a field that allows us to order them easily.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset