django基础操作简述

django基础操作简述

本文是对django整体架构功能的简单叙述,重在能够通过django架构简单的实现前端网页到后端数据库整体流程的实现,也是对django配置的概念补充。

静态文件

static文件夹 --- 存一些css,js,img,第三方模块等,也可以再分文件夹

如:我们可以要引入本地的bootstrap的css和js文件,那么就可以放在static文件夹中,并且引入到html文件中进行使用,如图:

<link rel="stylesheet" href="static/bootstrap-5.1.3-dist/css/bootstrap.css">
<script src="static/bootstrap-5.1.3-dist/js/bootstrap.bundle.js"></script>

image

但是当我们访问网页,发现我们预设的bootstrap的样式并没有加载出来

image

检查一下网络请求,发现是因为bootstrap的css文件和js文件没能正常请求到:

image

image

默认情况下无法访问我们这些静态文件,因为没有开放资源连接

静态文件资源开放

我们的html文件页面是通过url路由文件来配置路由和视图的对应关系,但是,对于繁杂的静态文件而言,使用urls去一个个的配置又过于麻烦,所以针对静态文件,django提供了一种配置接口:

# settings.py 中大概底端的位置
STATIC_URL = '/static/'   # 访问静态文件资源的接口前缀
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]  # 存储静态文件资源的目录

配置好后我们再次访问我们的网页,发现bootstrap文件就正常被导入了。

我们还可以让静态文件配置的动态加载,让访问的接口随配置的变化而变化。

在编写html文件时,可以先将一些配置导入,而静态文件的接口前缀则可以通过以下代码导入:

{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>

这些在html中插入{% %}形式的占位符,可以配合python代码,在处理这些文字时,实现一些逻辑,这个在后续会有详细的说明。

而这段代码中,导入了静态接口的前缀,让我们的bootstrap文件的请求网址能够随访问的接口前缀变化而变化。

form表单

action:三种情况

  • ""

    没有写,则默认提交给当前页面所在的地址

  • "https//:一个完整网址"

    那就提交给这个指定的网址

  • "/路由" 如:"/home/"一定会引到https//:顶级域名/home/

    朝当前服务端的对应路由提交

  • "一个字符串" 如:"home/"则会引到https//:顶级域名/当前页面路由/home/

    相对于现在界面的网址,再向后拼接这个字符串

method:get\post请求方式

  • get请求是最常用的请求方式,是默认的请求方式

    这种请求方式,有时会在网址和路由后携带数据,格式为:

    image

    ?键=值&键2=值2。。

    • 这种数据可以通过表单设置method为get提交,也可以直接在网址后提交。

    • get所携带的数据大小是有限的。

  • post请求的数据在请求头中

    • 这种请求方式,会隐藏的提交数据到后端,因为get请求提交的数据可以被看到不能满足所有的数据提交情况,如提交一些敏感数据时,可能被看到。

    • 这种数据可以通过表单提交(method="post")

    • post所携带的数据大小是没有限制的。

    而post所携带的数据,和get所携带的数据在request对象的不同属性中。

request对象

request对象是在wsgiref模块的request字典基础上,又进一步的将其封装成了对象,不但处理了数据,还提供了一些功能。

以下就是针对请求体的一些方法。

属性 属性值|方法 说明
.method 获取请求方式 GET或者POST的字符串
.POST 拿到请求体中的数据 拿到post请求携带数的据组织的queryDict
.GET 拿到请求首行中的数据 拿到get请求携带的数据组织的queryDict
QueryDict 可以通过get(),getlist()拿值 字典的派生类的对象
request.GET   # 获取get请求携带数据,组织形式为QuerySet{"":['',],}
# get数据需要

request.POST.get(key)  # 获取列表的最后一个数据值
request.POST.getlist(key)  # 获取整个列表数据

ps:在表单无法提交(403 forbidden)时,可以在配置中修改以下配置来解决:

image

Django连接数据库

  1. Django配置文件中默认配置的是sqlite3,用于本地测试,一般项目都不会用,实际项目中会替换掉。
# 默认配置文件
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
↓↓↓↓↓↓↓↓
# 修改配置文件
DATABASES = {
    'default': {
            'ENGINE': 'django.db.backends.mysql',  # django后端数据引擎
            'NAME': 'navicat_test1',  # mysql这个属性用数据库即可
            'HOST': '127.0.0.1',  # ip
            'PORT': 3306,
            'USER': 'root',  # mysql用户名,当然一般的项目中你都不是root
            'PASSWORD': '111',
            'CHARSET': 'utf8'
        }
}

image

配置文件改完后,看服务端的运行情况,报错了,并提示MySQLdb模块加载错误,是否下载mysqlclient。

我们下载后就恢复正常了,正常的启动我们的服务端。

ps:对于Django1.x版本而言,是通过pymysql连接的,需要以下语句俩配置
import pymysql 换行 pymysql.install_as_MySQLdb()

我们知道数据库能存储的数据类型是有限的,我们如果想要存储我们的类和对象,怎么做呢?

或者说如何通过操作对象的方式去取我们数据库的方式(绕过sql语句)

ORM

将类和对象映射为数据库的数据:

  • 类 --- 表
  • 对象 --- 记录
  • 对象的属性值 --- 记录某个字段的值

orm高度的封装了我们的sql语句,所以查询速度等级并不高,有些时候还是需要自己写sql。

但是orm操作对python程序员方便快捷。

orm操作

类相关

  1. models.py中编写模型类

    from django.db import models
    
    # Create your models here.
    
    class GirlsInfo(models.Model):
        # 字段名 = 字段类型 + 约束条件
        id = models.AutoField(primary_key=True)  # 主键类型
        name = models.CharField(max_length=32)   # 字符字段
        age = models.IntegerField()  # 整型字段
    
  2. 执行数据库迁移相关命令(每次修改和增加模型类都需要执行)

    python38 manage.py makemigrations  # 记录数据库相关
    python38 manage.py migrate  # 将操作同步到数据库
    # 第一次会创建很多表、其中一个是当前新增的模型表
    

记录数据库,django项目会根据models.py的改动同步到app各自的migrations文件夹中。
image

数据库记录完后,migrate命令会根据migrations记录,将模型类同步到mysql中(创建对应的表)
而对应的表的表名是以app名_类名来命名的。
除此以外,初次创建表还会建立很多其他的表。

image

对象相关

  1. 对 对象记录 进行筛选增删改查

    from app02 import models  # 将模型类导入 
    models.类名.objects.create()   # 根据字段塞关键字参数,就能插入记录
    models.类名.objects.filter()   # 筛选并默认查询
    models.类名.objects.update()   # 批量更新,一般搭配filter使用
    models.类名.objects.delete()   # 批量删除,一般搭配filter使用
    

django请求生命流程图

django项目所搭建的网页,从网页输入网址开始,都经历了哪些环节最终响应到我们的浏览器显示出来。一个大致的流程是这样的:

image

其中需要注意的是,wsgiref和uwsgi都是实现web服务网网关协议的功能模块,都遵循WSGI协议。

而两者的区别在于wsgiref能够承受的并发量很低,只能用于本地测试,而实际的项目中肯定会切换成并发量更高的uwsgi模块

后续的博文会基于这个流程图,分别对每一层进行详细的叙述。

数据增删改查app搭建实操

建立django项目和app

在pycharm中创建新django项目,可以自动生成一个app -- table_crud(自动配置app)
并设置一些基本配置,

  • 如templates的路径(TEMPLATES的DIRS)
  • 设置可post请求(MIDDLEWARE中间行注释掉)

与数据库建立联系

修改DATABASES配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': "site02",  # 前提有这个库
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': '111',
        'CHARSET': 'utf8'
    }
}

在models创建模型类

class UserData(models.Model):
    id = models.AutoField(primary_key=True)  # 如果不写,则会自动生成
    name = models.CharField(max_length=32)  # 默认varchar,必须指定最大长度
    password = models.CharField(max_length=32)  # 存个密码便于拓展
    age = models.IntegerField()
    tel = models.CharField(max_length=32, unique=True)  # 电话号码设置个唯一属性

将改动同步到migrations和数据库

python38 manage.py makemigrations
python38 manage.py migrate

确认下migrations文件夹和数据库中是否添加了相应的文件和表。

编写首页

首页主要用来展示我们的数据,并且提供 增加|修改|删除数据 的按钮链接。

总体需要搭建成这样(图中的数据是预设的):

image

总体搭建首页需要协同路由层,视图层数据处理,html模板语法。

  • 首页url配置:

    from table_crud import views as table_crud_views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', table_crud_views.show_data_page),  # 顶级域名默认首页
        path('home/', table_crud_views.show_data_page),  # 写了home路由也是首页
    ]
    
  • 视图层

    from table_crud import models  # 将模板类导入
    
    def show_data_page(request):
        user_data_list = models.UserData.objects.filter()  # 对表进行查询操作
        # 将表的查询结果[{},{},{}]通过render提交给html做模板语法,处理完后返回给用户
        return render(request, "show_data_page.html", {"user_data_list": user_data_list, })
    
  • 首页模板

    这里有些内容是后续过程中添加的,第一次编写首页时,我们只需要将重点放在:

    循环生成行标签,每行插入要展示的用户数据和即可,链接标签可以暂时为空。

    <head>
    	<!--head中导入jQuery、bootstrap等-->
    </head>
    <body>
    <div class="container">
    <div class="row">
    <div class="col-md-6 offset-md-3">
    <h1 class="text-center">数据展示页</h1>
    <p>
    <a class="btn btn-success" href={% url "add_func" %}>添加数据</a>
    </p>
    <div class="shadow"><table class="table table-striped table-hover">
    <thead>
    <tr>
    <th>name</th>
    <th>age</th>
    <th>tel</th>
    <th>operation</th>
    </tr>
    </thead>
    <tbody>
    {% for user_dict in user_data_list %}  <!--模板语法循环开始-->
    <tr>
    <td>{{ user_dict.name }}</td>  <!--模板语法:字典可以点取值-->
    <td>{{ user_dict.age }}</td>
    <td>{{ user_dict.tel }}</td>
    <td>
    <a class="btn btn-primary btn-sm" href="{% url 'modify_func' user_dict.id %}">修改</a>  
    <!--模板语法:动态路由解析-->
    <a class="btn btn-danger btn-sm delete_btn" href={% url "delete_func" user_dict.id %}>删除</a>
    </td>
    </tr>
    {% endfor %}
    </tbody>
    </table>
    </div>
    </div>
    </div>
    </div>
    <script>
        <!--绑定事件给删除按钮,如果确认框选择取消,则阻断重定向-->
        $('a.delete_btn').click(
            function () {
                return confirm("你是否确定删除数据")
            }
        )
    </script>
    </body>
    </html>
    

编写创建数据页

创建数据页会跳转到一个类似于注册界面的页面,我们可以通过表单标签从前端获取数据,然后通过模型类语句向表中插入新的数据。

image

依然需要路由层、视图层、模板层协同:

  • 路由配置

    [path('add_func/', table_crud_views.add_func, name='add_func'),]  # 起个别名
    
  • 视图函数

    def add_func(request):
        # 如果是post请求则说明是注册信息,我们就用模型类语法添加数据
        if request.method == 'POST':
            name = request.POST.get("name")
            password = request.POST.get("password")
            age = request.POST.get("age")
            tel = request.POST.get("tel")
            models.UserData.objects.create(name=name, password=password, age=age, tel=tel)
            # 添加完数据后,我们可以返回首页
            return redirect("http://127.0.0.1:8800")
        # 如果是get请求,那么拿到添加数据界面
        return render(request, "add_data_page.html")
    
  • 前端界面

    <body>
    <div class="container">
        <div class="row">
            <div class="col-md-6 offset-md-3">
                <h1 class="text-center">数据注册页</h1>
                <form action="" method="post">
                name:<input name="name" type="text" class="form-control">
                password:<input name="password" type="password" class="form-control">
                age:<input name="age" type="text" class="form-control">
                tel:<input name="tel" type="text" class="form-control">
                <br>
                <input type="submit" value="提交" class="btn btn-success form-control">
                </form>
            </div>
        </div>
    </div>
    </body>
    

编写数据修改页

编写数据修改页时,我们应该是基于原本的数据进行修改,那么在进入相似的编辑页面时,我们应该对编辑界面做一些参数的区分,可以通过

  • 路由后跟?携带数据的方式,通过request.GET参数进行区分

  • 动态路由+反向解析的方式,让不同记录所对应的编辑链接的路由有区别

    而urls动态解析可以捕捉不同的地方,将其作为参数传入视图函数。

我们选择第二种方式,则需要这么编写:

  • 路由层

    # 在模板中通过模板语法,可以根据记录的id号拼路由,间接传入视图函数
    [path('modify/<str:modify_id>/', table_crud_views.modify_func, name='modify_func'),]
    
  • 视图层

    def modify_func(request, modify_id):
        if request.method == 'POST':
            name = request.POST.get("name")
            password = request.POST.get("password")
            age = request.POST.get("age")
            tel = request.POST.get("tel")
            # 通过传入的函数modify_id可以对对应的数据进行精准修改
            models.UserData.objects.filter(id=modify_id[0]).update(name=name, password=password, age=age, tel=tel)
            return redirect("http://127.0.0.1:8800")
        user_dict = models.UserData.objects.filter(id=modify_id)[0]
        return render(request, 'modify_data_page.html', {"user_dict": user_dict})
    
  • 模板层

    几乎和注册一致

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>modify_page</title>
        <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.bundle.min.js"></script>
    </head>
    <body>
        <div class="container">
        <div class="row">
            <div class="col-md-6 offset-md-3">
                <h1 class="text-center">数据修改页</h1>
                <form action="" method="post">
                    name:<input name="name" type="text" class="form-control" value={{ user_dict.name }}>
                    password:<input name="password" type="password" class="form-control" value={{ user_dict.password }}>
                    age:<input name="age" type="text" class="form-control" value={{ user_dict.age }}>
                    tel:<input name="tel" type="text" class="form-control" value={{ user_dict.tel }}>
                    <br>
                    <input type="submit" value="提交" class="btn btn-success form-control">
                </form>
            </div>
        </div>
    </div>
    </body>
    </html>
    

删除层就不展开讲了,几乎一致。

posted @ 2022-12-11 22:45  leethon  阅读(42)  评论(0编辑  收藏  举报