Django

Create Django Models

django-logo

Create Django Models

Introduction:

  • We can produce the Django models that outline the fields and behaviors of the journal application information that we are going to be storing.
  • These models map the information from your Django application to the info. It’s what Django uses to come up with the info tables via their object relative mapping (ORM) API known as “models.”

Prerequisites:

You ought to have MySQL put in on Associate in Nursing Ubuntu 16.04 server, and you must even have a info association started along with your Django application.

Step 1 — Produce Django Application

To keep with the Django philosophy of modularity, we are going to produce a Django app at intervals our project that contains all of the files necessary for making the journal web site.

Let’s get in the subsequent directory:

cd ~/my_blog_app
. env/bin/activate
cd blog

From there, let’s run this command:

python manage.py startapp blogsite

At this point, you’ll have the following directory structure for your project:

my_blog_app/
└── blog
    ├── blog
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-35.pyc
    │   │   ├── settings.cpython-35.pyc
    │   │   ├── urls.cpython-35.pyc
    │   │   └── wsgi.cpython-35.pyc
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── blogsite
    │   ├── admin.py
    │   ├── apps.py
    │   ├── __init__.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    └── manage.py

The file we will automatically focus on for this tutorial, will be the models.py file in python.

Step 2 — Add the Posts Model

First we want to open and edit the models.py file so it contains the code for generating a Post model. A Post model contains the subsequent info fields:

  • title — The title of the journal post.
  • slug — wherever valid URLs square measure keep and generated for web content.
  • content — The matter content of the journal post.
  • created_on — The date on that the post was created.
  • author — The one who has written the post.

Now, amendment directories to wherever the models.py file is contained.

cd ~/my_blog_app/blog/blogsite

Use the cat command to point out the contents of the file in your terminal.

cat models.py

The file ought to have the subsequent code, that imports models, beside a comment describing what’s to be placed into this models.py file.

models.py
from django.db import models

#Produce your models here.

Using your favorite text editor or IDE, add the subsequent code to the models.py file. We’ll use nano as our text editor. But, you’re welcome to use no matter you like.

nano models.py

Within this file, the code to import the models API is already extra, we are able to plow ahead and delete the comment that follows. Then we’ll import slugify for generating slugs from strings, and Django’s User for authentication like so:

models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User

Then, add category class method on the model class we’ll be vocation Post, with the subsequent info fields, title, slug, content, created_on and author.

models.py
...
class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

Next, we’ll add practicality for the generation of the address and the function for saving the post. This can be crucial, as a result of this creates a unique link to match our unique post.

models.py
...
@models.permalink
 def get_absolute_url(self):
     return ('blog_post_detail', (),
          {
             'slug': self.slug,
          })
 def save(self, *args, **kwargs):
     if not self.slug:
         self.slug = slugify(self.title)
         super(Post, self).save(*args, **kwargs)

Now, we’d like to inform the model however the posts ought to be ordered, and displayed on the net page. The logic for this may be more to a nested inner Meta category. The Meta category usually contains different necessary model logic that may not associated with database field definition.

models.py
...
   class Meta:
        ordering = ['created_on']
        def __unicode__(self):
            return self.title

Finally, we’ll add the Comment model to the current file. This involves adding another category named Comment with models. Models in its signature and also the following database fields outlined:

  • name — The name of the person posting the comment.
  • email — The email address of the person posting the comment.
  • text — The text of the comment itself.
  • post — The post with which the comment was made.
  • created_on — The time the comment was created.
models.py
...
class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)

When finished, your complete models.py file should look like this:

models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User


class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

    @models.permalink
    def get_absolute_url(self):
        return ('blog_post_detail', (),
                {
                   'slug': self.slug,
                })

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title


class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)

Be bound to save and shut the file.

READ  Enable and Connect the Django Admin Interface

With the models.py file got wind of, we are able to prolong to update our settings.py file.

Step 3 — Update Settings

Now that we’ve more models to our application, we tend to should inform our project of the existence of the blogsite app that we’ve simply more. we tend to do that by adding it to the INSTALLED_APPS section in settings.py.

Navigate to the directory wherever your settings.py lives.

cd ~/my_blog_app/blog/blog

From here, open up your settings.py file, with nano, for example, victimization the command nano settings.py.

With the file open, add your blogsite app to the INSTALLED_APPS section of the file. As shown below.

settings.py
# Application definition
INSTALLED_APPS = [
    'blogsite',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

With the blogsite app additional, you’ll save and exit the file.

At this time we tend to move on to apply these changes.

Step 4 — Build Migrations

With our models Post and Comment additional, future step is to use these changes so our MySQL information schema acknowledges them and creates the required tables.

Let’s take a glance at what tables exist already in our blog_data information.

To try this, we want to log in to MySQL server.

Note: During this example, we’ll be exploitation the username root with no secret, however you ought to use the username and secret you’ve got discovered for MySQL.

mysql blog_data -u root

You’ll notice that if you kind into the SHOW DATABASES; command, you will see the following:

Output:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| blog_data          |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

We are watching the blog_data information and consider the tables that exist already, if any.

USE blog_data;

Then, list the tables that exist within the blog_data database:

SHOW TABLES;

Output:

Empty set (0.00 sec)

This django migrations table that we tend to receive as output provides the Django migration system with this state of the information, permitting it to grasp that migrations have to be compelled to be run.

READ  Enable and Connect the Django Admin Interface

Now we are going to proceed to form the migrations that apply the changes we’ve created in models.py.

Close out of MySQL with CTRL + D.

First, we tend to should package up our model changes into individual migration files exploitation the command make migrations. These files are like that of commits during a version system like puke.

Now, if you navigate to ~/my_blog_app/blog/blogsite/migrations and run ls, you will notice that there’s solely Associate in Nursing coryza.py file. this may amendment once we tend to add the migrations.

Change to the journal directory exploitation cd, like so:

cd ~/my_blog_app/blog
python manage.py makemigrations

You ought to then see the subsequent output in your terminal window:

Output:

Migrations for 'blogsite':
  blogsite/migrations/0001_initial.py
    - Create model Comment
    - Create model Post
    - Add field post to comment

Remember, once we navigated to /~/my_blog_app/blog/blogsite/migrations and it solely had the coryza.py file? If we tend to currently cd back to it directory we’ll see that 2 things are additional, __pycache__ and 0001_initial.py. The 0001_initial.py file was mechanically generated after you ran make migrations. an analogous file are generated anytime you run make migrations.

Run less 0001_initial.py if you would like to ascertain what the file contains.

Now navigate to /~/my_blog_app/blog.

Since we’ve created a migration file, we tend to should apply the changes these files describe to the information exploitation the command migrate. however initial let’s see what current migrations exists, exploitation the showmigrations command.

python manage.py showmigrations

Output:

admin
 [ ] 0001_initial
 [ ] 0002_logentry_remove_auto_add
auth
 [ ] 0001_initial
 [ ] 0002_alter_permission_name_max_length
 [ ] 0003_alter_user_email_max_length
 [ ] 0004_alter_user_username_opts
 [ ] 0005_alter_user_last_login_null
 [ ] 0006_require_contenttypes_0002
 [ ] 0007_alter_validators_add_error_messages
 [ ] 0008_alter_user_username_max_length
 [ ] 0009_alter_user_last_name_max_length
blogsite
 [ ] 0001_initial
contenttypes
 [ ] 0001_initial
 [ ] 0002_remove_content_type_name
sessions
 [ ] 0001_initial

You’ll notice the migration we’ve simply added for blogsite, that contains the migration 0001_initial for models Post and Comment.

Now let’s see the SQL statements which will be dead once we have a tendency to create the migrations, victimization the subsequent command. It takes within the migration and therefore the migration’s title as Associate in Nursing argument:

python manage.py sqlmigrate blogsite 0001_initial

As you see below, this can be the particular SQL question being created behind the scenes.

BEGIN;
--
-- Create model Comment
--
CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL);
--
-- Create model Post
--
CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL);
--
-- Add field post to comment
--
ALTER TABLE `blogsite_comment` ADD COLUMN `post_id` integer NOT NULL;
ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);
COMMIT;

Let’s now perform the migrations so that they get applied to our MySQL database.

python manage.py migrate

We will see the following output:

Output:

Operations to perform:
  Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying blogsite.0001_initial... OK
  Applying sessions.0001_initial... OK

You have currently with success applied your migrations.

READ  Enable and Connect the Django Admin Interface

It is vital to stay in mind that there square measure three caveats to Django migrations with MySQL as your backend, as declared within the Django documentation.

  • Lack of support for transactions around schema alteration operations.
  • In alternative words, if a migration fails to use with success, you may have to be compelled to manually unpick the changes you’ve created so as to try another migration.
  • It’s unacceptable to rollback, to Associate in Nursing earlier purpose, before any changes were created within the failing migration.
  • For most schema alteration operations, MySQL can absolutely rewrite tables. Within the worst case, the time complexions be proportional to the amount of rows within the table to feature or take away columns in line with the Django documentation, this might be as slow together minute per million rows.
  • In MySQL, there square measure little limits on name lengths for columns, tables and indices. There’s conjointly a limit on the combined size of all columns and index covers.
  • Whereas another backends will support higher limits created in Django, a similar indices can fail to be created with a MySQL backend in situ.

For every information you think about to be used with Django, take care to weigh the benefits and downsides of each.

Step 5 — Verify information Schema

With migrations complete, we must always verify the successful generation of the MySQL tables that we’ve created via our Django models.

To do that, run the subsequent command within the terminal to log in to MySQL.

mysql blog_data -u root

Now show the databases that exist.

SHOW DATABASES;

Select our information blog_data:

USE blog_data;

Then type the subsequent command to look at the tables,

SHOW TABLES;

You should see the following:

Output:

+----------------------------+
| Tables_in_blog_data        |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| blogsite_comment           |
| blogsite_post              |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+

You’ll see blogsite_comment and blogsite_post. These area unit the models that we’ve created ourselves. Let’s validate that they contain the fields we’ve outlined.

DESCRIBE blogsite_comment;

Output:

+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| name       | varchar(42)  | NO   |     | NULL    |                |
| email      | varchar(75)  | NO   |     | NULL    |                |
| website    | varchar(200) | YES  |     | NULL    |                |
| content    | longtext     | NO   |     | NULL    |                |
| created_on | datetime(6)  | NO   |     | NULL    |                |
| post_id    | int(11)      | NO   | MUL | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)
DESCRIBE blogsite_post;

Output:

+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| title      | varchar(255) | NO   |     | NULL    |                |
| slug       | varchar(255) | NO   | UNI | NULL    |                |
| content    | longtext     | NO   |     | NULL    |                |
| created_on | datetime(6)  | NO   |     | NULL    |                |
| author     | longtext     | NO   |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)

We have verified that the database tables were successfully generated from our Django model migrations.

Conclusion

In this tutorial we’ve with successfully added models for basic practicality in an exceedingly diary internet application. You have learned the way to code models, however migrations work and also the method of translating Django models to actual MySQL Database tables.

About the author

Venkatesan Prabu

Venkatesan Prabu

Wikitechy Founder, Author, International Speaker, and Job Consultant. My role as the CEO of Wikitechy, I help businesses build their next generation digital platforms and help with their product innovation and growth strategy. I'm a frequent speaker at tech conferences and events.

Add Comment

Click here to post a comment