Welcome to reprint, but please quote the original source at the beginning or end.

preface

Django and Flask are two of my favorite Python Web frameworks, but they are positioned very differently

  • Django -> “More is less”: Is “large and complete” heavyweight Web framework, its own a large number of common tools and components (such as database ORM components, user authentication, authority management, paging, cache), and even its own management background Admin, suitable for rapid development of functional enterprise website

  • Flask -> “Less is more”: a lightweight, extensible “micro” framework. By default, Django doesn’t have any of the tools and components that come with It, just a very simple and efficient “routing component” for Flask.

In ordinary days, do small tools small application what, the author still likes Flask, with the help of such small micro frame, can be lifted out in dozens of minutes.

But when it comes to writing larger applications, I usually go with Django. The main reason is that its ORM module is so good.

In Flask, SQLAlchemy is still the most used ORM framework, but I don’t think it’s as friendly as DjangoORM.

So the author came up with an idea: Flask + DjangoORM

starts

Manually creating a project

$ mkdir FlaskWithDjangoORM
Copy the code

withpipInstall the required dependency libraries

$ pip install flask django mysqlclient
Copy the code

Manually createappapplication

In a standard Django project, you use the $python manage.py startapp command to create a subapplication named app. The subapplication will typically have several files/directories in its directory:

  • migrations/This directory holds database migration files
  • admin.pyThis file is related to the management background
  • apps.pyThis file is related to the child application Settings
  • models.pyThis file holds the database model
  • tests.pyThis file holds the unit tests
  • views.pyThis file holds the view-layer code

But if we were using Only Django’s ORM module, we would leave just migrations/ and models.py. So discard the command and create it manually:

$ cd FlaskWithDjangoORM
$ mkdir -p app/migrations
$ touch app/migrations/__init__.py
Copy the code

The app subapplication was initialized. Procedure

$ cat >> app/__init__.py <<EOF
import os

from django.apps import apps
from django.conf import settings

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
apps.populate(settings.INSTALLED_APPS)
EOF
Copy the code

Create a data model Visit to record the time of each Web request

$ cat >> app/models.py <<EOF
from django.db import models

class Visit(models.Model):
    created_at = models.DateTimeField(auto_now_add=True, null=True)
EOF
Copy the code

insettings.pyInternal configuration of database connections (this article’s example usesMySQL)

$ cat >> settings.py <<EOF
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'flask-with-django-orm-sample',
        'USER': 'USERNAME',
        'PASSWORD': 'PASSWORD',
        'HOST': 'DATA_BASE_HOST',
        'PORT': '3306',
        'OPTIONS': {
            'charset': 'utf8mb4',
            # https://django-mysql.readthedocs.io/en/latest/checks.html#django-mysql-w002-innodb-strict-mode
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES', innodb_strict_mode=1",
        },
    }
}

INSTALLED_APPS = ('app',)

SECRET_KEY = 'SOME_SECRET_KEY'

EOF
Copy the code

configurationmanage.pyManagement tool

This is carried over from a standard Django project (slightly changing the setdefault parameter)

$ cat >> manage.py <<EOF #! /usr/bin/env python """Django's command-line utility for administrative tasks.""" import os import sys def main(): os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings') try: from django.core.management import execute_from_command_line except ImportError as exc: raise ImportError( "Couldn't import Django. Are you sure it's installed and " "available on your PYTHONPATH environment variable? Did you " "forget to activate a virtual environment?" ) from exc execute_from_command_line(sys.argv) if __name__ == '__main__': main() EOFCopy the code

At this point, let’s look at the directory structure:

. ├ ─ ─ app │ ├ ─ ─ just set py │ ├ ─ ─ migrations │ │ └ ─ ─ just set py │ └ ─ ─ models. Py ├ ─ ─ the manage. Py └ ─ ─ Settings. PyCopy the code

These files alone are more than enough to run Django ORM

Synchronize the local data model to the database

Create migration files

$ python manage.py makemigrations
Migrations for 'app':
  app/migrations/0001_initial.py
    - Create model Visit
Copy the code

Perform the migration

$ python manage.py migrate
Operations to perform:
  Apply all migrations: app
Running migrations:
  Applying app.0001_initial... OK
Copy the code

Take a look at the database

mysql> show databases; +------------------------------+ | Database | +------------------------------+ | flask-with-django-orm-sample | | Information_schema | | mysql | + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + 3 rows in the set (1.23 SEC)Copy the code

Select the database and list all the database tables

mysql> use flask-with-django-orm-sample; Database changed mysql> show tables; +----------------------------------------+ | Tables_in_flask-with-django-orm-sample | +----------------------------------------+ | app_visit | | django_migrations | + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + 2 rows in the set (0.04 SEC)Copy the code

We can see that there is a migration table, django_migrations, which records all the records of the migration of data model changes.

If we query the table, we can see 0001_INITIAL exists, which corresponds to the migration file app/migrations/ 0001_Initial.py generated by running Names, Hoisting

mysql> select * from django_migrations; +----+-----+--------------+----------------------------+ | id | app | name | applied | +, + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + | 1 | | 0001 app _initial 08:01:16. | 2020-12-20 | 618904 +, + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + 1 row in the set (0.22 SEC)Copy the code

Take a look at the structure of the app_visit table, which corresponds to the Visit we defined in app/models.py.

mysql> desc app_visit; +------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment |  | created_at | datetime(6) | YES | | NULL | | +------------+-------------+------+-----+---------+----------------+ 2 Rows in set (0.25 SEC)Copy the code

createserver.pyAs aflaskThe master file

$ cat >> server.py <<EOF
from flask import Flask

from app.models import Visit

app = Flask(__name__)


@app.route("/")
def index():
    Visit.objects.create()
    return str(Visit.objects.count())


if __name__ == '__main__':
    app.run()
EOF
Copy the code

Run server.py

$ python server.py
* Serving Flask app "server" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Copy the code

The test results

Multiple accesses on the new terminallocalhost:5000/, you can see the return from1Begin to increase in order

Check the program log

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) 127.0.0.1 - - [20/Dec/2020 09:52:56] "GET/HTTP/1.1" 200 - 127.0.0.1 - - [20/Dec/2020 09:52:58] "GET/HTTP/1.1" 200 - - [20/Dec/2020 09:53:00] "GET/HTTP/1.1" 200 - 127.0.0.1 - - [20/Dec/2020 09:53:03] "GET/HTTP/1.1" 200 - - [20/Dec/2020 09:53:03] "GET/HTTP/1.1" 200 - 127.0.0.1 - - [20/Dec/2020 09:53:04] "GET/HTTP/1.1" 200 - - [20/Dec/2020 09:53:05] "GET/HTTP/1.1" 200 - 127.0.0.1 - - [20/Dec/2020 09:53:07] "GET/HTTP/1.1" 200 - - [20/Dec/2020 09:53:07] "GET/HTTP/1.1" 200 - 127.0.0.1 - - [20/Dec/2020 09:53:08] "GET/HTTP/1.1" 200 - - [20/Dec/2020 09:53:12] "GET/HTTP/1.1" 200 - 127.0.0.1 - - [20/Dec/2020 09:53:14] "GET/HTTP/1.1" 200 - [20/Dec/2020 09:53:14] "GET/HTTP/1.1" 200 - 127.0.0.1 - - [20/Dec/2020 09:53:17] "GET/HTTP/1.1" 200 - [20/Dec/2020 09:53:17] "GET/HTTP/1.1" 200 - 127.0.0.1 - - [20/Dec/2020 09:53:18] "GET/HTTP/1.1" 200 - - [20/Dec/2020 09:53:19] "GET/HTTP/1.1" 200 - [20/Dec/2020 09:53:26] "GET/HTTP/1.1" 200 -Copy the code

Check the database again

mysql> select * from app_visit; +----+----------------------------+ | id | created_at | +----+----------------------------+ | 1 | 2020-12-20 09:52:56. 660151 | | 2 | 2020-12-20 09:52:58. 761042 | | 3 | 2020-12-20 09:53:00. 393140 | | | 4 09:53:01. 2020-12-20 811832 | | | 5 2020-12-20 09:53:03. 216767 | | | 6 09:53:04. 2020-12-20 471404 | | 7 | 2020-12-20 09:53:05. 639631 | | | 8 The 2020-12-20 09:53:06. 790564 | | | 9 09:53:07. 2020-12-20 823484 | | | 10 2020-12-20 09:53:08. | 836709 | | 2020-12-20 11 09:53:12. 069902 | | | 12 09:53:13. 2020-12-20 | 293624 | | 2020-12-20 13 09:53:14. 799734 | | | 14 2020-12-20 15 09:53:15. 993364 | | | 09:53:17. 2020-12-20 | 022426 | | 2020-12-20 16 09:53:18. 141073 | | | 17 2020-12-20 18 09:53:19. 499833 | | | 09:53:26. 2020-12-20 608735 | + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + 18 rows in the set (0.02 SEC)Copy the code

The access records in the log are exactly the same as the access records stored in the database, and you’re done! Knock it off and go to bed!