[实验] Django 注册功能的实现 (多对多版)

注意:

文中的 python 系统名、mysite 项目、user 应用 Clazz 类、Course 类和 Student 类只是站主在本次操作中随意取的名称,读者可以根据自己的喜好换成任意别的名称

正文:

步骤一:系统环境要求

1) 服务器的系统需要是 openSUSE 15.2 版本
2) 服务器要关闭防火墙
3) 服务器系统要配置好可用的软件源(最好是软件数量最多的官方版本)
4) 服务器要能够连接外网

步骤二:安装 Django

2.1 安装 Python3

[root@python ~]# zypper -n install python3

2.2 创建并进入 Django 项目的目录

[root@python ~]# mkdir project
[root@python ~]# cd project

2.3 将 Django 项目的目录指定为 Django 环境

[root@python project]# python3 -m venv django_env

2.4 进入 Django 环境

[root@python project]# source django_env/bin/activate
(django_env) [root@python project]# pip install django

(补充:在此次操作发生时,最新的 Django 版本是 3.2)

步骤三:创建 mysite 项目

3.1 创建 mysite 项目

(django_env) [root@python project]# django-admin startproject mysite

3.2 mysite 项目的目录

3.2.1 安装 tree 目录显示软件
(django_env) [root@python project]# zypper -n install tree
3.2.2 显示 mysite 项目的目录
(django_env) [root@python project]# cd mysite
(django_env) [root@python mysite]# tree
.
├── manage.py
└── mysite
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

1 directory, 5 files
3.2.3 Django 项目目录介绍

1) mysite 此 Django 项目的容器
2) manage.py 命令行工具,与 Django 项目进行交互
3) mysite/__init__.py 空文件,通知 Python 此项目是 1 个 Python 包
4) mysite/settings.py 此 Django 项目的配置文件
5) mysite/urls.py 此 Django 项目的 URL 声明和 Django 的网站“目录”
6) mysite/wsgi.py WSGI 兼容 Web 服务器的入口

步骤四:创建 user 应用

4.1 创建 user 应用

(django_env) [root@python mysite]# django-admin startapp user

4.2 user 应用的目录

4.2.1 显示 user 应用的目录
(django_env) [root@python mysite]# tree
.
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── user
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

3 directories, 13 files
4.2.2 Django 应用目录介绍

1) user/app.py 此 Django 应用的容器
2) user/__init__.py 空文件,通知 Python 此项目是 1 个 Python 包
3) muser/admin.py 此 Django 应用自带的后台管理相关的类
4) user/app.py 此 Django 应用指定应用名的文件
5) user/migrations.py 此 Django 应用通过 python 代码生成数据库表时里面会产生一些迁移文件
6) user/models.py 可以在里面创建一些 Python 对象并通过这些对象在数据库里创建对应的表
7) user/test.py 此 Django 应用的测试文档
8) user/views.py 此 Django 应用的视图,接收前端数据,把数据传递给后端,响应相关页面

4.3 在 mysite 应用中导入 user 应用

在 mysite/mysite/settings.py 中添加以下内容:

......
INSTALLED_APPS = [
......
    'user',
]
......

步骤五:实现 user 应用的层级多链接

在 mysite/mysite/urls.py 中添加以下内容:

......
from django.conf.urls import url, include
......
urlpatterns = [
......
    url(r'^register/', include('user.urls')),
]

(补充:这里以设置 /register/ 链接对应 user 应用的链接为例)

步骤六:实现连接 MariaDB 数据库

6.1 安装 MairaDB 数据库和客户端

(django_env) [root@python mysite]# zypper -n install mariadb mariadb-devel mariadb-server mariadb-client

6.2 创建用于 Django 的 MairaDB 的库和用户

6.2.1 进入 MairaDB 数据库
(django_env) [root@python mysite]# mysql -h 127.0.0.1 -p
6.2.2 创建用于 Django 的库
MariaDB [(none)]> create database user;

(补充:这里以创建 user 库为例)

6.2.3 创建用于 Django 的用户
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

(补充:这里以创建 root 用户,密码是 password 为例)

6.2.4 刷新权限
MariaDB [(none)]> flush privileges;

6.3 退出 MariaDB 数据库

MariaDB [(none)]> exit

6.4 重启 MariaDB

(django_env) [root@python mysite]# systemctl restart mariadb

步骤七:搭建用于 Django 的 MariaDB 数据库环境

7.1 安装 Django 连接 MariaDB 的模块

(django_env) [root@python mysite]# pip3 install hexdump
(django_env) [root@python mysite]# pip3 install pymysql

7.2 在 mysite 应用中添加 Django 连接 MariaDB 的模块

在 mysite.mysite.__init__.py 中添加以下内容:

import pymysql
pymysql.install_as_MySQLdb()

7.3 在 user 应用数据库模板中添加 Clazz 类、Course 类、Student 类和插入多对多数据的对象

在 mysite/user/models.py 中添加以下内容:

......
class Clazz(models.Model):
    cno = models.AutoField(primary_key=True)
    cname = models.CharField(max_length=30)

    def __str__(self):
        return u'Clazz:%s'%self.cname

class Course(models.Model):
    course_no = models.AutoField(primary_key=True)
    course_name = models.CharField(max_length=30)

    def __str__(self):
        return u'Course:%s'%self.course_name

class Student(models.Model):
    sno = models.AutoField(primary_key=True)
    sname = models.CharField(max_length=30)
    cls = models.ForeignKey(Clazz,on_delete=models.CASCADE)
    cour = models.ManyToManyField(Course)

    def __str__(self):
        return u'Student:%s'%self.sname

# Get class object according to class name
def getCls(cname):
    try:
        cls = Clazz.objects.get(cname=cname)
    except Clazz.DoesNotExist:
        cls = Clazz.objects.create(cname=cname)
        return cls

def getCourseList(*coursenames):
    courseList = []

    for cn in coursenames:
        try:
            c = Course.objects.get(course_name=cn)
        except Course.DoesNotExist:
            c = Course.objects.create(course_name=cn)
        courseList.append(c)

    return courseList

def registerStu(sname,cname,*coursenames):
    #1. Get class objects
    cls = getCls(cname)
    #2. Gets the list of course objects
    courseList = getCourseList(*coursenames)
    #3. Insert student table data
    try:
        stu = Student.objects.get(sname=sname)
    except Student.DoesNotExist:
        stu = Student.objects.create(sname=sname,cls=cls)
    #4. Insert intermediate table data
    stu.cour.add(*courseList)

    return True


补充:
1) 这里 getCls 对象的作用是获取 cname 变量,如果数据库中没有 cname 变量的值则直接插入这个值
2) 这里 getCourseList 对象的作用是获取 coursenames 变量,如果数据库中没有 coursenames 变量的值则直接插入这个值
3) 这里 registerStu 对象的作用是执行 getCls 对象和 getCourseList 对象,获取 sname 变量,如果数据库中没有 sname 变量的值则直接插入这个值

7.4 在 mysite 应用中设置连接到 MariaDB 数据库

将 mysite/mysite/settings.py 中的以下内容:

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

修改为:

......
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'user',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': 'password',
    }
}
......


补充:这里以
1) 使用的库是 user
2) 使用的服务器是 127.0.0.1
3) 使用的端口是 3306
4) 使用的用户是 root
5) 使用的密码是 password
为例

7.5 生成牵引文件

(django_env) [root@python mysite]# python3 manage.py makemigrations
Migrations for 'user':
  user/migrations/0001_initial.py
    - Create model Clazz
    - Create model Course
    - Create model Student

7.6 将牵引文件导入 MariaDB 数据库

(django_env) [root@python mysite]# python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, user
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
  Applying user.0001_initial... OK

(补充:此时会在数据库里生成三张表 user_clazz 表、user_course 表、user_student 表和 user_student_cour 表,其中 user_student_cour 表是 user_course 表和 user_student 表的中间表)

步骤八:实现多对多注册功能

8.1 在 user 应用中添加 1 个学生注册功能的 HTML 模板

创建 mysite/user/templates/register.html 并添加以下内容:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>register</title>
</head>
<body>
    <form action="/register/" method="post">
        {% csrf_token %}
        <p>
            <label for="sn">Name: </label><input name="sname" id="sn"/>
        </p>
        <p>
            <label for="sc">Classroom: </label>
            <select name="clsname" id="sc">
                <option value="Class 1">Class 1</option>
                <option value="Class 2">Class 2</option>
                <option value="Class 3">Class 3</option>
            </select>
        </p>
        <p>
            <label for="cour">Course Selection: </label>
            <input type="checkbox" name="coursename" value="Python"/>Python &emsp;
            <input type="checkbox" name="coursename" value="Shell"/>Shell &emsp;
            <input type="checkbox" name="coursename" value="HTML"/>HTML &emsp;
            <input type="checkbox" name="coursename" value="Django"/>Django &emsp;
        </p>
        <p>
            <input type="submit" value="Register"/>
        </p>
    </form>
</body>
</html>


补充:这里以
1) 生成 1 个用户名输入栏,赋值给 sname
2) 生成 1 个单选框,赋值给 clsname
3) 生成 1 个多选框,赋值给 cour
4) 生成 1 个注册按钮
为例

8.2 在 user 应用中添加 1 个网页返回值的模块并实现所需功能

在 mysite/user/views.py 中添加以下内容:

......
from django.shortcuts import render
from .models import *
from django.http import HttpResponse, request
......

def index_view(request):
    if request.method == 'GET':
        return render(request,'register.html')
    else:
        # Receive request parameters
        sname = request.POST.get('sname','')
        cname = request.POST.get('clsname','')
        coursenames = request.POST.getlist('coursename',[])

        # Register data to database
        flag = registerStu(sname,cname,*coursenames)
        if flag:
            return HttpResponse('register success!')
        return HttpResponse('register fale!')


补充:这里以
1) 获取来自 HTML 的 sanme、clsname 和 coursename 变量
2) 使用 registerStu 对象处理所有变量,处理成功则返回 success! 否则返回 fale!
为例

8.3 在 user 应用中添加 1 个链接并设置对应的模块

创建 mysite/user/urls.py 并添加以下内容:

from django.conf.urls import url
from user.views import *

urlpatterns=[
    url(r'^$',index_view)
]

(补充:这里以设置空链接链接对应 index_view 模块为例)

步骤九:启动 Django 服务

(django_env) [root@python mysite]# python3 manage.py runserver

步骤十:测试页码功能

1) 打开浏览器输入以下网址:

http://127.0.0.1:8000/register/

2) 可以看到 Name 输入栏、Classroom 单选框、Course Selection 多选框和 Register 注册按钮

[内容] Python 可变参数和参数解包

内容一:可变参数和参数解包区别

1) 可变参数是在形参中,通过 * 来实现
2) 参数解包是在实参中,通过 * 来实现

内容二:可变参数的使用案例

2.1 进入 Python3 环境

# python3
>>> 

2.2 创建 1 个输出可变参数内容的对象

>>> def demo(*args,**kwargs):
...     print(args)
...     print(kwargs)
... 


补充:
1) 这里以创建 demo 对象为例
2) 这里 1 个 * 代表接收的是 1 个元组,2 个 ** 代表接收的是 1 个键值对从而形成 1 个字典

2.3 测试输出可变参数内容的对象

>>> demo()
()
{}

(补充:这里 2 个小括号 “()” 是指元组,2 个大括号是 “{}” 是指字典)

2.4 让输出可变参数内容的对象处理元组

>>> demo(1,2,3)
(1, 2, 3)
{}

(补充:这里以处理元组 1,2,3 为例)

2.5 让输出可变参数内容的对象处理元组和字典

>>> demo(1,2,3,c='2')
(1, 2, 3)
{'c': '2'}

(补充:这里以处理元组 1,2,3 和字典 c=’2′ 为例)

内容三:参数解包的使用案例

3.1 进入 Python3 环境

# python3
>>> 

3.2 创建 1 个进行参数解包的对象

>>> def demo(a,b,c):
...     print(a,b,c)
...

3.3 测试进行参数解包的对象

>>> demo(1,2,3)
1 2 3

3.4 让进行参数解包的对象处理元组

>>> args = (1,2,3)
>>> demo(*args)
1 2 3

3.5 让进行参数解包的对象处理字典

>>> kwargs1 = { 'a':'a1','b':'b2','c':'c3'}
>>> demo(**kwargs1)
a1 b2 c3

[实验] Django 多表的实现 (多对多版)

注意:

文中的 python 系统名、mysite 项目、user 应用 ourCla 类和 Student 类只是站主在本次操作中随意取的名称,读者可以根据自己的喜好换成任意别的名称

正文:

步骤一:系统环境要求

1) 服务器的系统需要是 openSUSE 15.2 版本
2) 服务器要关闭防火墙
3) 服务器系统要配置好可用的软件源(最好是软件数量最多的官方版本)
4) 服务器要能够连接外网

步骤二:安装 Django

2.1 安装 Python3

[root@python ~]# zypper -n install python3

2.2 创建并进入 Django 项目的目录

[root@python ~]# mkdir project
[root@python ~]# cd project

2.3 将 Django 项目的目录指定为 Django 环境

[root@python project]# python3 -m venv django_env

2.4 进入 Django 环境

[root@python project]# source django_env/bin/activate
(django_env) [root@python project]# pip install django

(补充:在此次操作发生时,最新的 Django 版本是 3.2)

步骤三:创建 mysite 项目

3.1 创建 mysite 项目

(django_env) [root@python project]# django-admin startproject mysite

3.2 mysite 项目的目录

3.2.1 安装 tree 目录显示软件
(django_env) [root@python project]# zypper -n install tree
3.2.2 显示 mysite 项目的目录
(django_env) [root@python project]# cd mysite
(django_env) [root@python mysite]# tree
.
├── manage.py
└── mysite
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

1 directory, 5 files
3.2.3 Django 项目目录介绍

1) mysite 此 Django 项目的容器
2) manage.py 命令行工具,与 Django 项目进行交互
3) mysite/__init__.py 空文件,通知 Python 此项目是 1 个 Python 包
4) mysite/settings.py 此 Django 项目的配置文件
5) mysite/urls.py 此 Django 项目的 URL 声明和 Django 的网站“目录”
6) mysite/wsgi.py WSGI 兼容 Web 服务器的入口

步骤四:创建 user 应用

4.1 创建 user 应用

(django_env) [root@python mysite]# django-admin startapp user

4.2 user 应用的目录

4.2.1 显示 user 应用的目录
(django_env) [root@python mysite]# tree
.
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── user
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

3 directories, 13 files
4.2.2 Django 应用目录介绍

1) user/app.py 此 Django 应用的容器
2) user/__init__.py 空文件,通知 Python 此项目是 1 个 Python 包
3) user/admin.py 此 Django 应用自带的后台管理相关的类
4) user/app.py 此 Django 应用指定应用名的文件
5) user/migrations.py 此 Django 应用通过 python 代码生成数据库表时里面会产生一些迁移文件
6) user/models.py 可以在里面创建一些 Python 对象并通过这些对象在数据库里创建对应的表
7) user/test.py 此 Django 应用的测试文档
8) user/views.py 此 Django 应用的视图,接收前端数据,把数据传递给后端,响应相关页面

4.3 在 mysite 应用中导入 user 应用

在 mysite/mysite/settings.py 中添加以下内容:

......
INSTALLED_APPS = [
......
    'user',
]
......

步骤五:实现连接 MariaDB 数据库

5.1 安装 MairaDB 数据库和客户端

(django_env) [root@python mysite]# zypper -n install mariadb mariadb-devel mariadb-server mariadb-client

5.2 创建用于 Django 的 MairaDB 的库和用户

5.2.1 进入 MairaDB 数据库
(django_env) [root@python mysite]# mysql -h 127.0.0.1 -p
5.2.2 创建用于 Django 的库
MariaDB [(none)]> create database user;

(补充:这里以创建 user 库为例)

5.2.3 创建用于 Django 的用户
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

(补充:这里以创建 root 用户,密码是 password 为例)

5.2.4 刷新权限
MariaDB [(none)]> flush privileges;

5.3 退出 MariaDB 数据库

MariaDB [(none)]> exit

5.4 重启 MariaDB

(django_env) [root@python mysite]# systemctl restart mariadb

步骤六:搭建用于 Django 的 MariaDB 数据库环境

6.1 安装 Django 连接 MariaDB 的模块

(django_env) [root@python mysite]# pip3 install hexdump
(django_env) [root@python mysite]# pip3 install pymysql

6.2 在 mysite 应用中添加 Django 连接 MariaDB 的模块

在 mysite/mysite/__init__.py 中添加以下内容:

import pymysql
pymysql.install_as_MySQLdb()

6.3 在 user 应用数据库模板中添加 Course 类和 Teacher

在 mysite/user/models.py 中添加以下内容:

class Course(models.Model):
    course_no=models.AutoField(primary_key=True)
    course_name=models.CharField(max_length=30,)

    def __str__(self):
        return u'Course:%s'%self.course_name

class Teacher(models.Model):
    tno = models.AutoField(primary_key=True)
    tname = models.CharField(max_length=30)
    cour = models.ManyToManyField(Course)

    def __str__(self):
        return u'Teacher:%s'%self.tname


补充:
1) 这里的这条语句会让 Course 类中 course_name 字段以 Course: 的列表形式显示出来:

    def __str__(self):
        return u'Course:%s'%self.course_name

2) 这里的这条语句会让 Teacher 类中 tname 字段以 Teacher: 的列表形式显示出来:

    def __str__(self):
        return u'Teacher:%s'%self.tname

3) 这里的 Course 类和 Teacher 类可以相互多选,是多对多的形式

6.4 在 mysite 应用中设置连接到 MariaDB 数据库

将 mysite/mysite/settings.py 中的以下内容:

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

修改为:

......
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'user',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': 'password',
    }
}
......


补充:这里以
1) 使用的库是 user
2) 使用的服务器是 127.0.0.1
3) 使用的端口是 3306
4) 使用的用户是 root
5) 使用的密码是 password
为例

6.5 生成牵引文件

(django_env) [root@python mysite]# python3 manage.py makemigrations
Migrations for 'user':
  user/migrations/0001_initial.py
    - Create model Course
    - Create model Teacher

6.6 将牵引文件导入 MariaDB 数据库

(django_env) [root@python mysite]# python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, user
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
  Applying user.0001_initial... OK

(补充:此时会在数据库里生成三张表 user_course 表、user_teacher 表和 user_teacher_cour 表,其中 user_teacher_cour 表是 user_course 表和 user_teacher 表的中间表)

6.7 查看导入到 MariaDB 数据库的表

6.7.1 进入 MariaDB 数据库
(django_env) [root@python mysite]# mysql -uroot -p
6.7.2 查看所有的库
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| user               |
+--------------------+
4 rows in set (0.001 sec)
6.7.3 进入 user 库
MariaDB [(none)]> use user;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
6.7.4 查看 user 库里所有的表
MariaDB [user]> show tables;
+----------------------------+
| Tables_in_user             |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| user_course                |
| user_teacher               |
| user_teacher_cour          |
+----------------------------+
13 rows in set (0.001 sec)

(补充:这里的 user_teacher_cour 表是自动创建的,user_course 表和 user_teacher 表的中间表)

6.7.5 查看 user_course 表、user_teacher 表和 user_teacher_cour 表里的数据
MariaDB [user]> select * from user_course;
Empty set (0.001 sec)

MariaDB [user]> select * from user_teacher;
Empty set (0.001 sec)

MariaDB [user]> select * from user_teacher_cour;
Empty set (0.001 sec)
6.7.6 查看 user_course 表、user_teacher 表和 user_teacher_cour 的表结构
MariaDB [user]> desc user_course;
+-------------+-------------+------+-----+---------+----------------+
| Field       | Type        | Null | Key | Default | Extra          |
+-------------+-------------+------+-----+---------+----------------+
| course_no   | int(11)     | NO   | PRI | NULL    | auto_increment |
| course_name | varchar(30) | NO   |     | NULL    |                |
+-------------+-------------+------+-----+---------+----------------+
2 rows in set (0.004 sec)

MariaDB [user]> desc user_teacher;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| tno   | int(11)     | NO   | PRI | NULL    | auto_increment |
| tname | varchar(30) | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.002 sec)

MariaDB [user]> desc user_teacher_cour;
+------------+------------+------+-----+---------+----------------+
| Field      | Type       | Null | Key | Default | Extra          |
+------------+------------+------+-----+---------+----------------+
| id         | bigint(20) | NO   | PRI | NULL    | auto_increment |
| teacher_id | int(11)    | NO   | MUL | NULL    |                |
| course_id  | int(11)    | NO   | MUL | NULL    |                |
+------------+------------+------+-----+---------+----------------+
3 rows in set (0.002 sec)

步骤七:测试 Django 一对多多表

7.1 配置 Django 环境

7.1.1 进入 Python 环境
(django_env) [root@python mysite]# python3
7.1.2 引入 os 模块和 django 模块
>>> import os,django
7.1.3 调用 mysite.settings 的配置
>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
'mysite.settings'
7.1.4 让刚刚的调用生效
>>> django.setup()
7.1.5 调用 mysite 项目 user 应用 models 模块里的所有内容
>>> from user.models import *

7.2 插入多对多多表数据

7.2.1 往 Course 表插入 3 条数据(插入 3 条课程数据)
>>> cour1 = Course.objects.create(course_name='Python')
>>> cour2 = Course.objects.create(course_name='Shell')
>>> cour3 = Course.objects.create(course_name='HTML')

(补充:这里以随意插入三条数据为例)

7.2.2 往 Teacher 表插入 2 条数据(插入 2 条老师数据)
>>> t1 = Teacher.objects.create(tname='zhangsan')
>>> t2 = Teacher.objects.create(tname='lisi')

(补充:这里以随意插入两条数据为例)

7.2.3 让 Teacher 表里的某 1 条数据关联 Course 表中的 3 条数据
>>> t1.cour.add(cour1,cour2,cour3)

(补充:这里以让 t1 数据中的老师选择 cour1、cour2 和 cour3 数据里课程为例)

7.3 查看多对多多表数据

7.3.1 查看多对多多表数据的性质

1) 这里从 Course 表到 Teacher 表的查询正向查询
2) 这里从 Teacher 表到 Course 表的查询逆向查询

7.3.2 正向查询数据
>>> Course.objects.first().teacher_set.all()
<QuerySet [<Teacher: Teacher:zhangsan>]>


补充:
1) 集合后面需要添加 all(),如果不是集合只是对象则不需要添加 all()
2) 这里的 QuerySet 代表多对多
3) 这里的 _set 代表一对多,有一对多的就会有 _set

7.3.3 逆向查询数据
>>> Teacher.objects.first().cour.all()
<QuerySet [<Course: Course:Python>, <Course: Course:Shell>, <Course: Course:HTML>]>


补充:
1) 集合后面需要添加 all(),如果不是集合只是对象则不需要添加 all()
2) 这里的 QuerySet 代表多对多

7.4 使用对象插入 1 对多多表数据

7.4.1 创建 1 个插入数据的对象
>>> def insertData(tname,*coursenames):
...     try:
...         t = Teacher.objects.get(tname=tname)
...     except Teacher.DoesNotExist:
...         t = Teacher.objects.create(tname=tname)
...     courseList = []
...     for cn in coursenames:
...         try:
...             cou = Course.objects.get(course_name=cn)
...         except Course.DoesNotExist:
...             cou = Course.objects.create(course_name=cn)
...         courseList.append(cou)
...     t.cour.add(*courseList)
...


补充:
1) 这里的星号 “*” 代表 1 个可变参数
2) 一个星号 “*” 代表是 1 个元组的形势,各个元素单独存在且用逗号隔开
3) 两个星号 “**” 代表是 1 个键值对,用 = 的方式存在且用逗号隔开

7.4.2 使用对象插入多对多多表数据
>>> insertData('wangwu','SQLite','MySQL')


补充:结合 7.4.1 这里以
1) 在 Teacher 表中插入 wangwu 数据
2) 在 Course 表中插入 SQLite 数据和 MySQL 数据
3) wangwu 对应 SQLite 数据和 MySQL 数据
为例

[步骤] Django 模型字段别名的实现

注意:

在实现 Django 模型类字段别名之前要先创建连接了 MariaDB 数据库或 MySQL 数据库的 Django 项目

正文:

步骤一: 在 users 应用数据库模板中修改 user 类

在 mysite/users/models.py 中将以下内容:

......
# Student table, subordinate table, not unique
class Student(models.Model):
    sno = models.AutoField(primary_key=True)
    sname = models.CharField(max_length=30)
    cno = models.ForeignKey(ourCla,on_delete=models.CASCADE)

    def __str__(self):
        return u'Student:%s'%self.sname

修改为:

......
# Student table, subordinate table, not unique
class Student(models.Model):
    sno = models.AutoField(primary_key=True)
    sname = models.CharField(max_length=30)
    cno = models.ForeignKey(ourCla,on_delete=models.CASCADE,related_name='sts')

    def __str__(self):
        return u'Student:%s'%self.sname

步骤二:测试 Django 模型类字段别名

2.1 配置 Django 环境

2.1.1 进入 Python 环境
(django_env) [root@python mysite]# python3
2.1.2 引入 os 模块和 django 模块
>>> import os,django
2.1.3 调用 mysite.settings 的配置
>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
'mysite.settings'
2.1.4 让刚刚的调用生效
>>> django.setup()
2.1.5 调用 mysite 项目 user 应用 models 模块里的所有内容
>>> from user.models import *

2.2 测试 Django 模型类字段别名

>>> ourCla.objects.first().sts.all()
<QuerySet [<Student: Student:zhangsan>, <Student: Student:lisi>]>

(补充:这里的本来应该有 _set 参数,但是在 mysite.users.models.py 中设置了 related_name=’sts’ 后,就不再需要 _set 参数了,直接使用别名就可以了)

[实验] Django 多表的实现 (一对多版)

注意:

文中的 python 系统名、mysite 项目、user 应用 ourCla 类和 Student 类只是站主在本次操作中随意取的名称,读者可以根据自己的喜好换成任意别的名称

正文:

步骤一:系统环境要求

1) 服务器的系统需要是 openSUSE 15.2 版本
2) 服务器要关闭防火墙
3) 服务器系统要配置好可用的软件源(最好是软件数量最多的官方版本)
4) 服务器要能够连接外网

步骤二:安装 Django

2.1 安装 Python3

[root@python ~]# zypper -n install python3

2.2 创建并进入 Django 项目的目录

[root@python ~]# mkdir project
[root@python ~]# cd project

2.3 将 Django 项目的目录指定为 Django 环境

[root@python project]# python3 -m venv django_env

2.4 进入 Django 环境

[root@python project]# source django_env/bin/activate
(django_env) [root@python project]# pip install django

(补充:在此次操作发生时,最新的 Django 版本是 3.2)

步骤三:创建 mysite 项目

3.1 创建 mysite 项目

(django_env) [root@python project]# django-admin startproject mysite

3.2 mysite 项目的目录

3.2.1 安装 tree 目录显示软件
(django_env) [root@python project]# zypper -n install tree
3.2.2 显示 mysite 项目的目录
(django_env) [root@python project]# cd mysite
(django_env) [root@python mysite]# tree
.
├── manage.py
└── mysite
    ├── __init__.py
    ├── asgi.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

1 directory, 5 files
3.2.3 Django 项目目录介绍

1) mysite 此 Django 项目的容器
2) manage.py 命令行工具,与 Django 项目进行交互
3) mysite/__init__.py 空文件,通知 Python 此项目是 1 个 Python 包
4) mysite/settings.py 此 Django 项目的配置文件
5) mysite/urls.py 此 Django 项目的 URL 声明和 Django 的网站“目录”
6) mysite/wsgi.py WSGI 兼容 Web 服务器的入口

步骤四:创建 user 应用

4.1 创建 user 应用

(django_env) [root@python mysite]# django-admin startapp user

4.2 user 应用的目录

4.2.1 显示 user 应用的目录
(django_env) [root@python mysite]# tree
.
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── user
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

3 directories, 13 files
4.2.2 Django 应用目录介绍

1) user/app.py 此 Django 应用的容器
2) user/__init__.py 空文件,通知 Python 此项目是 1 个 Python 包
3) user/admin.py 此 Django 应用自带的后台管理相关的类
4) user/app.py 此 Django 应用指定应用名的文件
5) user/migrations.py 此 Django 应用通过 python 代码生成数据库表时里面会产生一些迁移文件
6) user/models.py 可以在里面创建一些 Python 对象并通过这些对象在数据库里创建对应的表
7) user/test.py 此 Django 应用的测试文档
8) user/views.py 此 Django 应用的视图,接收前端数据,把数据传递给后端,响应相关页面

4.3 在 mysite 应用中导入 user 应用

在 mysite/mysite/settings.py 中添加以下内容:

......
INSTALLED_APPS = [
......
    'user',
]
......

步骤五:实现连接 MariaDB 数据库

5.1 安装 MairaDB 数据库和客户端

(django_env) [root@python mysite]# zypper -n install mariadb mariadb-devel mariadb-server mariadb-client

5.2 创建用于 Django 的 MairaDB 的库和用户

5.2.1 进入 MairaDB 数据库
(django_env) [root@python mysite]# mysql -h 127.0.0.1 -p
5.2.2 创建用于 Django 的库
MariaDB [(none)]> create database user;

(补充:这里以创建 user 库为例)

5.2.3 创建用于 Django 的用户
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password' WITH GRANT OPTION;

(补充:这里以创建 root 用户,密码是 password 为例)

5.2.4 刷新权限
MariaDB [(none)]> flush privileges;

5.3 退出 MariaDB 数据库

MariaDB [(none)]> exit

5.4 重启 MariaDB

(django_env) [root@python mysite]# systemctl restart mariadb

步骤六:搭建用于 Django 的 MariaDB 数据库环境

6.1 安装 Django 连接 MariaDB 的模块

(django_env) [root@python mysite]# pip3 install hexdump
(django_env) [root@python mysite]# pip3 install pymysql

6.2 在 mysite 应用中添加 Django 连接 MariaDB 的模块

在 mysite/mysite/__init__.py 中添加以下内容:

import pymysql
pymysql.install_as_MySQLdb()

6.3 在 user 应用数据库模板中添加 ourCla 类和 Student 类

在 mysite/user/models.py 中添加以下内容:

......
# Class table, main table, unique
class ourCla(models.Model):
    cno = models.AutoField(primary_key=True)
    cname = models.CharField(max_length=30)

# Student table, subordinate table, not unique
class Student(models.Model):
    sno = models.AutoField(primary_key=True)
    sname = models.CharField(max_length=30)
    cno = models.ForeignKey(ourCla,on_delete=models.CASCADE)

    def __str__(self):
        return u'Student:%s'%self.sname


补充:
1) 这里的这条语句会让 Student 类中 sname 字段以 Student: 的列表形式显示出来:

def __str__(self):
return u’Student:%s’%self.sname

2) 这里的 CASCADE 是指级连,默认就算这里没写也会有,它是引用不用加括号
3) 这里 ourCla 的数据是唯一的,所以 ourCla 是主表
4) 这里外键在 Student 表里,所以 Student 是从表

6.4 在 mysite 应用中设置连接到 MariaDB 数据库

将 mysite/mysite/settings.py 中的以下内容:

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

修改为:

......
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'user',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': 'password',
    }
}
......


补充:这里以
1) 使用的库是 user
2) 使用的服务器是 127.0.0.1
3) 使用的端口是 3306
4) 使用的用户是 root
5) 使用的密码是 password
为例

6.5 生成牵引文件

(django_env) [root@python mysite]# python3 manage.py makemigrations
Migrations for 'user':
  user/migrations/0001_initial.py
    - Create model ourCla
    - Create model Student

6.6 将牵引文件导入 MariaDB 数据库

(django_env) [root@python mysite]# python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, post, 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 post.0001_initial... OK
  Applying sessions.0001_initial... OK

6.7 查看导入到 MariaDB 数据库的表

6.7.1 进入 MariaDB 数据库
(django_env) [root@python mysite]# mysql -uroot -p
6.7.2 查看所有的库
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| user               |
+--------------------+
4 rows in set (0.001 sec)
6.7.3 进入 user 库
MariaDB [(none)]> use user;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
6.7.4 查看 user 库里所有的表
MariaDB [user]> show tables;
+----------------------------+
| Tables_in_user             |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| user_ourcla                |
| user_student               |
+----------------------------+
12 rows in set (0.002 sec)
6.7.5 查看 user_ourcla 表和 user_student 表里的数据
MariaDB [user]> select * from user_ourcla;
Empty set (0.001 sec)

MariaDB [user]> select * from user_student;
Empty set (0.001 sec)
6.7.6 查看 user_ourcla 表和 user_student 表的表结构
MariaDB [user]> desc user_ourcla;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| cno   | int(11)     | NO   | PRI | NULL    | auto_increment |
| cname | varchar(30) | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.006 sec)

MariaDB [user]> desc user_student;
+--------+-------------+------+-----+---------+----------------+
| Field  | Type        | Null | Key | Default | Extra          |
+--------+-------------+------+-----+---------+----------------+
| sno    | int(11)     | NO   | PRI | NULL    | auto_increment |
| sname  | varchar(30) | NO   |     | NULL    |                |
| cno_id | int(11)     | NO   | MUL | NULL    |                |
+--------+-------------+------+-----+---------+----------------+
3 rows in set (0.002 sec)
6.7.7 退出 MariaDB 数据库
MariaDB [(user)]> quit();

步骤七:测试 Django 一对多多表

7.1 配置 Django 环境

7.1.1 进入 Python 环境
(django_env) [root@python mysite]# python3
7.1.2 引入 os 模块和 django 模块
>>> import os,django
7.1.3 调用 mysite.settings 的配置
>>> os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
'mysite.settings'
7.1.4 让刚刚的调用生效
>>> django.setup()
7.1.5 调用 mysite 项目 user 应用 models 模块里的所有内容
>>> from user.models import *

7.2 插入一对多多表数据

7.2.1 往 ourCla 表插入 2 条数据(插入 2 条班级数据)
>>> cla = ourCla.objects.create(cname='classone')
>>> cla1 = ourCla.objects.create(cname='classtwo')

(补充:这里以随意插入两条数据为例)

7.2.2 往 Student 表插入 3 条数据(插入 3 条学生数据)
>>> Student.objects.create(sname='zhangsan',cno=cla)
<Student: Student:zhangsan>
>>> Student.objects.create(sname='lisi',cno=cla)
<Student: Student:lisi>
>>> Student.objects.create(sname='Wangwu',cno=cla1)
<Student: Student:Wangwu>


补充:
1) 这里以随意插入 3 条数据为例
2) zhangsan 和 lisi 的 cno 与 7.2.1 中 cla 的相同
3) Wangwu 的 cno 与 7.2.1 中 cla1 的相同

7.3 查看一对多多表数据

7.3.1 查看一对多多表数据的性质

1) 这里从 ourCla 表到 Student 表的查询正向查询
2) 这里从 Student 表到 ourCla 表的查询逆向查询
3) 这里 ourCla 是主表,数据是唯一的
4) 这里 Student 是从表,有外键

7.3.2 正向查询数据
>>> ourCla.objects.first().student_set.all()
<QuerySet [<Student: Student:zhangsan>, <Student: Student:lisi>]>

(补充:这里的 _set 代表一对多,有一对多的就会有 _set)

7.3.3 逆向查询数据
>>> Student.objects.first().cno
<ourCla: ourCla object (1)>

7.4 使用对象插入一对多多表数据

7.4.1 创建 1 个插入数据的对象
>>> def insertData(claname,*snames):
...      try:
...          cla = ourCla.objects.get(cname=claname)
...      except ourCla.DoesNotExist:
...          cla = ourCla.objects.create(cname=claname)
...      for sn in snames:
...          try:
...               stu = Student.objects.get(sname=sn)
...          except Student.DoesNotExist:
...              Student.objects.create(sname=sn,cno=cla)
...


补充:
1) 这里的星号 “*” 代表 1个可变参数
2) 一个星号 “*” 代表是 1个元组的形势,各个元素单独存在且用逗号隔开
3) 两个星号 “**” 代表是 1 个键值对,用 <key>=<value> 的方式存在且用逗号隔开

7.4.2 使用对象插入一对多多表数据
>>> insertData('classthree','studentone','studenttwo')


补充:结合 7.4.1 这里以
1) 在 Student 表中插入 studentone 数据和 studenttwo 数据
2) 在 ourCla 表中插入 classthree 数据
3) studentone 数据和 studenttwo 数据都对应 classthree 数据
为例