Django框架知识

目录

一.数据的增删改查

1.大致流程

用户列表的展示

修改数据的逻辑分析

删除功能的分析

2.如何查询数据

3.数据的增加

4.用户操作数据的更改

(1)编辑功能

(2)删除功能

二.表关系的建立

1.表关系相关知识

2.总结

(1)ForeignKey(多对一)

(2)ManyToManyField(多对多)

(3)OneToOneField(一对一)

[(4)ManyToManyField 和 OneToOneField自动加id后缀](#(4)ManyToManyField 和 OneToOneField自动加id后缀)


一.数据的增删改查

1.大致流程

用户列表的展示

把数据表中的用户数据都给查询出来展示在页面上

修改数据的逻辑分析

  1. 先确定修改哪条记录 ------> 怎么确定修改哪条记录
  2. 通过什么字段可以确定唯一一条记录
  3. 在后端接收主键id值,然后根据这个id值再去表中查询数据
  4. 然后把查询的数据渲染到页面中,然后在进行修改
  5. 把修改之后的表单提交到后端,再做修改

删除功能的分析

  1. 给删除按钮加一个链接,携带当前记录的id值
  2. 后端要接收这个主键id值
  3. 后端直接执行删除操作

2.如何查询数据

python 复制代码
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')
python 复制代码
# 向数据库查询数据
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
  • 返回值类似于列表套对象
    • 支持索引取值,支持切片,但是不支持负数索引取值
    • 不推荐索引取值

3.数据的增加

python 复制代码
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')

4.用户操作数据的更改

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

(1)编辑功能

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

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

查询数据

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

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

用户数据展示

python 复制代码
<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>

编辑数据

python 复制代码
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())

用户数据展示页面

python 复制代码
{% 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>

编辑用户数据页面

python 复制代码
{% 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>

路由层

python 复制代码
"""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)删除功能

  • 跟编辑功能逻辑类似

删除功能

python 复制代码
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/')

路由层

python 复制代码
"""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),
]
  • 真正的删除数据操作需要二次确认
  • 删除数据,内部其实不是真正的删除数据
    • 我们会给数据添加一个删除字段来表示数据是否被删除了,如果数据被删除了,仅仅只是修改字段的状态值

二.表关系的建立

1.表关系相关知识

  • 表与表之间的关系
    • 一对一
    • 一对多
    • 多对多
  • 判断表关系的方法
    • 换位思考

以图书和出版社关系为例

  • 图书和出版社是一对多的关系
    • 外键建在多的一方,即图书
  • 图书和作者是多对多的关系
    • 需要创建第三张表
  • 作者与作者详情表是一对一的关系

图书表

python 复制代码
class Book(models.Model):
    # 默认创建主键字段(可忽略不写)
    # 创建字段 :书籍标题
    title = models.CharField(max_length=32, verbose_name="书籍名称")
    # 创建字段 :书籍价格
    # max_digits : 小数一共几位
    # decimal_places :小数点后几位
    price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="书籍价格")
    '''
    图书和出版社是一对多,并且书是多的一方 , 所以外键字段放在书表里面
    '''
    # to_fields : 默认不写就是和被关联表的id值进行关联
    # on_delete=models.CASCADE : 级联更新
    '''
    如果字段对应的是 ForeignKey 那么 ORM 会自动在字段后面 加 id 变成 publish_id 
    如果自己 加了 id 即 publish_id ,ORM 仍然会帮我们在后面 加 _id 变成 publish_id_id
    
    后面在使用 ForeignKey 时 ,不建议 自己主动加id
    '''
    publish = models.ForeignKey(to='Publisher', on_delete=models.CASCADE)
    '''
    图书和作者是多对多的关系 外键建在任意一方即可 ,但是推荐建在查询频率较高的一方
    '''
    # authors : 是一个虚拟字段,主要是用来告诉 ORM 数据表和作者表是多对多的关系
    # 让 ORM 来帮助我们自动创建第三张表
    authors = models.ManyToManyField(to='Author')

出版社表

python 复制代码
class Publisher(models.Model):
    # 默认创建主键字段(可忽略不写)
    # 创建字段 : 出版社名字
    pub_name = models.CharField(max_length=32, verbose_name="出版社名称")
    # 创建字段 : 出版社地址'
    pub_addr = models.CharField(max_length=32, verbose_name="出版社地址")

作者表

python 复制代码
class Author(models.Model):
    # 默认创建主键字段(可忽略不写)
    # 创建字段 : 作者名字
    aut_name = models.CharField(max_length=32, verbose_name="作者名字")
    # 创建字段 : 作者年龄
    aut_age = models.IntegerField(verbose_name="作者年龄")
    '''
    作者与作者详情之间是一对一的关系, 外键字段建在任意一方即可,但是推荐建在查询频率较高的一方
    '''
    '''
       如果字段对应的是 OneToOneField 那么 ORM 会自动在字段后面 加 id

       后面在使用 OneToOneField 时 ,不建议 自己主动加id
    '''
    author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)

作者详情表

python 复制代码
class AuthorDetail(models.Model):
    # 默认创建主键字段(可忽略不写)
    # 创建字段 : 作者电话
    # 考虑到电话的长度问题,建议用 BigIntegerField 或者 直接 用 CharField存成字符串
    aut_phone = models.BigIntegerField(verbose_name="作者电话")
    # 创建字段 : 作者的住址
    aut_addr = models.CharField(max_length=32, verbose_name="作者住址")

配置文件:setting.py

python 复制代码
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'day10', # 指定数据库
        'USER': 'root', #  自己的用户名
        'PASSWORD': '1314521',  #  自己的密码
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'CHARSET': 'utf8',
    }
}

初始化文件:init.py

python 复制代码
import pymysql

pymysql.install_as_MySQLdb()

终端重载数据库

python 复制代码
python39 manage.py makemigrations

python39 manage.py migrate

2.总结

(1)ForeignKey(多对一)

  • 是Django中的一个字段类型,用于建立模型间的多对一关系,通过在一个模型中使用ForeignKey字段,可以将其与另一个模型的主键关联起来,表示多个实例对应一个实例关系
  • 比如
    • 一个博客系统中,可以有两个模型:作者(Author)和文章(Post)
    • 一个作者可以写多篇文章,但一篇文章只能对应一个作者
    • 这时,可以在Post模型中定义一个ForeignKey字段,指向Author模型:
python 复制代码
class Author(models.Model):
    name = models.CharField(max_length=50)

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

(2)ManyToManyField(多对多)

  • 也是Django中的一个字段类型,用于建立模型间的多对多关系
    • 通过使用ManyToManyField字段,可以在两个模型之间创建一个多对多的关联,表示多个实例之间互相对应的关系
  • 继续以博客系统为例
    • 在一个标签(Tag)模型和文章(Post)模型之间存在多对多的关系
    • 一篇文章可以对应多个标签,一个标签也可以对应多篇文章
    • 这时,可以在Post模型和Tag模型中分别定义ManyToManyField字段:
python 复制代码
class Tag(models.Model):
    name = models.CharField(max_length=50)

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    tags = models.ManyToManyField(Tag)

(3)OneToOneField(一对一)

  • 是Django中的另一个字段类型,用于建立模型间的一对一关系
    • 通过使用OneToOneField字段,可以在两个模型之间创建一个一对一的关联,表示一个实例对应另一个实例的关系
  • 例如
    • 一个用户(User)模型和一个用户资料(Profile)模型之间有一对一的关系
    • 每个用户只有一个对应的用户资料
    • 可以在Profile模型中定义一个OneToOneField字段,在User模型上进行关联:
python 复制代码
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField()
    location = models.CharField(max_length=50)
  • 上述代码中,Profile模型中的user字段是一个OneToOneField字段,它以User模型为参数来指定一对一的关联,这样就可以让每个user实例对应一个Profile实例,方便扩展用户信息

(4)ManyToManyField 和 OneToOneField自动加id后缀

如果字段对应的是ForeignKey/OneToOneField那么ORM会自动在字段后面加id变成publish_id如果自己加了id,ORM仍会在字段后再加上id

  • 实际上,ManyToManyField和OneToOneField字段在数据库中会自动创建相关的外键
    • 并非在字段后加上'id'后缀
    • 这些外键字段名的生成方式取决于Django的命名规则和相关模型的名称

对于ManyToMany字段,Django会默认使用源模型(即声明ManyToManyField的模型)的名称和目标模型(关联的模型)的名称来生成中间表的名称,并在其中创建外键

  • 例如,如果有两个模型:Author和Book,并且在Author模型中有一个books字段声明为ManyTomanyField类型:
python 复制代码
from django.contrib.auth.models import User

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField()
    location = models.CharField(max_length=50)
  • Django将在Profile模型中创建一个名为user_id的外键字段,用于与User模型进行关联

总结来说,ManyToManyField和OneToOneField字段在数据库中会生成相关的外键字段,并且没有自动加上id后缀

其他与这些字段相关的命名规则和约定主要取决于使用Django的默认行为或者通过特定参数进行自定义

相关推荐
魔道不误砍柴功5 分钟前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2345 分钟前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
_.Switch30 分钟前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
王哈哈^_^1 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
Chrikk2 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*2 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue2 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man2 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
cs_dn_Jie2 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
测开小菜鸟2 小时前
使用python向钉钉群聊发送消息
java·python·钉钉