Django
1. 再写N个页面
- url -> 函数
- 函数
urlpatterns = [
    # path('admin/', admin.site.urls),
    # www.xxx.com/index/    -> 函数
    path('index/', views.index),
    path('user/list/', views.user_list),
    path('user/add/', views.user_add),
]
from django.shortcuts import render,HttpResponse
# Create your views here.
def index(request):
    return HttpResponse("hello world")
def user_list(request):
    return HttpResponse("用户列表")
def user_add(request):
    return HttpResponse("添加用户")
2. templates模板
def user_list(request):
    # 1. 默认去APP目录下的templates目录寻找user_list.html
    # (根据APP的注册顺序,逐一去他们的templates目录中寻找)
    # 2. 如果在settings.py中配置了'DIRS': [os.path.join(BASE_DIR,'templates')],(需要提前在settings.py中配置,不配置就是无效)
    # (则会去项目根目录中的templates目录中寻找user_list.html)
    # (如果寻找不到,则会根据APP的注册顺序,就会在每个APP下的templates目录中寻找)
    return render(request, "user_list.html")
3. 静态文件
在开发过程中一般将:
- 图片
 - CSS
 - JS
 - 第三方插件等
 
都会当做静态文件处理
3.1 static目录
- 在APP目录下创建static文件夹
 - 引用静态文件
 
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1-dist/css/bootstrap.css' %}">
    
</head>
<body>
    <h1>用户列表</h1>
    <input type="text" class="btn btn-primary" value="新建">
    <img src="{% static 'img/fm_33.jpg' %}" style="height: 100%; width: 100%;">
    <script src="{% static 'js/jquery-3.7.1.min.js' %}"></script>
    <script src="{% static 'js/plugins/bootstrap-3.4.1-dist/js/bootstrap.js' %}"></script>
</body>
</html>
4. 模板语法
- 本质上:在HTML中写一些占位符,由数据对这些占位符进行替换和处理
 
> 视图函数render内部
1. 读取含有模板语法的HTML文件
2. 内部进行渲染(模板语法并执行替换数据)
- 最终得到,只包含HTML标签的字符串
3. 将渲染(替换)完成的HTML返还给用户浏览器
def tpl(request):
    name = '111'
    roles = ['管理员', '队长', '小组长', '保安']
    user_info = {'name':'果汁', 'salary': 10000, 'role': 'CTO'}
    data_list = [
        {'name':'果汁', 'salary': 10000, 'role': 'CTO'},
        {'name':'芦荟', 'salary': 22222, 'role': 'CEO'},
        {'name':'水果', 'salary': 33333, 'role': 'CFO'},
    ]
    return render(
        request,
        "tpl.html",
        {
            'n1': name,
            'n2': roles,
            'n3': user_info,
            'n4': 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</title>
</head>
<body>
    <h1>模板语法的学习</h1>
    <div>{{ n1 }}</div>
    <div>{{ n2 }}</div>
    <div>{{ n2.0 }}</div>
    <div>{{ n2.1 }}</div>
    <div>{{ n2.2 }}</div>
    <div>{{ n2.3 }}</div>
    <div>
        {% for item in n2 %}
            {{item}}
        {% endfor %}
    </div>
    <hr/>
    <hr/>
    {{ n3 }}
    {{ n3.name }}
    {{ n3.salary }}
    {{ n3.role }}
    <ul>
        {% for item in n3.keys %}
            
                {{ item }}
             
        {% endfor %}
    </ul>
    <ul>
        {% for item in n3.values %}
            
                {{ item }}
             
        {% endfor %}
    </ul>
    <ul>
        {% for k,v in n3.items %}
            
                {{ k }} = {{ v }}
             
        {% endfor %}
    </ul>
    <hr/>
    <hr/>
    {{ n4.0 }}
    {{ n4.1.name }}
    {{ n4.0.role }}
    {% for item in n4 %}
        {{ item.name }} / {{ item.salary }}
    {% endfor %}
    <hr/>
    <hr/>
    {% if n1 == "韩超" %}
        
    {% elif n1 == "111" %}
        
    {% else %}
        
    {% endif %}
</body>
</html>
案例:伪联通新闻中心
urlpatterns = [
    # path('admin/', admin.site.urls),
    # www.xxx.com/index/    -> 函数
    path('index/', views.index),
    path('user/list/', views.user_list),
    path('user/add/', views.user_add),
    path('tpl/', views.tpl),
    path('news/', views.news),
]
def news(request):
    # 1. 定义一些新闻(列表/字典); 或 数据库 或 爬虫爬取数据
    # 向http://www.chinaunicom.com.cn/api/article/NewsByIndex/2/2023/09/news发送请求
    # 第三方模块:requests
    headers = {'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"}
    url = 'http://www.chinaunicom.com.cn/api/article/NewsByIndex/2/2023/09/news'
    res = requests.get(headers=headers, url= url)
    data_list = res.json()
    # print(data_list)
    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>Document</title>
</head>
<body>
    <h1>联通新闻中心</h1>
    <ul>
        {% for item in news_list %}
            {{ item.news_title }} 时间:{{ item.post_time }} 
        {% endfor %}
        <hr/>
        <li>{{ news_list.1.news_title }}</li>
        <li>{{ news_list.2.news_title }}</li>
        <li>{{ news_list.3.news_title }}</li>
    </ul>
</body>
</html>
5. 请求和响应
    # 请求和响应
    path('something/', views.something),
def something(request):
    # request是一个对象,内部封装了用户发送过来的所有数据
    # 1.获取请求方式
    print(request.method)
    # 2.在URL上传递一些参数值 something/?n1=123&n2=999
    print(request.GET)
    # 3.在请求体中提交数据
    print(request.POST)
    # 【响应】4.将字符串内容返回给请求者 HttpResponse("返回内容")
    # return HttpResponse("返回内容")
    # 【响应】5.读取HTML内容 + 渲染(替换) -> 返还给用户,浏览器
    # return render(request, "something.html", {"title": "你干嘛?"})
    # 【响应】6.让浏览器重定向到其他页面(将内容返还给浏览器,让浏览器自己去重新请求对应的地址)
    return redirect("https://www.baidu.com")
案例:用户登录
def login(request):
    if request.method =="GET":
        return render(request, "login.html")
    elif request.method == "POST":
        # 如果是POST请求,获取用户提交的数据,并进行验证
        # print(request.POST)
        username = request.POST.get("user")
        password = request.POST.get("pwd")
        if username == "root" and password == "123":
            return redirect("http://www.chinaunicom.com.cn/index.html")
        else:
            return render(request, 'login.html', {"error_msg":"登录失败,请检查用户名或密码是否输入错误"})
# 上述代码简化
def login(request):
    if request.method =="GET":
        return render(request, "login.html")
    # 如果是POST请求,获取用户提交的数据,并进行验证
    # print(request.POST)
    username = request.POST.get("user")
    password = request.POST.get("pwd")
    if username == "root" and password == "123":
        return redirect("http://www.chinaunicom.com.cn/index.html")
    return render(request, 'login.html', {"error_msg":"登录失败,请检查用户名或密码是否输入错误"})
<!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 action="/login/" method="post">
        {% 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>
6. Python直接操作数据库
- MySQL数据库 + pymysql
 
import pymysql
# 1. 链接MySQL
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',password='root123',db='unicom',charset='utf8')
# 创建游标对象
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 2. 发送指令
cursor.execute("insert into admin(username,password,mobile) values('徐泽林','123456','13100204183')")
conn.commit()
# 3. 关闭连接
cursor.close()
conn.close()
- Django开发操作数据库更简单,内部提供了ORM框架
 
ORM —> pymysql、MySQLdb、mysqlclient
6.1 安装第三方模块
pip install mysqlclient
6.2 ORM
- ORM可以帮助我们做两件事:
- 创建、修改、删除数据库中的表(不用写SQL语句)【无法创建数据库】
 - 操作表中的数据(不用写SQL语句)
 
 
6.2.1 创建数据库
- 启动MySQL服务
 - 自带工具创建数据库
 
show databases;
create database 数据库名称 DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
6.2.2 Django连接数据库
- 在settings.py文件中进行配置和修改
 
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",   # 数据库类型
        "NAME": "djangotest02",                 # 数据库名称
        "USER": "root",                         # 用户名
        "PASSWORD": "root123",                  # 密码
        "HOST": "127.0.0.1",                    # 主机
        "PORT": "3306",                         # 端口
    }
}
6.2.3 Django操作表
- 创建表:在models.py文件中
 
class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    age = models.IntegerField()
    
"""
create table app01_userinfo{
    id bigint auto_increment primary key,
    name varchar(32),
    password varchar(64),
    age int
}
"""
# 提交数据库变更(需要APP提前注册)
python manage.py makemigrations
python manage.py migrate
在表中新增列时,由于已存在的列中可能已有数据,所以新增列必须要指定新增列对应的数据
手动输入一个值
Please select a fix: 1) Provide a one-off default now (will be set on all existing rows with a null value for this column) 2) Quit, and let me add a default in models.py Select an option: 1 Please enter the default value now, as valid Python The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now Type 'exit' to exit this prompt >>> 1设置默认值
age = models.IntegerField(default=2)允许为空
data = models.IntegerField(null=True, blank=True)
以后在开发中如果想要对表结构进行调整
- 在models.py文件中操作类即可
 - 通过命令提交变更表结构
 
python manage.py makemigrations python manage.py migrate
6.2.4 操作表中的数据
# from app01 import models
from app01.models import Department, UserInfo
def orm(request):
    # 测试ORM操作表中的数据
    # models.Department
    ########## 1.新建数据 ##########
    # Department.objects.create(title="销售郁")
    # Department.objects.create(title="产品部")
    # Department.objects.create(title="IT部")
    # Department.objects.create(title="运营部")
    # UserInfo.objects.create(name="林泽徐", password="123", age=19)
    # UserInfo.objects.create(name="诺手", password="666")
    # UserInfo.objects.create(name="德玛西亚", password="789456123")
    ########## 2.删除数据 ##########
    # UserInfo.objects.filter(id=1).delete()
    # Department.objects.all().delete()
    ########## 3.查找数据 ##########
    # 3.1 获取符合条件的所有数据
    # [行对象,行对象,行对象]  QuerySet类型
    # data_list = UserInfo.objects.all()
    # for obj in data_list:
    #     print(obj.id, obj.name, obj.password, obj.age)
    # data_list = [对象,]
    # data_list = UserInfo.objects.filter(id=2)
    # print(data_list)
    # 3.2 获取第一条数据,返回一个对象
    # row_obj = UserInfo.objects.filter(id=2).first()
    # print(row_obj.id, row_obj.name, row_obj.password, row_obj.age)
    ########## 4.修改数据 ##########
    # UserInfo.objects.all().update(password="XXXXXX")
    # UserInfo.objects.filter(id=2).update(age="999")
    # UserInfo.objects.filter(name="123").update(age="999")
    return HttpResponse("orm成功")
6.3 案例:用户管理
- 展示用户列表
 
- URL
 - 函数
- 获取所有用户信息
 - HTML渲染
 
 
def info_list(request):
    # 1. 获取数据库中所有的用户信息
    # [对象, 对象, 对象, ...]
    data_list = UserInfo.objects.all()
    return render(request, "info_list.html", {"data_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>Document</title>
</head>
<body>
    <h1>INFO列表</h1>
    <a href="/info/add/">添加</a>
    <table border="1px">
        <thead>
            <tr>
                <th>ID</th>
                <th>姓名</th>
                <th>密码</th>
                <th>年龄</th>
            </tr>
        </thead>
        <tbody>
            {% for obj in data_list %}
                
                    {{ obj.id }} 
                    {{ obj.name}} 
                    {{ obj.password}} 
                    {{ obj.age }} 
                 
            {% endfor %}
        </tbody>
    </table>
</body>
</html>
- 添加用户
 
- URL
 - 函数
- GET,看到页面,输入内容
 - POST,提交 -> 写入到数据库
 
 
def info_add(request):
    if request.method == "GET":
        return render(request, 'info_add.html')
    # 获取用户提交的数据
    username = request.POST.get("user")
    password = request.POST.get("password")
    age = request.POST.get("age")
    # 添加到数据库
    UserInfo.objects.create(name=username, password=password, age=age)
    # 自动跳转至列表页面
    # return redirect("http://127.0.0.1:8000/info/list/")
    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="password" name="password" placeholder="请输入密码">
        <input type="text" name="age" placeholder="请输入年龄">
        <input type="submit" value="添加用户">
    </form>
</body>
</html>
- 删除用户
 
- URL
 - 函数
 
http://127.0.0.1:8000/info/delete/?nid=1
http://127.0.0.1:8000/info/delete/?nid=2
def 函数(request):
    nid = request.GET.get("nid")
    UserInfo.objects.filter(id=nid).delete()
    return HttpResponse("删除成功")