Django

📒 笔记 · 2023-12-20

Django是一个开源的、用于构建Web应用程序的高级Python Web框架。


安装

pip install django

创建项目

Django中项目会有一些默认的文件和默认的文件夹

在项目文件夹下运行,生成默认文件:

D:\Anaconda3\envs\DPlearning\Scripts\django-admin.exe startproject 项目名
添加到系统环境变量后可以不用输入路径。

默认文件介绍

默认生成的文件:

  • manager.py:项目的管理、启动项目、创建app、数据管理【不需要修改】
  • 与项目同名的文件夹

    • asgi.py: 接收网络请求(异步请求)【不需要修改】
    • wsgi.py: 接收网络请求(同步请求)【不需要修改 】
    • urls.py: URL和函数的对应关系【经常操作】
    • settting.py: 项目配置文件。【会操作,连接数据库等配置】

app的创建和说明

一般情况下,项目下创建一个app即可。

项目目录下运行python manage.py startapp app01会生成app01文件夹。

├─app01
│  │  admin.py      【固定,不用动】 django默认提供的后台管理
│  │  apps.py       【固定,不用动】 app的启动类
│  │  models.py     【重要】 对数据库进行操作。不需要再用pymysql了。
│  │  tests.py      【固定,不用动】 单元测试
│  │  views.py      【重要】 函数
│  │  __init__.py
│  │
│  └─migrations         【固定,不用动】 数据库变更记录
│          __init__.py
│
└─mydjango
    │  asgi.py
    │  settings.py
    │  urls.py
    │  wsgi.py
    └─ __init__.py

快速上手

  • 确保app已注册:\mydjango\settings.py中的INSTALLED_APPS增加'app01.apps.App01Config'app01改成自己新建的app的名称
  • 编写URL和视图函数对应关系urls.py
  • 编写视图函数view.py
  • 启动django项目。命令行启动:python manage.py runserver

templates

def user_list(request):
    # 去app01下的templates下的user_list.html。根据app的注册顺序去找templates下的user_list.html
    return render(request,'user_list.html')

def user_add(request):
    return render(request,'user_add.html')

静态文件

在开发过程中,一般将:

  • 图片
  • css
  • js

都会当作静态文件处理。

django中,一般将静态文件放在app目录下的static中。

  • 在app目录下创建static文件夹
  • 顶部{% load static %},引入静态文件。<link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}" />,<script src="{% static 'js/jquery-3.7.1.min.js' %}"></script>

模板语法

本质上:在html中写一些占位符,由数据对这些占位符进行替换和处理。

当浏览器访问时,先访问utls.py,然后跳转到views.py函数,函数的render方法将含模板语法的html转换为标准的html传给浏览器,最后浏览器读取标准html解析并显示。

  1. 单独一个值用花括号{}
def tpl(request):
    name = "韩超"
    return render(request,'tpl.html',{"n1":name})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TPL</title>
</head>
<body>
    <h1>TPL</h1>
    <div>{{ n1 }}</div>
</body>
</html>
  1. 列表(元组)的索引
 <!-- 列表的第一个索引 -->
    <div>{{ n2.0 }}</div>   
    <!-- 列表的第二个索引 -->
    <div>{{ n2.1 }}</div>
    <!-- 列表的第三个索引 -->
    <div>{{ n2.2 }}</div>
  1. 循环
{% for item in n2 %}
            <span>{{item}}</span>
        {% endfor %}
  1. 字典
<!-- 字典的获取 -->
{{ n3 }}
{{ n3.name }}
{{ n3.salary }}
{{ n3.role }}

 <!-- 获取所有的键 -->
{% for item in n3.keys %}
<li>{{ item }}</li>
{% endfor %}

 <!-- 获取所有的键值 -->
{% for item in n3.values %}
<li>{{ item }}</li>
{% endfor %}

<!-- 获取键值对 -->
{% for k,v in n3.items %}
<li>{{ k }} = {{ v }}</li>
{% endfor %}
  1. 列表里嵌套字典:[{},{},{}]
{{ n4.1.name }}
{{ n4.1.salary }}
{{ n4.1.role }}

{{ n4.2.name }}
{{ n4.2.salary }}
{{ n4.2.role }}

{% for item in n4 %}
    <div>
        {{ item.name }}
        {{ item.salary }}
        {{ item.role }}
    </div>
{% endfor %}
  1. if语句
{% if n1 == "韩超" %}
    <h1>NB</h1>
{% elif n1 == "XxX" %}
    <h1>HH</h1>
{% else %}
    <h1>SB</h1>
{% endif %}

案例:伪联通新闻中心

def news(request):
    # 1. 获取联通新闻的数据
    urls = "https://www.chinaunicom.com.cn/api/article/NewsByIndex/2/2023/12/news"
    # 2. 解析数据
    res = requests.get(urls,headers={"User-Agent":"Mozilla/5.0"})
    data_list = res.json()
    # 3. 获取数据
    return render(request,'news.html',{"news_list":data_list})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>联通新闻中心</title>
</head>
<body>
    <h1>联通新闻中心</h1>
    <ul>
        {% for item in news_list %}
        <li>{{item.news_title}} 时间: {{item.post_time}}</li>
        {% endfor %}
    </ul>
</body>
</html>

效果:

image

请求和相应

def qingqiuxiangying(req):
    # request是一个对象,包含了请求的所有信息

    # 1. 获取请求的方式 GET/POST
    print(req.method)

    # 2. 在URL上传递值:/request/?name=韩超&age=18
    print(req.GET)

    # 3. 在请求体中提交数据
    print(req.POST)

    # 4. 【响应】 HttpResponse。字符串和内容返回给请求者
    # return HttpResponse('请求和响应')

    # 5. 【响应】 render。渲染模板文件,返回给请求者
    # return render(req,'request.html')

    # 6. 【响应】 redirect。重定向,返回给请求者。
    return redirect('https://www.baidu.com')

案例:用户登录

Django默认要求在处理POST请求时包含CSRF令牌。确保您的表单包含{% csrf_token %}标签
def login(request):
    # 如果是get请求,返回登录页面
    if request.method == "GET":
        return render(request,'login.html')
    else:
        # 如果是post请求
        # print(request.POST)
        username = request.POST.get('user')
        password = request.POST.get('pwd')
        if username == 'admin' and password == '123':
            # 登录成功
            return redirect("https://www.chinaunicom.com.cn")
        else:
            # 登录失败
            error_msg = '用户名或密码错误'
            # return HttpResponse('登录失败')
            return render(request,'login.html',{'error_msg':error_msg})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户登录</title>
</head>
<body>
    <h1>用 户 登 录</h1>
    <form method="post" action="/login">
        
        <!-- 表单验证(加在form表单里面) -->
        {% csrf_token %}

        <input type="text" name="user" placeholder="用户名">
        <input type="password" name="pwd" placeholder="密码">
        <input type="submit" value="提交" /> 
        <span style="color: red;">{{ error_msg }}</span>
    </form>
</body>
</html>

数据库操作--ORM框架

Flask中一般用pymysql操作数据库,但是django中已经提供了数据库工具--ORM框架。
  • ORM对pymysql等库进行了封装,所以使用起来更简洁。

Django最新版本对pymysql支持一般,所以建议安装mysqlclient。如果安装失败就下载whl包离线安装。

pip install mysqlclient

ORM可以实现:

  • 创建和修改数据库中的(不用再写sql语句)。【无法创建数据库】
  • 操作表中的数据(不用再写sql语句)

操作数据库中的表

  1. 创建数据库
  • 启动mysql服务
  • 自带工具创建数据库
  1. 修改django设置文件settings.py,将DATABASES改为mysql数据库引擎。
DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.mysql',    # 数据库引擎
        'NAME': 'xxx',   # 数据库名
        'USER': 'xxx',     # 用户名
        'PASSWORD': 'xxxx', # 密码
        'HOST':'127.0.0.1',     # 主机
        'PORT': '3306',         # 端口
        }
}
  1. 使用django操作数据库中的表
  • 创建表
  • 删除表
  • 修改表

打开models.py文件,写入以下内容:

from django.db import models

# Create your models here.
class UserInfo(models.Model):
    '''
    create table app01_userinfo(
        id bigint primary key auto_increment,
        name varchar(32),
        password varchar(64),
        age int
    )
    '''
    # 上述sql语句的python代码实现
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    age = models.IntegerField()
必须确保已经注册app

然后执行命令:

python manage.py makemigrations
python manage.py migrate

sql命令查看数据库中创建的表

mysql> show tables;
+----------------------------+
| Tables_in_unicom           |
+----------------------------+
| app01_userinfo             |
| 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             |
+----------------------------+
11 rows in set (0.00 sec)     

能看到创建了11个表。其中后面十个是默认生成的表(按照setting.py中的INSTALL_APPS的设置自动创建的。后期不需要可以删除)

如果想删除某个表,可以删除models.py中的特定的类,然后重新执行:

python manage.py makemigrations
python manage.py migrate

如果想增加表,就在models.py中新建类,再执行命令。

如果想在表中新增列,那么就在对应的class里新增创建列的代码。然后重新运行命令。终端中会提示两个选择:1 or 2。

其中:1代表。提供一次性默认值列中每个值都用你提供的默认值(将在该列具有空值的所有现有行上设置)。2代表退出并在 models.py 中手动定义默认值。

  • 手动输入一个值
  • 设置默认值:age = models.IntegerField(default=2)
  • 允许为空:data = models.IntegerField(null=True, blank=True)

以后在开发中如果想要对表结构进行调整:

  • models.py文件中操作类即可
  • 两条命令更新表结构
python manage.py makemigrations
python manage.py migrate

操作表中的数据

  • 增加数据
UserInfo.objects.create(name='alex', password='123', age=18)
  • 删除数据
UserInfo.objects.filter(name='alex').delete()
    UserInfo.objects.all().delete() # 删除所有数据
  • 获取数据
data_list = UserInfo.objects.all()  # 获取所有数据,得到一个列表[对象1,对象2,对象3...]
for obj in data_list:
    print(obj.name,obj.password,obj.age)    # 获取每一行的数据

# 获取单条数据
UserInfo.objects.filter(id=1)  # 得到数据[对象1,]
data = UserInfo.objects.filter(id=1).first()   # 获取id=1的数据,得到一行数据[对象]
print(data.name,data.password,data.age)
  • 更新数据
UserInfo.objects.filter(name='alex').update(age=19)
UserInfo.objects.all().update(age=19)

案例:用户管理

  1. 展示用户列表
  • url
  • 函数

    • 获取所有用户信息
    • HTML渲染
from app01.models import UserInfo
def info_list(request):
    # 获取所有数据
    data_list = UserInfo.objects.all()
    for obj in data_list:
        print(obj.name,obj.password,obj.age)
    
    return render(request,'info_list.html',{'data_list':data_list})
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户列表</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
</head>
<body>
    <h1 class="page-header">Info列表</h1>
    <table class="table table-hover">
        <thead>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>密码</th>
                <th>年龄</th>
            </tr>
        </thead>
        <tbody>
            {% for obj in data_list %}
            <tr>
                <td>{{ obj.id }}</td>
                <td>{{ obj.name }}</td>
                <td>{{ obj.password }}</td>
                <td>{{ obj.age }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</body>
</html>
  1. 添加用户
  • url
  • 函数

    • GET
    • POST
from app01.models import UserInfo
def info_add(req):
    if req.method == "GET":
        return render(req,'info_add.html')
    
    username = req.POST.get('user')
    password = req.POST.get('pwd')
    age = req.POST.get('age')
    UserInfo.objects.create(name=username,password=password,age=age)
    return redirect('/info/list')
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>增加用户</h1>
    <form method="post">
        {% csrf_token %}
        <input type="text" name="user" placeholder="用户名">
        <input type="text" name="pwd" placeholder="密码">
        <input type="text" name="age" placeholder="年龄">
        <input type="submit" value="提 交">
    </form>
</body>
</html>
  1. 删除用户
def delete(req):
    # 获取要删除的id
    nid = req.GET.get('nid')
    # 根据id删除数据
    UserInfo.objects.filter(id=nid).delete()
    return HttpResponse('删除成功')

项目:员工管理系统

Python Django
Theme Jasmine by Kent Liao