This is the 20th day of my participation in the Genwen Challenge


The introduction

In the Django model design, we only designed a BookInfo model class, which is boring. Let’s start with the BMSTes library management system.


Model design

We should develop good habits when we write projects and things. We should not write handwritten codes as soon as we come. We should first conduct preliminary analysis and design, so that our brain can have an overall concept of what technologies are needed to achieve what effects. This habit can not learn too dead, we have to live to learn to use, learn to adapt. Sometimes it’s just a simple study, or a simple implementation of a small feature. The brain can already roughly grasp, without design and analysis.


Preliminary analysis and design

Our library management system is mainly to achieve the association of books and books hero, the association management of books and books type, so it is divided into book information model, hero information model, book type model, three models. The corresponding relationship is designed as follows

A book type, corresponding to many books, such as: novel type of books, there are the legend of the Heroes of the Condor, the condor heroes, heaven lean on the dragon novel books, etc.

A book, corresponding to a number of heroes, such as: the book of the Heroes of the Condor, corresponding to Guo Jing, Huang Rong, Hong Qigong and so on, condor chivalry is corresponding to Yang Guo, xiaolongnu, etc..

  • The relationship between the book type model and the book information model is 1 to many
  • The relationship between book information model and hero information model is 1 to many
Entity Model 1 Entity Model 2 Corresponding relations between
BookType Book Information (BookInfo) 1 : N
Book Information (BookInfo) HeroInfo 1 : N


Concrete implementation design

BookType BookType model class

Class attribute The data type note
id IntegerField (integer) Primary key, increment
type_name CharField (character) Book type


BookInfo Book model class

Class attribute The data type note
id IntegerField (integer) Primary key, increment
book_type IntegerField (integer)ForeignKey Book type, foreign key
title CharField (character) The name of the book
author CharField (character) The book the author
pub_date CharField (character) Book publication Date
isbn CharField (character) The books ISBN
book_desc CharField (character) Book description
book_detail TextField (text type) The book details
book_price DecimalField (Numeric type) The book price
book_like_num IntegerField (integer) Book liking number
book_collect_num IntegerField (integer) Book collection


HeroInfo Book hero model class

Class attribute The data type note
id IntegerField (integer) The primary key from the increase
name CharField (character) Name of a hero
gender CharField (character) The hero of gender
skill CharField (character) Heroic Skills (Martial Arts)
book InterField (integer)Foreignkey Hero book, foreign key


Django model code

# -*- coding:utf-8 -*-
"" @author :Hui @desc :{model design module} ""
from django.db import models


class BookType(models.Model) :
    """ Book Category Category ""

    type_name = models.CharField(verbose_name=U 'Book type', max_length=20)

    def __str__(self) :
        return self.type_name

    class Meta:
        
        db_table = 'BookType'       # table name

        verbose_name = 'Book Type'   # table note

        The table name is plural. If not set, the end of the table will be an extra s
        verbose_name_plural = verbose_name
        
        ordering = ['id']          # sort field


class BookInfo(models.Model) :
    """ Book Model class """

    title = models.CharField(verbose_name=U 'Book Name', max_length=20)

    author = models.CharField(verbose_name=U 'Book author', max_length=20)

    pub_date = models.DateField(verbose_name=U 'Date of publication')

    book_type = models.ForeignKey(BookType, on_delete=models.CASCADE, verbose_name=U 'Book type')

    isbn = models.CharField(verbose_name='ISBN', max_length=20)

    book_desc = models.CharField(verbose_name=U 'Book Description', max_length=128)

    book_detail = models.TextField(verbose_name=U 'Book Details')

    book_price = models.DecimalField(verbose_name=U 'Book price', max_digits=5, decimal_places=2)

    book_like_num = models.IntegerField(verbose_name=U 'Book likes')

    book_collect_num = models.IntegerField(verbose_name=U 'Book collection')

    def __str__(self) :
        return self.title

    class Meta:
        db_table = 'BookInfo'
        verbose_name = U 'Book Information'
        verbose_name_plural = verbose_name
        ordering = ['id']


class HeroInfo(models.Model) :
    """ Hero model class """
    name = models.CharField(verbose_name=U 'Hero name', max_length=20)

    # Hero gender
    gender = models.CharField(verbose_name=U 'Hero sex', max_length=3)

    # Heroic Skills (Kung Fu)
    skill = models.CharField(verbose_name=U 'Heroic Martial Arts', max_length=128)

    # Hero owning book
    book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name=U 'books')

    def __str__(self) :
        return self.name

    class Meta:
        db_table = 'HeroInfo'
        verbose_name = U 'Character information'
        verbose_name_plural = verbose_name
        ordering = ['id']

Copy the code

There are several field types that have not been used before when designing the model, which are briefly described here.

  • TextField: large TextField, usually used when more than 4000 characters are in length.
  • IntegerField: integer.
  • DecimalField (max_digits = None, decimal_places = None) :Decimal floating point number.
    • The max_digits parameter indicates the total number of digits.
    • The parameter Decimal_places represents the number of decimal places.


Attributes in the Meta class

  • Db_table:Sets the name of the database table to be created. The default isApplication name _ Model class name
  • Verbose_name: Sets the details of the database table (table remarks)
  • Verbose_name_plural: Sets the plural display form of the table
  • Ordering: Set the order field of the table

Fields, and Meta class attributes, more on that later.


Custom background management

Once the model is designed, it’s time to register the model under admin.py. To register the model, I added the inlines, list_per_page, and search_fields attributes

  • Inlines: Objects used to embed edit associations with properties set in one of the one-to-many model (table) relationships.

  • Admin. TabularInline: The edit style of the object associated with the embedded edit is a tabular class

  • Admin.stackedinline: The editing style of the object associated with the embedded edit is stacked class

  • Model: Associated child object

  • Extra: Number of embedded edit child objects


  • List_per_page: specifies the number of data pages on each page
  • Search_fields: indicates the query field


# -*- coding:utf-8 -*-
"" @author :Hui @desc :{background admin module} ""
from django.contrib import admin
from book.models import BookType, BookInfo, HeroInfo


class BookTypeInline(admin.StackedInline) :
    model = BookInfo    # Associated child object
    extra = 1           # Number of embedded edit child objects


class BookInfoInline(admin.TabularInline) :
    model = HeroInfo
    extra = 2


class BookTypeAdmin(admin.ModelAdmin) :
    "" book Type model Management ""

    # Data pagination, 10 pages per page
    list_per_page = 10

    # Properties (fields) displayed in the background
    list_display = ['id'.'type_name']

    Select * from * where *
    search_fields = ['type_name']

    # Insert edit associated object (tabular)
    inlines = [BookTypeInline]


class BookInfoAdmin(admin.ModelAdmin) :
    "" book Information Model Management ""

    list_per_page = 20

    list_display = [
        'id'.'title'.'author'.'pub_date'.'book_desc'.'book_like_num'.'book_collect_num'.'book_type'
    ]

    search_fields = ['id'.'title'.'author'.'book_desc']

    # Set author and type to filter field
    list_filter = ['author'.'book_type']

    # Embed edit-associated objects (stacked)
    inlines = [BookInfoInline]


class HeroInfoAdmin(admin.ModelAdmin) :
    """ Hero Information Model Management class
    list_display = ['id'.'name'.'skill'.'book']

    Set the book query field
    search_fields = ['name'.'skill'.'book']

    # set hero book filter field
    list_filter = ['book']


Register model classes
admin.site.register(BookType, BookTypeAdmin)
admin.site.register(BookInfo, BookInfoAdmin)
admin.site.register(HeroInfo, HeroInfoAdmin)

Copy the code


Configuring the MySQL Database

After registering the model classes, we need to configure the database. Previously, we used Django’s sqlite3 database, but now we use MySQL database.

Start by entering the command in PyCharm’s Terminal to install the Pymysql driver

pip install pymysql
Copy the code

Then locate the DATABASES configuration item in the project settings.py file and change its information to:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql'.MySQL > alter database
        # 'NAME': BASE_DIR/'db.sqlite3', # sqlite3 database
        'NAME': 'BMSTest'.# database name
        'HOST': '127.0.0.1'.# database address, local IP address 127.0.0.1
        'PORT': 3306.# database port
        'USER': 'root'.Database user name
        'PASSWORD': '123456'.# database password}}Copy the code

Finally, import the module and configure it in __init__.py in the same directory as settings.py

import pymysql

pymysql.version_info = (1.4.13."final".0)
pymysql.install_as_MySQLdb()
Copy the code

Pymysql. Version_info = (1, 4, 13, “final”, 0

To solve the django. Core. Exceptions. ImproperlyConfigured: mysqlclient 1.4.0 or newer is required; You have 0.10.1. You have searched the web for a solution to either upgrade or downgrade, but both of them were so troublesome that you looked around for a solution with just a few lines of code. Finally, you found a solution on StackFlow: __init__.py under settings.py Just insert this line of code.


Running server

  • Create database migration filespython manage.py makemigrations
  • Perform database migration filespython manage.py migrate
  • Running serverpython manage.py runserver

Run Python manage.py makemigbar And hoisting the following situation occurs

(py_django) D:\Hui\Code\Python\DjangoProject\BMSTest>python manage.py makemigrations
You are trying to add a non-nullable field 'book_type' to bookinfo without a default; we can't do that (the database needs something to populate ex isting rows). Please select a fix: 1) Provide a one-off default now (will be set on all existing rows with a null value for this column) 2) Quit, and let me add a default in models.py Select an option:Copy the code


BookInfo has only title, author, and pub_date, but now it has book_type, isBN, book_desc, and book_detail. These properties do not have a default value, but a null value.


Solution:

  • 1) If 1 is selected, provide the default value.

  • 2) Select 2 to set the default value or allow the property (field) to be null, for example:

    book_desc = models.CharField(verbose_name=U 'Book Description', max_length=128, null=True)
    
    book_detail = models.TextField(verbose_name=U 'Book Details', null=True)
    
    book_price = models.DecimalField(verbose_name=U 'Book price', max_digits=5, decimal_places=2, null=True)
    
    book_like_num = models.IntegerField(verbose_name=U 'Book likes', default=0)
    
    book_collect_num = models.IntegerField(verbose_name=U 'Book collection', default=0)
    Copy the code

    The new attributes are the default valuesdefault, or nullnull.

  • If you want to switch to another database, you can delete the migration file created before in the migrations directory under the application and then create the migration file.


Database structure


Note: If you switch databases, the data will not be migrated, so manually add or import it yourself.


Page rendering of book type


Filtering effect of book information


Embed edit-associated objects (stacked)

When editing the book type, the number of associated objects (book information) is embedded below according to the value of the extra attribute


Embed edit-associated objects (tabular)


Advice:

  • If the associated model (table) has many attributes, it is recommended to use the stack type (admin.stackedinline) and do not place too many attributes. One or none is recommended.
  • If the associated model (table) attributes are small, the tabular format (admin.tabularinline) is recommended for more places, and the arbitrary format is fine for less places.

So you don’t end up with pages that slide too long from top to bottom, or slide too long from left to right, that are not easy to edit, that are not beautiful.


The public,

Create a new folder X

Nature took tens of billions of years to create our real world, while programmers took hundreds of years to create a completely different virtual world. We knock out brick by brick with a keyboard and build everything with our brains. People see 1000 as authority. We defend 1024. We are not keyboard warriors, we are just extraordinary builders of ordinary world.