Django blog development tutorial 4 - Let Django complete translation: migrating database

Keywords: Python Django Database shell

We've written the code for the blog database model, but that's just Python code. Django hasn't translated it into database language yet, so actually these database tables haven't really been created in the database.

Migrating databases

In order for Django to complete the translation and create these database tables, we once again invited my engineering management assistant, management.py. Activate the virtual environment, switch to the directory where the management.py file is located, and run the python management.py makemigrations and python management.py migrate commands, respectively:

C:\WINDOWS\system32>C:\Users\yangxg\Envs\blogproject_env\Scripts\activate

(blogproject_env) C:\WINDOWS\system32>cd C:\Users\yangxg\Workspace\blogproject

(blogproject_env) C:\Users\yangxg\Workspace\blogproject>python manage.py makemigrations
Migrations for 'blog':
  blog\migrations\0001_initial.py:
    - Create model Category
    - Create model Post
    - Create model Tag
    - Add field tags to post
    
(blogproject_env) C:\Users\yangxg\Workspace\blogproject>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, blog, 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 blog.0001_initial... OK
  Applying sessions.0001_initial... OK

Note: If the code contains Chinese comments and you use Python 2 development environment, you will get a coding error. So Please add the encoding declaration at the beginning of the document with Chinese comments: # coding: utf-8.

When we executed Python management.py makemigrations, Django generated a 0001_initial.py file in the migrations directory of the blog application, which Django used to record what changes we made to the model. For now, we have created three model classes in the models.py file, and Django has recorded these changes in 0001_initial. py.

At this point, we just told Django what changes we had made. In order for Django to really create database tables for us, we then executed the python management. py migrate command. Django detects the files in the migrations directory of the application and knows what operations we have done to the database. Then it translates these operations into the database operating language, which acts on the real database.

You can see that besides Applying blog.0001_initial... OK, Django also operates on other files. This is because in addition to our own blog applications, Django itself also has many built-in applications that need to store data. You can see these applications in settings.py's INSTALLED_APP settings, but of course we don't need to care about them at the moment.

blogproject/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]

For those who know the database language, you can run the following command to see what Django has done for us:

python manage.py sqlmigrate blog 0001

You will see the output of Django translated database table creation statements, which helps you understand the working mechanism of Django ORM.

Select the database version

We didn't install any database software, so Django helped us migrate the database. This is because we use Python's built-in SQLLite3 database.

SQLite3 is a very lightweight database with only one file. You can see that there is an extra db.sqlite3 file in the project root directory, which is the SQLite3 database file. The data of Django blog will be stored in this database file.

Django did some default database configuration for us in settings.py:

blogproject/settings.py

## Other configuration options...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
## Other configuration options...

You can see that the default database engine is SQLite3.

Of course, some people tend to use large databases such as MySQL. As for how Django configures MySQL, there is no need to elaborate. You can use the search engine or consult the official documents of Django to solve the problem. For a small blog, the SQLite3 database is adequate.

Operating the database in Django mode

The main operation of a database is to store data in it, extract data from it, modify saved data and delete data that is no longer needed. Like creating database tables, Django provides a whole set of methods for these operations, freeing us from the database language. We don't have to learn how to use the database language to do these operations, just simply call a few Python functions to meet our needs.

Storage of data

First, explore these functions on the command line and feel how to manipulate the database in Django. Run the python management.py shell command in the directory where manage.py is located:

(blogproject_env) C:\Users\yangxg\Workspace\blogproject>python manage.py shell
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

This opens an interactive command line.

First, let's create a classification and a label:

>>> from blog.models import Category, Tag, Post
>>> c = Category(name='category test')
>>> c.save()
>>> t = Tag(name='tag test')
>>> t.save()

We first import three previously written model classes, then instantiate a Category class and a Tag class, assigning values to their attribute name. In order for Django to save these data into the database, call the save method of the instance.

Try creating another article, but before creating an article, we need to create a User to specify the author of the article. Django, the command to create User, has been written for us and is still running through manage.py. Firstly, press Ctrl + c to exit the command interaction bar (press several times in succession if you can't exit once), run the python management.py create superuser command and create the user according to the prompt:

(blogproject_env) C:\Users\yangxg\Workspace\blogproject>python manage.py createsuperuser
Username (leave blank to use 'zmrenwu@163.com'): myuser
Email address: a@aa.com
Password:
Password (again):
Superuser created successfully.

Run Python management.py create superuser to start creating users, and then prompt you to enter user name, mailbox, password and confirmation password, just follow the prompt. Note that there will be no character display in the password input process. Don't mistake your keyboard for a problem, just enter it normally. Finally, Superuser created successfully. This indicates that the user created successfully.

Run Python management.py shell again to enter the Python command interaction bar and start creating articles:

>>> from blog.models import Category, Tag, Post
>>> from django.utils import timezone
>>> from django.contrib.auth.models import User

>>> user = User.objects.get(username='myuser')
>>> c = Category.objects.get(name='category test')

>>> p = Post(title='title test', body='body test', created_time=timezone.now(), modified_time=timezone.now(), category=c, author=user)
>>> p.save()

Since we restarted the shell, we need to re-import Category, Tag, Post, and User. We also imported a Django-provided auxiliary module, timezone, because we need to call its now() method to specify the time for create_time and modified_time, so it's easy to understand that now method returns the current time. Then we use get method to extract User and Category in database according to user name and classification name (the method of data extraction is described below). Then we specify the title, body, created_time, modified_time values for the article and associate them with the Category and User created earlier. Allow empty excerpt, tags, we did not specify values for them.

Note: Here we use the get method to get a record of the classification based on the value of Category's name attribute. Category.objects.get(name='category test') means a classification record that takes the value of name from the database as category test. Make sure that there is only one record in the database with the value category test, otherwise the get method will return a MultipleObjectsReturned exception. If you accidentally have saved many records, please delete the extra records. How to delete data is shown below.

Fetch data

The data has been stored in the database. Now we need to take them out and see:

>>> Category.objects.all()
<QuerySet [<Category: Category object>]>
>>> Tag.objects.all()
<QuerySet [<Tag: Tag object>]>
>>> Post.objects.all()
<QuerySet [<Post: Post object>]>
>>>

objects is our model manager, which provides us with a series of methods to extract data from the database. Here we use all method to indicate that we want to extract all the corresponding data. You can see that all methods return data, which should have been saved before, but the string displayed is a bit strange, and it is impossible to see whether it is the data we saved before. In order to make the displayed data more humane, we add a _str_ method to each of the three models:

blog/models.py

from django.utils.six import python_2_unicode_compatible

# python_2_unicode_compatible Decorator for Python 2 Compatibility
@python_2_unicode_compatible
class Category(models.Model):
    ...

    def __str__(self):
        return self.name
    
@python_2_unicode_compatible
class Tag(models.Model):
    ...

    def __str__(self):
        return self.name
    
@python_2_unicode_compatible
class Post(models.Model):
    ...
    
    def __str__(self):
        return self.title

Once the _str_ method is defined, the content displayed by the interpreter will be the content returned by the _str_ method. Here Category returns the category name, Tag returns the label name, and Post returns its title.

The python_2_unicode_compatible decorator is used for compatibility with Python 2. If you use the Python 3 development environment, removing this decorator will have no impact. If you use a Python 2 development environment and don't want to use this decorator, change the _str_ method to _unicode_ method.

First press Ctrl + c to exit the Shell, and then re-run Python management. py Shell to enter the Shell.

>>> from blog.models import Category, Tag, Post
>>> Category.objects.all()
<QuerySet [<Category: category test>]>

>>> Tag.objects.all()
<QuerySet [<Tag: tag test>]>

>>> Post.objects.all()
<QuerySet [<Post: title test>]>

>>> Post.objects.get(title='title test')
<Post: title test>

You can see that the data we saved before is returned.

In addition, we mentioned how to get data by get method when we created the article. Here, the difference between all method and get method is that all method returns all data, which is a QuerySet like list data structure, while get returns a record data, if there are many records or no records, get method will throw corresponding exception.

Change data

Attempt to modify the data:

>>> c = Category.objects.get(name='category test')
>>> c.name = 'category test new'
>>> c.save()
>>> Category.objects.all()
<QuerySet [<Category: test category new>]>

First, get the value of category test to the classification by get method according to the name of the classification name, modify its name attribute to the new value category test new, then call save method to save the modification to the database, and then you can see that the data returned by the database is the modified value. The same is true for Tag and Post.

Delete data

Delete data:

>>> p = Post.objects.get(title='title test')
>>> p
<Post: title test>
>>> p.delete()
(1, {'blog.Post_tags': 0, 'blog.Post': 1})
>>> Post.objects.all()
<QuerySet []>

First, post is extracted from the database according to the value of title, saved in variable p, and then called its delete method. Finally, Post.objects.all() returns an empty QuerySet (similar to a list), indicating that there is no post in the database and that post has been deleted.

This is Django's operation of adding, deleting, altering and checking databases. In addition to the demo methods mentioned above, Django also provides us with a lot of other methods, some of which will be used in the tutorial, and I will explain their usage when used. But in the future, when you develop your own project, you need to read Django's official documentation To find out what methods are available and how to use them.

summary

The code in this chapter is located in: Step4: make migrations and migrate.

If you encounter problems, please seek help in the following ways.

For more Django tutorials, visit Blog of Dream-chasing Persons.

Posted by onedumbcoder on Fri, 28 Jun 2019 11:26:16 -0700