【3.0】Django框架之数据操作初识

发布时间 2023-07-17 11:35:08作者: Chimengmeng

【一】登录功能实现

【1】form表单默认是post请求

  • 添加的数据会默认拼接在url后面
<form action=""></form>

http://127.0.0.1:8000/login/?username=dream&password=521

【2】form表单的action参数

  • 不写,向当前所在的url提交数据
  • 全写,向指定url提交数据
  • 只写后缀

在前期我们使用django提交post请求时,需要修改配置文件中的一项配置

  • 将中间件禁掉,不走中间件传输数据
  • 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',
]

【3】请求方式的不同返回信息不同

def login(request):
    '''
    get 请求和 post 请求应该具有不同的处理机制
    :param request:
    :return:
    '''
    # (1) 获取 请求方式 并且是全大写字符串
    if request.method == "GET":
        # 返回一个登录界面
        return render(request, 'login.html')
    return HttpResponse("这是get请求")

【二】request初识

【1】request.method

获取发起请求的请求方式

get请求携带的数据是由大小限制的

post请求携带的请求参数没有限制

【2】request.POST

获取用户输入的请求数据,但不包含文件

返回的是:大写字符串

【3】get/getlist

get 只会获取列表最后一个元素

getlist 直接将列表取出(多选项)

def login(request):
    '''
    get 请求和 post 请求应该具有不同的处理机制
    :param request:
    :return:
    '''
    # (1) 获取 请求方式 并且是全大写字符串
    if request.method == "POST":
        # 获取用户数据
        data = request.POST
        print(data)

        '''
        # get 只会获取列表最后一个元素
        username = data.get('username')
        password = data.get('password')
        hobby = data.get('hobby')
        '''
        # getlist 获取所有值
        username = data.getlist('username')
        password = data.getlist('password')
        hobby = data.getlist('hobby')

        print(username, password, hobby)

    # 获取 get 请求 网址后边携带的请求参数
    data = request.GET
    # 处理请求数据 同 POST
    return render(request, 'login.html')

【三】操作数据库

【1】默认数据库

默认数据库:sqlite3

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

【2】修改数据库

修改数据库配置

  • settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day09',
        'USER': 'root',
        'PASSWORD': '1314521',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'CHARSET': 'utf8',
    }
}

代码声明

django 默认使用mysqldb模块链接mysql

但是该模块的兼容性不好,需要手动修改为pymysql链接

在项目下的init或者任意的应用名下的init文件中书写一下代码

  • init.py
import pymysql

pymysql.install_as_MySQLdb()

【四】django ORM

ORM ---- 对象映射关系

作用:能够让一个不会用sql语句操控数据库的小白也能通过python 面向对象的代码简单快捷的操作数据库

不足之处:封装程度不高,有时候sql语句的效率偏低,需要自己写sql语句

应用下的models.py文件中修改

【1】在models.py中建表

from django.db import models


# Create your models here.

class User(models.Model):
    # id int primary key auto_increment
    id = models.AutoField(primary_key=True)

    # username varchar(32)
    username = models.CharField(max_length=32)

    # password int
    password = models.IntegerField()

【2】数据库迁移命令

  • 将操作记录记录在migrations文件夹
python39 manage.py makemigrations
  • 将操作同步到真正的数据库
python39 manage.py migrate

只要修改了models中有关数据库相关的代码,就必须执行上面的数据库迁移命令

1

2

  • app01_user
    • 我们通过orm创建的表
    • 一个项目可能有多个应用,在前面加上前缀是为了防止表明冲突造成数据错乱
  • models.py
from django.db import models


# Create your models here.

class User(models.Model):
    # id int primary key auto_increment
    id = models.AutoField(primary_key=True)

    # username varchar(32)
    username = models.CharField(max_length=32,verbose_name="用户名")
    # CharField : 必须指定 max_length 参数 ,不指定就会报错
    # verbose_name : 该参数所有字段都可以使用,就是一个注释语法
    # password int
    password = models.IntegerField()


class Author(models.Model):
    # 由于一张表中必须要有一个主键字段,并且一般情况下都叫id字段
    # 所有当我们没有定义 主键 id字段 的时候,orm会帮我们创建一个名为 id 的主键字段
    # 也就意味着后续我们在创建模型表的时候,如果主键字段名没有额外的叫法,那么主键字段可以省略不写

    # username varchar(32)
    username = models.CharField(max_length=32)

    # password int
    password = models.IntegerField()

修改数据库操作时候,一定要进行数据库的重加载(我自己的叫法)

【五】字段的增删改查

【1】字段的添加

【1】在终端给出默认值

  • 直接在终端给出默认值

【2】允许为空

  • 给语句增加一条 null=True

【3】主动设置默认值default="music"

  • 提前设定好默认值

【4】代码

from django.db import models


# Create your models here.

class User(models.Model):
    # id int primary key auto_increment
    id = models.AutoField(primary_key=True)

    # username varchar(32)
    username = models.CharField(max_length=32, verbose_name="用户名")
    # CharField : 必须指定 max_length 参数 ,不指定就会报错
    # verbose_name : 该参数所有字段都可以使用,就是一个注释语法
    # password int
    password = models.IntegerField()
	
    # *******
    # (1)添加字段:年龄,若表内已经存在数据,而要添加额外的字段需要给默认值
    age = models.IntegerField(verbose_name="年龄")
    # (2)添加允许为空字段
    info = models.CharField(verbose_name="个人简介", max_length=32, null=True)
    # (3)提前设定好默认值
    hobby = models.CharField(verbose_name="爱好", max_length=32, default="music")
	# *******

class Author(models.Model):
    # 由于一张表中必须要有一个主键字段,并且一般情况下都叫id字段
    # 所有当我们没有定义 主键 id字段 的时候,orm会帮我们创建一个名为 id 的主键字段
    # 也就意味着后续我们在创建模型表的时候,如果主键字段名没有额外的叫法,那么主键字段可以省略不写

    # username varchar(32)
    username = models.CharField(max_length=32)

    # password int
    password = models.IntegerField()

【2】字段的更改

  • 直接修改源码,再进行数据库重载
from django.db import models


# Create your models here.

class User(models.Model):
    # id int primary key auto_increment
    id = models.AutoField(primary_key=True)

    # username varchar(32)
    username = models.CharField(max_length=32, verbose_name="用户名")
    # CharField : 必须指定 max_length 参数 ,不指定就会报错
    # verbose_name : 该参数所有字段都可以使用,就是一个注释语法
    # password int
    # password = models.IntegerField()
    # *******由原来的字段修改为新的字段*******
    password = models.CharField(verbose_name="密码", max_length=64)

    # (1)添加字段:年龄,若表内已经存在数据,而要添加额外的字段需要给默认值
    age = models.IntegerField(verbose_name="年龄")
    # (2)添加允许为空字段
    info = models.CharField(verbose_name="个人简介", max_length=32, null=True)
    # (3)提前设定好默认值
    hobby = models.CharField(verbose_name="爱好", max_length=32, default="music")


class Author(models.Model):
    # 由于一张表中必须要有一个主键字段,并且一般情况下都叫id字段
    # 所有当我们没有定义 主键 id字段 的时候,orm会帮我们创建一个名为 id 的主键字段
    # 也就意味着后续我们在创建模型表的时候,如果主键字段名没有额外的叫法,那么主键字段可以省略不写

    # username varchar(32)
    username = models.CharField(max_length=32)

    # password int
    password = models.IntegerField()

【3】删除字段

  • 直接注释源码

  • 再进行重载数据库

一旦删除字段,字段下所在的数据也会同时消失,一定要小心

重载之前一定要确认数据

【六】数据的增删改查

【1】查询数据

from django.shortcuts import render, HttpResponse, redirect
from app01 import models


# Create your views here.

def login(request):
    '''
    get 请求和 post 请求应该具有不同的处理机制
    :param request:
    :return:
    '''
    # (1) 获取 请求方式 并且是全大写字符串
    if request.method == "POST":
        # 获取用户数据
        data = request.POST
        # print(data)

        '''
        # get 只会获取列表最后一个元素
        username = data.get('username')
        password = data.get('password')
        hobby = data.get('hobby')
        '''
        # # getlist 获取所有值
        # username = data.getlist('username')
        # password = data.getlist('password')
        # hobby = data.getlist('hobby')
        #
        # print(username, password, hobby)

        # --------------------------
        # 获取用户输入的用户名和密码
        username = data.get('username')
        password = data.get('password')

        # 向数据库查询数据
        res = models.User.objects.filter(username=username)
        print(res)
        # 返回的是[数据对象1,数据对象2]
        # 数据对象支持索引取值
        user_obj = res[0]
        print(user_obj.username)
        print(user_obj.password)



    # 获取 get 请求 网址后边携带的请求参数
    data = request.GET
    # 处理请求数据 同 POST
    return render(request, 'login.html')

# 向数据库查询数据
res = models.User.objects.filter(username=username)
print(res)
# 返回的是[数据对象1,数据对象2]
# 数据对象支持索引取值
user_obj = res[0]
print(user_obj.username)
# dream
print(user_obj.password)
# 521
  • 返回值类似于列表套对象
    • 支持索引取值,支持切片,但是不支持负数索引取值
    • 不推荐索引取值

【2】数据的增加

def register(request):
    # 先给用户返回一个注册页面
    if request.method == 'POST':
        data = request.POST
        username = data.get('username')
        password = data.get('password')

        # # 直接获取用户输入的数据存储进数据库
        # # (1)第一种直接添加
        # res = models.User.objects.create(username=username, password=password)
        # # 返回值就是当前被创建的对象本身
        # print(res)
        # (2) 第二种 创建类对象
        user_obj = models.User(username=username, password=password)
        # 保存数据
        user_obj.save()

    return render(request, 'register.html')

【3】用户操作数据的更改

  • 先从数据库中将数据全部展示到前端,然后添加两个按钮,一个编辑,一个删除

(1)编辑功能

点击编辑按钮,向后端发送编辑数据的请求

  • 如何告诉用户想要编辑哪条数据?
    • 将编辑按钮所在的信息的主键值发送给后端
      • 在URL的?中携带参数
  • 后端拿到用户想要编辑的数据对象,展示到前端页面供用户查看和编辑

查询数据

def resetdata(request):
    # 查询用户表内的所有数据
    # 方式一
    # data = models.User.objects.filter()
    # 方式二
    user_queryset = models.User.objects.all()

    return render(request, 'resetdata.html', locals())

用户数据展示

<tbody>
    {% for user_obj in user_queryset %}
    <tr>
        <td>{{ user_obj.id }}</td>
        <td>{{ user_obj.username }}</td>
        <td>{{ user_obj.password }}</td>
        <td>
            <a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-success btn-primary">编辑</a>
            <a href="" class="btn btn-danger btn-primary">删除</a>
        </td>
    </tr>


    {% endfor %}

</tbody>

编辑数据

def edit_user(request):
    # 获取URL后面拼接的用户ID
    edit_id = request.GET.get('user_id')
    # 查询当前用户想要编辑的用户对象
    edit_obj = models.User.objects.filter(id=edit_id).first()
    # 编辑用户
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        # 在数据库中修改数据

        # 修改数据方式一
        # 将 filter 查询出的列表内的所有的对象全部更新 ---- 批量更新操作
        # 只修改被修改的字段
        # models.User.objects.filter(id=edit_id).update(username=username, password=password)
        # 编辑完后跳转到展示与用户数据页面

        # 修改数据方式二
        # 局部更新
        # 当字段特别多的时候,效率会非常低
        # 从头到尾将数据的所有字段更新一遍,无论字段是否被改变
        edit_obj.username = username
        edit_obj.password = password
        edit_obj.save()

        return redirect('/resetdata/')

    # 将数据对象展示到页面上
    return render(request, 'edituser.html', locals())

用户数据展示页面

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!--  本地 链接 引入方法  -->
    <!--  Websource 文件夹 拷贝到当前文件夹下即可使用  -->
    <!--  jQuery 文件  -->
    <script src="{% static 'plugins/Bootstrap/js/bootstrap.min.js' %}"></script>
    <!--  Bootstrap 的 JS 文件 (动画效果需要jQuery)  -->
    <script src="{% static 'js/jquery.min.js' %}"></script>
    <!--  Bootstrap 的 CSS 样式文件  -->
    <link rel="stylesheet" href="{% static 'plugins/Bootstrap/css/bootstrap.min.css' %}">
    <!-- bootstrap-sweetalert(弹框) 的 CSS 文件   -->
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-sweetalert/dist/sweetalert.css' %}">
    <!-- bootstrap-sweetalert(弹框) 的 JS 文件 -->
    <script src="{% static 'plugins/bootstrap-sweetalert/dist/sweetalert.min.js' %}"></script>

    <!--  以下为 css样式书写区  -->
    <style>


    </style>

</head>
<body>

{#拿到用户数据#}
{{ user_queryset }}

<h1 class="text-center">用户数据展示</h1>
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <table class="table table-striped table-hover">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>USERNAME</th>
                    <th>PASSWORD</th>
                    <th>ACTION</th>
                </tr>
                </thead>
                <tbody>
                {% for user_obj in user_queryset %}
                    <tr>
                        <td>{{ user_obj.id }}</td>
                        <td>{{ user_obj.username }}</td>
                        <td>{{ user_obj.password }}</td>

                        <td>
                            <a href="/edit_user/?user_id={{ user_obj.id }}" class="btn btn-success btn-primary">编辑</a>
                            <a href="" class="btn btn-danger btn-primary">删除</a>
                        </td>
                    </tr>


                {% endfor %}

                </tbody>
            </table>
        </div>
    </div>
</div>


</body>
</html>

编辑用户数据页面

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!--  本地 链接 引入方法  -->
    <!--  Websource 文件夹 拷贝到当前文件夹下即可使用  -->
    <!--  jQuery 文件  -->
    <script src="{% static 'plugins/Bootstrap/js/bootstrap.min.js' %}"></script>
    <!--  Bootstrap 的 JS 文件 (动画效果需要jQuery)  -->
    <script src="{% static 'js/jquery.min.js' %}"></script>
    <!--  Bootstrap 的 CSS 样式文件  -->
    <link rel="stylesheet" href="{% static 'plugins/Bootstrap/css/bootstrap.min.css' %}">
    <!-- bootstrap-sweetalert(弹框) 的 CSS 文件   -->
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-sweetalert/dist/sweetalert.css' %}">
    <!-- bootstrap-sweetalert(弹框) 的 JS 文件 -->
    <script src="{% static 'plugins/bootstrap-sweetalert/dist/sweetalert.min.js' %}"></script>

    <!--  以下为 css样式书写区  -->
    <style>


    </style>
<body>
<h1 class="text-center">信息编辑功能</h1>
<div class="container">
    <div class="row">
        <div class="col-lg-8 col-md-offset-2">
            <form action="" method="post">
                <p>username:<input type="text" name="username" class="form-control" value="{{ edit_obj.username }}"></p>
                <p>password<input type="password" name="password" class="form-control" value="{{ edit_obj.password }}"></p>
                <input type="submit" class="btn btn-success btn-block" value="编辑">
            </form>
        </div>
    </div>
</div>
</body>
</html>

路由层

"""day02 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('register/', views.register),
    # 查询所有用户信息
    path('resetdata/', views.resetdata),
    # 编辑用户信息
    path('edit_user/', views.edit_user),
]

(2)删除功能

  • 跟编辑功能逻辑类似

删除功能

def del_user(request):
    # 获取用户想要删除的用户ID
    del_user_id = request.GET.get('user_id')
    # 拿到用户对象并删除
    # 批量删除
    models.User.objects.filter(id=del_user_id).delete()

    # 删除成功,跳转到展示页面
    return redirect('/resetdata/')

路由层

"""day02 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('register/', views.register),
    # 查询所有用户信息
    path('resetdata/', views.resetdata),
    # 编辑用户信息
    path('edit_user/', views.edit_user),
    # 删除用户数据
    path('del_user/', views.del_user),
]
  • 真正的删除数据操作,需要二次确认!
  • 删除数据,内部其实不是真正的删除数据
    • 我们会给数据添加一个删除字段来表示数据是否被删除了,如果数据被删除了,仅仅只是修改字段的状态值