[PYTHON] Benefits of refining Django's Model

Introduction

It's been about three years since I started using web frameworks. My first web application development was PHP and Perl & CGI, but I met Django about three years ago and have been using it as my primary weapon ever since.

When I first started using it, my title was a student, so I started without any experience as a web engineer. At that time, I didn't have any practical experience in web technology or design, so I was trying to improve the condition of the Django project without having a concrete solution. As a result, I was able to obtain useful knowledge now that I am a member of society.

In this article, I'll summarize the design insights I've gained from my experience with Django. Personally, I have a problem in labeling the design concept, so I am also aiming to improve it. I hope I can tell you that there are some good things you can do to improve your Django project.

Refine your Django model

The model here is an inheritance of django.db.models.Model and is a class defined in models.py in each application.

For example, a model that represents one song can be written as follows.

class Artist(models.Model):
  name = models.CharField(null=False, max_lenght=200)

class Music(models.Model):
  name = models.CharField(null=False, max_lenght=200)
  artists = models.ManyToManyField(Artist)

The class Music that represents a piece of music has a field called ʻartists`. This represents the artist who made the song. For example, "Hitomi o Tojite" refers to "Ken Hirai model".

However, in this case, the role of "Ken Hirai" in the song is not specified. Many humans have the precondition that "Ken Hirai = singer", but machines cannot have information unless the preconditions that humans have are clearly stated.

It is also possible to give the skills of the artist to the ʻArtist` model. However, it is often the case that even one artist is multi-weapon and offers only one of multiple skills depending on how he collaborates. For example, Kenshi Yonezu may have the image of a "singer" in general, but he also provides music. What if the artist who received the song is "feat. Kenshi Yonezu"? The artist who received the song does not reflect Kenshi Yonezu's singing ability in his work.

In such cases, I think there may be some additional information in the association between the song and the artist. In that case, I think the way to write the model class is as follows.

class Artist(models.Model):
  name = models.CharField(null=False, max_lenght=200)

class Music(models.Model):
  name = models.CharField(null=False, max_lenght=200)

class MusicArtist(models.Model):
  music = models.ForeignKey(Music, on_delete=models.CASCADE)
  artsit = models.ForeignKey(Artist, on_delete=models.CASCADE)
  as_vocalist = models.BooleanField(default=False)
  as_producer = models.BooleanField(default=False)

Removed ʻartists from the Musicclass and defined a newMusicArtistmodel. TheMusicArtist model externally references the Music and ʻArtist models. It also holds the ʻas_vocalist and ʻas_producer fields as states.

By defining the MusicArtist model as described above, it is possible to record additional information in the association between music and artistry. With this, even if Kenshi Yonezu participates in the song as a music provider with "feat. Kenshi Yonezu", it is clearly stated that he is participating as a producer, not as a singer.

So far, the ʻArtist model and the Musicmodel have been defined independently, and a newMusicArtistmodel has been defined independently. The artist information of the song was supposed to be held in theMusic.artists` field, but it will now exist independently as associated information with a new state.

In addition, it can be said that the following efforts have been made through the above efforts.

--Nth normal form --Lightweight Domain Driven Design Experience

Nth normal form

Table normalization is a must-have task in back-end web application development.

In Django, one model basically represents one table. Also, if there is an externally referenced field in one model, create three tables including an intermediate table that connects the two models.

In general, I think it is good if the table normalization is completed up to the third normal form. However, in my case, as a result of the fun of the model class division mentioned above, it seems that it has been implemented up to the point called 5th normal form. The model classes have been split to make them look beautiful in terms of design and purpose, but they have produced unrealistic artifacts for production use.

You can achieve table normalization by subdividing the model class. However, over-normalization can significantly slow down query execution. It's possible with Django to be careful not to overdo it, and to use indexing etc. effectively while operating the model class so that it doesn't grow.

Lightweight Domain Driven Design Experience

I don't understand Domain Driven Design, as you can see from reading Eric's book and in his first year of career. However, as a result of aiming for a sophisticated Django model, I feel that I was able to touch the essence of DDD.

For example, in the example above, we added a model called MusicArtist to a model called Music that represents a song and a model called ʻArtistthat represents an artist.MusicArtist` is the concept of the artist who created the music, but it is now possible to express the information about the role of the artist involved in the music production from the information that they are just participating. It was. In other words, in the process of refining Django's model class, the domain was distilled and represented in the model class.

Personally, I feel that the Domain Driven Design-like experience gained through the act of refining the model class is a very powerful experience. In production operation, I think that there is a limit to expressing the domain only with the model class in Django, but by decomposing and defining the model class in detail without assuming production, the 5th normal form In addition to the experience, I was able to experience the domain class representation at the same time.

There is an Eloquent Model in Laravel, but I think that the Eloquent Model, like Django's model class, has a limit in expressing the domain. In other words, it is necessary to define a new class that expresses the domain, but I think that the experience of refining Django's model class can be utilized here.

in conclusion

When I first started using Django, I didn't have any reason or purpose for choosing it. As a result, I've learned a lot of knowledge and ideas by trying to clean up the configuration and design with Django. I've omitted it because of scale issues, but the existence of the Django REST Framework naturally gave me an idea like a resource thinking architecture. I highly recommend Django to students who are thinking about getting started with web frameworks! !!

I'm still in my first year as a software engineer, so I think it may contain incorrect descriptions and recognition, but I would appreciate it if you could point it out.

(The release has been delayed due to the full Advent calendar. I'm sorry!)

Recommended Posts

Benefits of refining Django's Model
Benefits of using slugfield in Django's model
Django's Model Form was amazing.
Benefits and examples of using RabbitMq
Memorandum of saving and loading model
Mathematical model of infectious disease epidemics
Python-Simulation of the Epidemic Model (Kermack-McKendrick Model)
Diversion of layers of trained keras model
Limit Views using Django's Permission model
[My note] Django's custom User model