Django实践-03模型-01表生成模型+学科页面与教师页面编写

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: Django实践-03模型-01表生成模型+学科页面与教师页面编写

image.png


Django实践-03模型


官网:https://www.djangoproject.com/

博客:https://www.liujiangblog.com/

git:https://gitcode.net/mirrors/jackfrued/Python-100-Days


Django静态文件问题备注:

参考:

Django测试开发-20-settings.py中templates配置,使得APP下的模板以及根目录下的模板均可生效

解决django 多个APP时 static文件的问题


Django MTV之模型


MVC架构中的“模型”和“视图”的解耦合。所谓“模型”就是数据(的表示),数据模型通常通过数据库实现持久化操作,而关系型数据库在过去和当下都是持久化的首选方案。


投票案例

下面我们通过完成一个投票项目来讲解和模型相关的知识点。


投票项目的首页会展示某在线教育平台所有的学科;

点击学科可以查看到该学科的老师及其信息;

用户登录后在查看老师的页面为老师投票,可以投赞成票和反对票;

未登录的用户可以通过登录页进行登录;

尚未注册的用户可以通过注册页输入个人信息进行注册。


在这个项目中,我们使用MySQL数据库来实现数据持久化操作。


1.创建应用

1.创建应用

注意执行的位置,要在djangoproject的目录下执行

django-admin startapp polls

2.配置模板文件

在templates目录下


登录页面login.html

注册页面register.html,


创建templates/polls目录。在polls目录下创建


展示学科的页面subjects.html

显示学科老师的页面teachers.html


具体内容下文进行描述。


2.配置关系型数据库MySQL

1.创建数据库

在MySQL中创建数据库,创建用户,授权用户访问该数据库。

create database vote default charset utf8;
create user 'django'@'%' identified by 'django123';
grant all privileges on vote.* to 'django'@'%';
flush privileges;

2.创建表

在MySQL中创建保存学科和老师信息的二维表(保存用户信息的表稍后处理)。

use vote;
-- 创建学科表
create table `tb_subject`
(
  `no` integer auto_increment comment '学科编号',
    `name` varchar(50) not null comment '学科名称',
    `intro` varchar(1000) not null default '' comment '学科介绍',
    `is_hot` boolean not null default 0 comment '是不是热门学科',
    primary key (`no`)
);
-- 创建老师表
create table `tb_teacher`
(
    `no` integer auto_increment comment '老师编号',
    `name` varchar(20) not null comment '老师姓名',
    `sex` boolean not null default 1 comment '老师性别',
    `birth` date not null comment '出生日期',
    `intro` varchar(1000) not null default '' comment '老师介绍',
    `photo` varchar(255) not null default '' comment '老师照片',
    `gcount` integer not null default 0 comment '好评数',
    `bcount` integer not null default 0 comment '差评数',
    `sno` integer not null comment '所属学科',
    primary key (`no`),
    foreign key (`sno`) references `tb_subject` (`no`)
);

3.按照MySQL依赖

在虚拟环境中安装连接MySQL数据库所需的依赖项。

pip install mysqlclient -i https://pypi.tuna.tsinghua.edu.cn/simple

4.修改settings.py文件 添加应用 配置数据库

修改项目的settings.py文件,首先将我们创建的应用polls添加已安装的项目(INSTALLED_APPS)中,然后配置MySQL作为持久化方案。

INSTALLED_APPS = [
    # 新增polls
    'polls',
]
DATABASES = {
    'default': {
        # 数据库引擎配置
        'ENGINE': 'django.db.backends.mysql',
        # 数据库的名字
        'NAME': 'vote',
        # 数据库服务器的IP地址(本机可以写localhost或127.0.0.1)
        'HOST': 'localhost',
        # 启动MySQL服务的端口号
        'PORT': 3306,
        # 数据库用户名和口令
        'USER': 'django',
        'PASSWORD': 'django123',
        # 数据库使用的字符集
        'CHARSET': 'utf8',
        # 数据库时间日期的时区设定
        'TIME_ZONE': 'Asia/Shanghai',
    }
}

在配置ENGINE属性时,常用的可选值包括:sqlite3,postgresql,oracle,mysql


5. 基于数据库生成实体类

Django框架提供了ORM来解决数据持久化问题,ORM翻译成中文叫“对象关系映射”。利用Django的ORM,我们可以直接将刚才创建的学科表和老师表变成Django中的模型类。

python manage.py inspectdb > polls/models.py

在polls/models.py中生成如下代码,我们可以修改实体类,


from django.db import models
# Create your models here.
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
#   * Rearrange models' order
#   * Make sure each model has one field with primary_key=True
#   * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
#   * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
# 添加了注释部分verbose_name="名称"
class Subject(models.Model): # TbSubject 修改为 Subject
    no = models.AutoField(primary_key=True,verbose_name="编号")
    name = models.CharField(max_length=50,verbose_name="名称")
    intro = models.CharField(max_length=1000,verbose_name="介绍")
    is_hot = models.IntegerField(verbose_name="是否热门")
    class Meta:
        managed = False 
        db_table = 'tb_subject'
class Teacher(models.Model): # TbTeacher修改为Teacher
    no = models.AutoField(primary_key=True,verbose_name="编号")
    name = models.CharField(max_length=20,verbose_name="教师姓名")
    sex = models.IntegerField(verbose_name="性别")
    birth = models.DateField(verbose_name="出生年月")
    intro = models.CharField(max_length=1000,verbose_name="个人介绍")
    photo = models.CharField(max_length=255,verbose_name="照片")
    good_count = models.IntegerField(db_column="gcount",verbose_name="好评数") # gcount 修改为good_count
    bad_count= models.IntegerField(db_column="bcount",verbose_name="差评数") # bcount 修改为bad_count 添加db_column
    subject = models.ForeignKey(Subject, models.DO_NOTHING, db_column='sno') # sno 修改为 subject, TbSubject修改为Subject
    class Meta:
        managed = False
        db_table = 'tb_teacher'

3.使用ORM完成模型的CRUD操作

在终端中输入下面的命令进入到Django项目的交互式环境,然后尝试对模型的操作。


python manage.py shell

1.新增

from polls.models import Subject,Teacher
subject1 = Subject(name='Python全栈开发', intro='当下最热门的学科', is_hot=True)
subject1.save()
subject2 = Subject(name='全栈软件测试', intro='学习自动化测试的学科', is_hot=False)
subject2.save()
subject3 = Subject(name='JavaEE分布式开发', intro='基于Java语言的服务器应用开发', is_hot=True)
subject3.save()

ed5ba44272011d29249982921479d8ab_1767be9309ab41de8fe20056d08d326c.png

subject = Subject.objects.get(no=1)
t1 = Teacher(name='甲1', sex="1",birth="2000-05-02",photo="照片路径",good_count="11",bad_count="0",intro='数学老师', subject=subject )
t1.save()

2b7ecca8dd53d06c5c57efc309c0d3cf_88b41d6554b84c298475d4d324e9cf76.png


subject = Subject.objects.get(no=3)
t2 = Teacher(name='丙3', sex="2",birth="2000-05-02",photo="照片路径",good_count="11",bad_count="0",intro='语文老师', subject=subject )
t2.save()

3a1ffc849d49bd8cd2c16a059c213c15_52a0a83dffdf4a9b8698203a2e4aa872.png


subject = Subject.objects.get(no=1)
t3 = Teacher(name='丁4', sex="1",birth="2000-05-02",photo="照片路径",good_count="11",bad_count="0",intro='计算机老师', subject=subject )
t3.save()

41b6643d7595c9e3fc778ebd2887e9bc_c817bcfeea8146648513cccf3827f88c.png


2.删除

subject = Subject.objects.get(no=2)
subject.delete()
# (1, {'polls.Subject': 1})

3.更新

subject = Subject.objects.get(no=1)
subject.name = 'Python全栈+人工智能'
subject.save()

c990cb5f5effaf1f8177891b2b7fd43c_b26764fb98504a9a841fe5dab229f8e6.png


4.查询

  1. 查询所有对象。
Subject.objects.all()
# <QuerySet [<Subject: Subject object (1)>, <Subject: Subject object (3)>]>
  1. 过滤数据。
# 查询名称为“Python全栈+人工智能”的学科
Subject.objects.filter(name='Python全栈+人工智能')
# <QuerySet [<Subject: Subject object (1)>]>
# 查询名称包含“全栈”的学科(模糊查询)
Subject.objects.filter(name__contains='全栈')
# <QuerySet [<Subject: Subject object (1)>]>
Subject.objects.filter(name__startswith='全栈')
# <QuerySet []>
Subject.objects.filter(name__endswith='全栈')
# <QuerySet []>
# 查询所有热门学科
Subject.objects.filter(is_hot=True)
# <QuerySet [<Subject: Subject object (1)>, <Subject: Subject object (3)>]>
# 查询编号大于3小于10的学科
Subject.objects.filter(no__gt=3).filter(no__lt=10)
# <QuerySet []>
Subject.objects.filter(no__gt=3, no__lt=10)
# <QuerySet []>
# 查询编号在3到7之间的学科
Subject.objects.filter(no__gte=3, no__lte=7)
# <QuerySet [<Subject: Subject object (3)>]>
Subject.objects.filter(no__range=(3, 7))
# <QuerySet [<Subject: Subject object (3)>]>
  1. 查询单个对象。
# 查询主键为1的学科
Subject.objects.get(pk=1)
# <Subject: Subject object (1)>
Subject.objects.get(no=1)
# <Subject: Subject object (1)>
Subject.objects.filter(no=1).first()
# <Subject: Subject object (1)>
Subject.objects.filter(no=1).last()
# <Subject: Subject object (1)>
  1. 排序。
# 查询所有学科按编号升序排列
Subject.objects.order_by('no')
# <QuerySet [<Subject: Subject object (1)>, <Subject: Subject object (3)>]>
# 查询所有部门按部门编号降序排列
Subject.objects.order_by('-no')
# <QuerySet [<Subject: Subject object (3)>, <Subject: Subject object (1)>]>
  1. 切片(分页查询)。
# 按编号从小到大查询前3个学科
Subject.objects.order_by('no')[:3]
# <QuerySet [<Subject: Subject object (1)>, <Subject: Subject object (3)>]>
  1. 计数。
# 查询一共有多少个学科
Subject.objects.count()
# 2
  1. 高级查询。
# 查询编号为1的学科的老师
Teacher.objects.filter(subject__no=1)
# <QuerySet [<Teacher: Teacher object (1)>, <Teacher: Teacher object (3)>]>
Subject.objects.get(pk=1).teacher_set.all() 
# Subject.objects.get(pk=1).teacher_set.all() 
# 查询学科名称有“全栈”二字的学科的老师
Teacher.objects.filter(subject__name__contains='全栈') 
# <QuerySet [<Teacher: Teacher object (1)>, <Teacher: Teacher object (3)>]>

说明1:由于老师与学科之间存在多对一外键关联,所以能通过学科反向查询到该学科的老师(从一对多关系中“一”的一方查询“多”的一方),反向查询属性默认的名字是类名小写_set(如上面例子中的teacher_set),当然也可以在创建模型时通过ForeingKey的related_name属性指定反向查询属性的名字。如果不希望执行反向查询可以将related_name属性设置为’+‘或者以’+'开头的字符串。

说明2:ORM查询多个对象时会返回QuerySet对象,QuerySet使用了惰性查询,即在创建QuerySet对象的过程中不涉及任何数据库活动,等真正用到对象时(对QuerySet求值)才向数据库发送SQL语句并获取对应的结果,这一点在实际开发中需要引起注意!

说明3:如果希望更新多条数据,不用先逐一获取模型对象再修改对象属性,可以直接使用QuerySet对象的update()方法一次性更新多条数据。


3.实现学科页和老师页效果

修改polls/views.py文件,编写视图函数实现对学科页和老师页的渲染。

from django.shortcuts import render, redirect
from polls.models import Subject, Teacher
def show_subjects(request):
    subjects = Subject.objects.all().order_by('no')
    return render(request, 'polls/subjects.html', {'subjects': subjects})
def show_teachers(request):
    try:
        sno = int(request.GET.get('sno'))
        teachers = []
        if sno:
            subject = Subject.objects.only('name').get(no=sno)
            teachers = Teacher.objects.filter(subject=subject).order_by('no')
        return render(request, 'polls/teachers.html', {
            'subject': subject,
            'teachers': teachers
        })
    except (ValueError, Subject.DoesNotExist):
        return redirect('/')

创建header.html文件

接下来我们可以稍微对首页的代码进行调整,在页面的右上角显示出登录用户的用户名。我们将这段代码单独写成了一个名为polls/templates/header.html的HTML文件,首页中可以通过在标签中添加{% include ‘header.html’ %}来包含这个页面,代码如下所示。


<div class="user">
    {% if request.session.userid %}
    <span>{{ request.session.username }}</span>
    <a href="/logout">注销</a>
    {% else %}
    <a href="/login">登录</a>&nbsp;&nbsp;
    {% endif %}
    <a href="/register">注册</a>
</div>

修改templates/subjects.html和templates/teachers.html模板页。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>学科信息</title>
    <style>
        #container {
            width: 80%;
            margin: 10px auto;
        }
        .user {
            float: right;
            margin-right: 10px;
        }
        .user>a {
            margin-right: 10px;
        }
        #main>dl>dt {
            font-size: 1.5em;
            font-weight: bold;
        }
        #main>dl>dd {
            font-size: 1.2em;
        }
        a {
            text-decoration: none;
            color: darkcyan;
        }
    </style>
</head>
<body>
    {% include 'header.html' %}
    <div id="container">
        <!-- <div class="user">
            <a href="/login">用户登录</a>
            <a href="/register">快速注册</a>
        </div> -->
        <h1>XX学堂所有学科</h1>
        <hr>
        <a href="/excel">教师信息下载</a>
        <div id="main">
            {% for subject in subjects %}
            <dl>
                <dt>
                    <a href="/teachers/?sno={{ subject.no }}">{{ subject.name }}</a>
                    {% if subject.is_hot %}
                    <img src="/static/images/hot-icon-small.png">
                    {% endif %}
                </dt>
                <dd>{{ subject.intro }}</dd>
            </dl>
            {% endfor %}
        </div>
    </div>
</body>
</html>


teachers.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>老师信息</title>
    <style>
        #container {
            width: 80%;
            margin: 10px auto;
        }
        .teacher {
            width: 100%;
            margin: 0 auto;
            padding: 10px 0;
            border-bottom: 1px dashed gray;
            overflow: auto;
        }
        .teacher>div {
            float: left;
        }
        .photo {
            height: 140px;
            border-radius: 75px;
            overflow: hidden;
            margin-left: 20px;
        }
        .info {
            width: 75%;
            margin-left: 30px;
        }
        .info div {
            clear: both;
            margin: 5px 10px;
        }
        .info span {
            margin-right: 25px;
        }
        .info a {
            text-decoration: none;
            color: darkcyan;
        }
    </style>
</head>
<body>
    {% include 'header.html' %}
    <a href="/get_echarts">教师好评分析</a>
    <div id="container">
        <h1>{{ subject.name }}学科的老师信息</h1>
        <hr>
        {% if not teachers %}
            <h2>暂无该学科老师信息</h2>
        {% endif %}
        {% for teacher in teachers %}
        <div class="teacher">
            <div class="photo">
                <img src="/static/images/{{ teacher.photo }}" height="140" alt="">
            </div>
            <div class="info">
                <div>
                    <span><strong>姓名:{{ teacher.name }}</strong></span>
                    <span>性别:{{ teacher.sex | yesno:'男,女' }}</span>
                    <span>出生日期:{{ teacher.birth }}</span>
                </div>
                <div class="intro">{{ teacher.intro }}</div>
                <div class="comment">
                    <a href="/praise/?tno={{ teacher.no }}">好评</a>&nbsp;&nbsp;
                    (<strong>{{ teacher.good_count }}</strong>)
                    &nbsp;&nbsp;&nbsp;&nbsp;
                    <a href="/criticize/?tno={{ teacher.no }}">差评</a>&nbsp;&nbsp;
                    (<strong>{{ teacher.bad_count }}</strong>)
                </div>
            </div>
        </div>
        {% endfor %}
        <a href="/">返回首页</a>
    </div>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script>
        $(() => {
            $('.comment>a').on('click', (evt) => {
                evt.preventDefault()
                let url = $(evt.target).attr('href')
                $.getJSON(url, (json) => {
                    if (json.code == 20000) {
                        $(evt.target).next().text(json.count)
                    } else {
                        alert(json.mesg)
                    }
                })
            })
        })
    </script>
</body>
</html>

修改vote/urls.py文件,实现映射URL。

from django.contrib import admin
from django.urls import path
from polls import views as polls_views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', polls_views.show_subjects),
    path('teachers/', polls_views.show_teachers),
]

到此为止,页面上需要的图片(静态资源)还没有能够正常展示,我们在下一章节中为大家介绍如何处理模板页上的需要的静态资源。


运行测试
python manage.py runserver


041413db40f5bd1adf59bf1e0ed18f82_c8a37bb2de5c461a82f96793165ba518.png

8ded1df3cd4f52899a21feb745b3a555_41998556c26a45f3a4282cd49c0ab5bb.png


总结


本文主要是Django系列博客。本文是Django模型层models的使用过程。

1.创建数据库

2.创建表

3.按照MySQL依赖

4.修改settings.py文件,添加应用配置数据库

5.基于数据库生成实体类

6.使用shell完成CRUD操作

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
23天前
|
存储 监控 数据库
Django 后端架构开发:高效日志规范与实践
Django 后端架构开发:高效日志规范与实践
35 1
|
1月前
|
监控 BI Python
python django教学质量评价系统,实现学生、教师、管理员不同角色管理
本文介绍了一个基于Django框架开发的教学质量评价系统,该系统为学生、教师和管理员提供了不同角色的管理和评价功能,实现了教学质量的全方位评估和管理,旨在提高教育质量和促进教学改革。
python django教学质量评价系统,实现学生、教师、管理员不同角色管理
|
23天前
|
负载均衡 应用服务中间件 网络安全
Django后端架构开发:Nginx服务优化实践
Django后端架构开发:Nginx服务优化实践
34 2
|
4天前
|
数据处理 Python
Django视图:构建动态Web页面的核心技术
Django视图:构建动态Web页面的核心技术
|
1月前
|
机器学习/深度学习 前端开发 数据挖掘
基于Python Django的房价数据分析平台,包括大屏和后台数据管理,有线性、向量机、梯度提升树、bp神经网络等模型
本文介绍了一个基于Python Django框架开发的房价数据分析平台,该平台集成了多种机器学习模型,包括线性回归、SVM、GBDT和BP神经网络,用于房价预测和市场分析,同时提供了前端大屏展示和后台数据管理功能。
|
1月前
|
存储 数据库 开发者
Django Web架构:全面掌握Django模型字段(下)
Django Web架构:全面掌握Django模型字段(下)
49 2
|
18天前
|
API 数据库 开发者
【独家揭秘】Django ORM高手秘籍:如何玩转数据模型与数据库交互的艺术?
【8月更文挑战第31天】本文通过具体示例详细介绍了Django ORM的使用方法,包括数据模型设计与数据库操作的最佳实践。从创建应用和定义模型开始,逐步演示了查询、创建、更新和删除数据的全过程,并展示了关联查询与过滤的技巧,帮助开发者更高效地利用Django ORM构建和维护Web应用。通过这些基础概念和实践技巧,读者可以更好地掌握Django ORM,提升开发效率。
11 0
|
21天前
|
SQL Shell API
python Django教程 之 模型(数据库)、自定义Field、数据表更改、QuerySet API
python Django教程 之 模型(数据库)、自定义Field、数据表更改、QuerySet API
|
23天前
|
JSON API 数据安全/隐私保护
Django 后端架构开发:JWT 项目实践与Drf版本控制
Django 后端架构开发:JWT 项目实践与Drf版本控制
31 0
|
1月前
|
SQL 关系型数据库 MySQL
如何创建 Django 模型
如何创建 Django 模型
16 0