DjangoORM操作数据库(增删改查)

一、默认数据库配置

python 自带SQLite数据库,Django支持各种主流的数据库,本文使用SQLite进行初始化。

.
├── HelloWorld            
│   ├── settings.py       //该 Django 项目的配置,包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量

如果使用其它数据库可在settings.py文件中进行设置,数据库默认的配置为:

# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

二、初始化数据库

#使用  python manage.py migrate 初始化(也叫迁移)数据库
(py3env) Mac:HelloWorld eword$ python manage.py migrate

执行结果:

Operations to perform:
  Apply all migrations: admin, auth, 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 admin.0003_logentry_add_action_flag_choices... 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 auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

执行完成后,会在项目默认使用的SQLlite数据库中生产如下数据表

.
├── HelloWorld
├── blog
├── db.sqlite3              //默认使用的SQLlite数据库
└── manage.py

image-20201022212813644

三、初始化Django自带Web后台的用户名和密码

3.1、初始化账号和密码

(py3env) MacBook-Pro:HelloWorld ewordeword.name$ python manage.py createsuperuser

执行结果

Username (leave blank to use 'ewordeword.name'): admin
Email address: eword@eword.name
Password: 
Password (again): 
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y    //由于使用了简单密码所以提示了绕过密码验证和创建用户
Superuser created successfully.

3.2、帐号密码登入测试

启动django开发服务器,使用一下地址访问django自带的Web后台

http://127.0.0.1:8000/admin

image-20201022213947707

image-20201022214029398

如果无法打开web,需要确认一下是否在settings.py加入blog应用模块配置

.
├── HelloWorld
│   ├── settings.py     <----

在settings.py中找到INSTALLED_APPS配置项

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',              //确认加入了blog【注意逗号】
]

四、数据库操作

4.1、创建数据表

4.1.1、定义表字段

├── blog
│   ├── models.py                        //用来存放当前APP模块的数据库模型

打开blog应用模块目录下的models.py文件,定义blog应用模块数据结构:

from django.db import models


# Create your models here.

class Article(models.Model):
    title = models.CharField(max_length=50)
    subtitle = models.CharField(max_length=50)
    body = models.CharField(max_length=2000)
    read_count = models.IntegerField()

4.1.2、生产数据库迁移文件

使用makemigrations命令生产数据库迁移文件

(py3env) Mac:HelloWorld eword$ python manage.py makemigrations

执行结果

Migrations for 'blog':
  blog/migrations/0001_initial.py
    - Create model Article

blog/migrations/0001_initial.py文件内容

# Generated by Django 3.1.2 on 2020-10-23 07:04

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Article',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('title', models.CharField(max_length=50)),
                ('subtitle', models.CharField(max_length=50)),
                ('body', models.CharField(max_length=2000)),
                ('read_count', models.IntegerField()),
            ],
        ),
    ]

4.1.3、数据库迁移(同步数据库)

根据结果我们发现makemigrations命令为我们生产了blog/migrations/0001_initial.py文件用来记录变更差异,此时我们可以使用migrate命令将变更的内容更新到数据库:

(py3env) Mac:HelloWorld eword$ python manage.py migrate

执行结果

Operations to perform:
  Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
  Applying blog.0001_initial... OK

此时可以看到SQLite数据库中多出了blog_article表,从图中可以看出,Django默认会以应用模块名为数据表前缀,以类名为数据表名,同时会默认加上一个id字段做为自增主键。

image-20201023151428317

4.2、向数据表插入数据(增)

4.2.1、编写业务逻辑

├── blog
│   └── views.py                        //当前APP模块的业务逻辑

Django是在views.py文件中,通过导入models.py文件来实现数据操作,现在我们在views.py文件中加入向数据表blog_article插入数据的代码:

# Create your views here.
from blog import models  # 导入blog模块
from django.http import HttpResponse


# 向数据表article插入数据
def db_create(request):
    models.Article.objects.create(title='测试标题', subtitle='副标题', body='正文内容', read_count=10)
    return HttpResponse('OK')

也可以使用字典进行数据插入

# 向数据表article插入数据
def db_create(request):
    # models.Article.objects.create(title='测试标题', subtitle='副标题', body='正文内容', read_count=10)
    dic = {"title": "测试标题", "subtitle": "副标题", "body": "正文内容", "read_count": 10}
    models.Article.objects.create(**dic)
    return HttpResponse('OK')

4.2.2、配置路由

├── HelloWorld            
│   ├── urls.py             //该 Django 项目的 URL 路径目录,负责把URL模式映射到应用程序。

在urls.py中配置路由,以便让浏览器能够访问到views.py文件中的db_create函数(方法):

from django.contrib import admin
from django.urls import path
from blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('create', views.db_create),        //加入此行【注意逗号】
]

4.2.3、浏览器访问

启动django开发服务器后,使用浏览器访问以下地址

http://127.0.0.1:8000/create

image-20201023200034259

这是我们可以看到SQLite数据中的blog_article表被插入了一条记录

image-20201023200211985

4.3、修改数据表数据(改)

4.3.1、编写业务逻辑

├── blog
│   └── views.py                        //当前APP模块的业务逻辑

编辑views.py文件,加入修改数据表blog_article中id=1的数据

# 修改数据表article中的数据
def db_update(request):
    # 找到id=1的数据,将read_count改为100
    models.Article.objects.filter(id=1).update(read_count=100)
    return HttpResponse('OK')

4.3.2、配置路由

├── HelloWorld            
│   ├── urls.py             //该 Django 项目的 URL 路径目录,负责把URL模式映射到应用程序。

在urls.py中配置路由,以便让浏览器能够访问到views.py文件中的db_update函数(方法):

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', views.hello),
    path('create', views.db_create),
    path('update', views.db_update),    //加入此行【注意逗号】
]

4.3.3、浏览器访问

启动django开发服务器后,使用浏览器访问以下地址

http://127.0.0.1:8000/update

执行成功后id=1的记录,read_count值被改成了100。

4.4、查询数据表数据(查)

4.4.1、创建显示页

我们利用Django的模板功能,新建一个query.html文件,用来显示查询出来的数据。

在项目目录中新建一个templates文件夹,然后在templat文件夹中新建query.html文件,最终得到的项目目录如下

.
├── HelloWorld
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-37.pyc
│   │   ├── settings.cpython-37.pyc
│   │   ├── urls.cpython-37.pyc
│   │   └── wsgi.cpython-37.pyc
│   ├── asgi.py
│   ├── settings.py   //该 Django 项目的配置,这里用来配置模板路径
│   ├── urls.py
│   └── wsgi.py
├── blog
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-37.pyc
│   │   ├── admin.cpython-37.pyc
│   │   ├── apps.cpython-37.pyc
│   │   ├── models.cpython-37.pyc
│   │   └── views.cpython-37.pyc
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-37.pyc
│   │       └── __init__.cpython-37.pyc
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── db.sqlite3
├── manage.py
└── templates                    //模板文件夹
    └── query.html               //显示查询出来的数据页

query.html显示页内容如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Django操作数据库</title>
</head>
<body>
<table border="1">
    <tr>
        <th>标题</th>
        <th>副标题</th>
        <th>内容</th>
        <th>阅读量</th>
    </tr>
    {% for item in li %}
        <tr>
            <td>{{ item.title }}</td>
            <td>{{ item.subtitle }}</td>
            <td>{{ item.body }}</td>
            <td>{{ item.read_count }}</td>
        </tr>
    {% endfor %}
</table>
</body>
</html>

4.4.2、配置模板路径

├── HelloWorld
│   ├── settings.py   //该 Django 项目的配置,这里用来配置模板路径

为了在views.py文件中能够调用到templates目录下的query.html,需要在settings.py文件中配置模板路径,否着会找不到模板

# 导入 os
import os

…… ……

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  # 配置模板路径
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

4.4.3、编写业务逻辑

├── blog
│   └── views.py                        //当前APP模块的业务逻辑

编辑views.py文件,加入查询数据表blog_article数据的代码

# 查询数据表article中的数据
def db_query(request):
    dataset = models.Article.objects.all()
    return render(request, 'query.html', {'li': dataset})

4.4.4、配置路由

├── HelloWorld            
│   ├── urls.py             //该 Django 项目的 URL 路径目录,负责把URL模式映射到应用程序。

在urls.py中配置路由,以便让浏览器能够访问到views.py文件中的db_query函数(方法):

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', views.hello),
    path('create', views.db_create),
    path('update', views.db_update),
    path('query', views.db_query),      //加入此行【注意逗号】
]

4.4.5、浏览器访问

启动django开发服务器后,使用浏览器访问以下地址

http://127.0.0.1:8000/query

image-20201023204553594

为了显示更直观,这里共插入了4条数据。

4.5、删除数据表数据(删)

4.5.1、编写业务逻辑

├── blog
│   └── views.py                        //当前APP模块的业务逻辑

编辑views.py文件,加入删除数据表blog_article中id=1的数据

# 删除数据表article中的数据
def db_delete(request):
    models.Article.objects.filter(id=1).delete()
    return HttpResponse('OK')

4.5.2、配置路由

在urls.py中配置路由,以便让浏览器能够访问到views.py文件中的db_delete函数(方法):

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', views.hello),
    path('create', views.db_create),
    path('delete', views.db_delete),
    path('delete', views.db_delete),     //加入此行【注意逗号】
]

4.5.3、浏览器访问

启动django开发服务器后,使用浏览器访问以下地址

http://127.0.0.1:8000/delete

执行成功后id=1的记录将被删除。

五、使用MySql数据库

5.1、安装pymysql模块

如果想使用mysql数据库而不是SQLite,那么首先必须得安装pymysql模块,python3.5版本不再支持MySQLdb模块!

(py3env) Mac:HelloWorld eword$ pip install pymysql

执行结果

Looking in indexes: http://……………………/repository/pypi-public/simple/
Collecting pymysql
  Downloading http://……………………/repository/pypi-public/packages/1a/ea/dd9c81e2d85efd03cfbf808736dd055bd9ea1a78aea9968888b1055c3263/PyMySQL-0.10.1-py2.py3-none-any.whl (47 kB)
     |████████████████████████████████| 47 kB 2.5 MB/s 
Installing collected packages: pymysql
Successfully installed pymysql-0.10.1

5.2、配置数据库

├── HelloWorld
│   ├── settings.py   //该 Django 项目的配置,这里用来配置使用mysql数据库

在settings.py文件中配置mysql数据库

# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'NAME': 'djangodb',
        'USER': 'root',
        'PASSWORD': '密码……',
    }
}

在 " _init _.py"文件中配置pymysql模块版本

# 文件在目录中的位置
├── HelloWorld
│   ├── __init__.py
import pymysql

pymysql.version_info = (1, 4, 13, "final", 0)
pymysql.install_as_MySQLdb()  # 使用pymysql代替mysqldb连接数据库
如果不在 __init__.py文件中配置pymysql模块版本
等django使用较高版本时会报如下错误
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.4.0 or newer is required;

5.3、迁移数据库(数据库初始化)

根据《4.1.2、生产数据库迁移文件》中生产的迁移文件“ blog/migrations/0001_initial.py”,我们只要在mysql数据库中建立一个名为“djangodb”(与settings.py中配置的数据库名称相同)的数据库,并执行“”迁移命令,就可以初始化mysql数据库

(py3env) Mac:HelloWorld eword$ 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 admin.0003_logentry_add_action_flag_choices... 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 auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying blog.0001_initial... OK
  Applying sessions.0001_initial... OK

可见mysql初始化成功如下图

image-20201023224207929

六、引入js、css等静态文件

6.1、创建query.css文件

为了使4.4.5点中的表格页面更美观,我们新建一个query.css文件用来定义query.html中表格的样式。

在项目根目录中新建一个static文件夹,并在static文件夹中新建一个query.css文件,最终得到的项目目录如下:

.
├── HelloWorld
│   ├── settings.py      //该 Django 项目的配置,这里用来配置静态资源路径
│   ├── …………
├── blog
│   ├── …………
├── db.sqlite3
├── manage.py
├── static                //静态资源文件夹
│   └── query.css         //样式文件
└── templates
    └── query.html

query.css样式文件内容如下:

table, td, th {
    border-color: #ccc;
    border-style: groove;
}
.tb_article {
    text-align: left;
    width: 100%;
}

6.2、配置静态资源路径

├── HelloWorld
│   ├── settings.py   //该 Django 项目的配置,这里用来配置静态资源路径

为了在query.html文件中能够引用到static目录下的query.css样式文件,需要在settings.py文件中配置static路径:

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

6.3、在query.html中引用query.css样式文件

修改query.html内容:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Django操作数据库</title>
    <!-- 引用query.css样式文件 -->
    <link type="text/css" href="/static/query.css" rel="stylesheet" />
</head>
<body>
<!-- class="tb_article" -->
<table class="tb_article">
    <tr>
        <th>标题</th>
        <th>副标题</th>
        <th>内容</th>
        <th>阅读量</th>
    </tr>
    {% for item in li %}
        <tr>
            <td>{{ item.title }}</td>
            <td>{{ item.subtitle }}</td>
            <td>{{ item.body }}</td>
            <td>{{ item.read_count }}</td>
        </tr>
    {% endfor %}
</table>
</body>
</html>

6.4、浏览器访问

启动django开发服务器后,使用浏览器访问以下地址

http://127.0.0.1:8000/query

image-20201023211654448

请忽略这个很丑的表格,这里只使为了演示query.css生效了,😄!!!

七、Post提交数据

7.1、新建Post.html提交页

我们利用Django的模板功能,新建一个Post.html文件,用来向blog_article表提交数据。

在项目目录下的templates文件夹中新建post.html文件,在static文件夹中新建post.css文件,最终目录大致如下:

.
├── HelloWorld
│   ├── urls.py           //配置路由,引用blog/urls.py,当然也可以直接在这里配置
│   └── …………
├── blog
│   ├── …………
│   ├── urls.py           //配置路由然后被HelloWorld/urls.py引用
│   └── views.py          //编写业务逻辑
├── …………
├── static
│   ├── post.css          //提交页样式文件
│   └── query.css
└── templates
    ├── post.html         //提交页
    └── query.html

post.html文件内容如下,post.css这里略……

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Django提交表单</title>
    <link type="text/css" href="/static/post.css" rel="stylesheet"/>
</head>
<body>
<form action="/blog/article" method="post">
    <div class="row">
        <label class="field">标题</label>
        <input name="title"/>
    </div>
    <div class="row">
        <label class="field">副标题</label>
        <input name="subtitle"/>
    </div>
    <div class="row">
        <label class="field">内容</label>
        <input name="body"/>
    </div>
    <div class="row">
        <label class="field">阅读量</label>
        <input name="read_count"/>
    </div>
    <p><input type="submit" value="提交"/></p>
</form>
</body>
</html>

7.2、编写业务逻辑

├── blog
│   └── views.py                        //当前APP模块的业务逻辑

编辑views.py文件,加入向数据表blog_article提交数据的代码

# 向数据表article提交数据
def db_post_article(request):
    if request.method == "GET":
        return render(request, 'post.html')      <----GET请求时返回 提交页

    if request.method == "POST":
        dic = {"title": request.POST['title'], "subtitle": request.POST['subtitle'], "body": request.POST['body'],
               "read_count": request.POST['read_count']}
        models.Article.objects.create(**dic)
    dataset = models.Article.objects.all()
    return render(request, 'query.html', {'li': dataset})   <----POST提交后,返回查询页

7.3、配置路由

├── blog
│   ├── …………
│   ├── urls.py           //配置路由然后被HelloWorld/urls.py引用

blog/urls.py文件内容

from django.urls import path
from blog import views

urlpatterns = [
    path('hello/', views.hello),
    path('article', views.db_post_article),     <---添加,注意逗号
]

注意HelloWorld/urls.py中的引用

from django.contrib import admin
from django.urls import path, include      <-----注意这里的include
from blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),      <-----这里引用blog/urls.py
    path('hello/', views.hello),
    path('create', views.db_create),
    path('update', views.db_update),
    path('query', views.db_query),
    path('delete', views.db_delete),
]

7.4、安全配置

在Django中要使用post方式提交表单,需要在HelloWorld/settings.py配置文件中将下面一行的内容给注释掉:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',                 <---注释掉这一行
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

7.5、浏览器访问

启动django开发服务器后,使用浏览器访问以下地址

http://127.0.0.1:8000/blog/article

image-20201023235655246

提交后返回页

image-20201023235809875

results matching ""

    No results matching ""