Django入门到放弃 学习笔记 01

跟b站武沛齐老师的视频学习
对学习过程进行一些记录以便复习 同时自我督促 :D冲鸭

视频链接: 15天django入门到放弃-哔哩哔哩.

回顾

对数据库的操作:pymysql、SQLAlchemy、navicat(终端)

  1. 安装

  2. 创建用户 + 授权

  3. 连接

     - 数据库
     	终端创建数据库(字符编码) 
     - 数据表
     	终端、ORM、pymysql 
     	pymysql:create ...(数据类型/是否可以为空/主键/自增/外键/索引)engine=innodb支持事务性操作
     - 数据行 
     	增、删、改、查
     	查:limit、group by、order by ...
    

    关闭

内容概要

Web框架

  • socket
  • http协议
    连接方式对比
    HTTP:无状态、短连接
    TCP:不断开
  • HTML知识
  • 数据库(pymysql、SQLAlchemy)

Web应用

  • 浏览器(socket客户端)
    ② www.cnblogs.com(42.121.252.58,80)

     sk.socket()
     sk.connect((42.121.252.58,80)
     sk.send('我想要xx')
    

    ⑤ 接受
    ⑥ 连接断开

  • 博客园(socket服务端)
    ① 监听ip和端口(42.121.252.58,80)
    while True:
    – 用户 = 等待用户连接
    – ③ 收到‘我想要xx’
    – ④ 相应:“好”
    用户断开

铺垫练习

s1 简单的byte传输

简单的数据传输。

# -*- coding: utf-8 -*-
import socket


server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
server_socket.bind(('127.0.0.1', 8000))
server_socket.listen(5)

while True:
    client_socket, client_addr = server_socket.accept()  # 阻塞
    data = client_socket.recv(8096)  # 最大接收字节
    response = "HTTP/1.1 200 OK\r\n\r\n"  # 200 表示找到这个资源
    client_socket.send(response.encode('utf8'))
    client_socket.send(b'123123')
    client_socket.send(bytes("hello", encoding='utf-8'))
    client_socket.close()

s2 URL

对接收数据进行分割,提取出URL内容,实现不同URL页面显示不同文字。

# -*- coding: utf-8 -*-
import socket


server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
server_socket.bind(('127.0.0.1', 8000))
server_socket.listen(5)

while True:
    client_socket, client_addr = server_socket.accept()  # 阻塞
    data = client_socket.recv(8096)  # 最大接收字节
    data = str(data, encoding='utf-8')  # 想转成什么就写什么
    headers, bodys = data.split('\r\n\r\n')
    temp_list = headers.split('\r\n')
    method, url, protocal = temp_list[0].split(' ')

    response = "HTTP/1.1 200 OK\r\n\r\n"  # 200 表示找到这个资源
    client_socket.send(response.encode('utf8'))

    if url == "/xxxx":
        client_socket.send(b'123123')
    else:
        client_socket.send(b'404 not found')

    client_socket.close()

s3 静态网站

在s2基础上,将文件作为data返回,实现更复杂的数据传输。
s3.python

# -*- coding: utf-8 -*-
import socket


def f1():
    """
    处理用户请求,并返回相应的内容
    :param request: 用户请求的所有信息
    :return:
    """
    f = open('index.html', 'rb')
    data = f.read()
    f.close()
    return data


def f2():
    f = open('article.html', 'rb')
    data = f.read()
    f.close()
    return data


def f3():
    return b'word'


routers = [
    ('/index', f1),
    ('/article', f2),
    ('/word', f3)
]


def run():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    server_socket.bind(('127.0.0.1', 8000))
    server_socket.listen(5)

    while True:
        client_socket, client_addr = server_socket.accept()  # 阻塞
        data = client_socket.recv(8096)  # 最大接收字节
        data = str(data, encoding='utf-8')  # 想转成什么就写什么
        headers, bodys = data.split('\r\n\r\n')
        temp_list = headers.split('\r\n')
        method, url, protocal = temp_list[0].split(' ')

        response_header = "HTTP/1.1 200 OK\r\n\r\n"  # 200 表示找到这个资源

        func_name = None
        for item in routers:
            if item[0] == url:
                func_name = item[1]
                break

        if func_name:
            response_body = func_name()
        else:
            response_body = b'404'

        client_socket.send(response_header.encode('utf8'))
        client_socket.send(response_body)
        client_socket.close()

if __name__ == '__main__':
    run()

article.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>article</title>
</head>
<body>
    <table>
        <thead>
            <tr>
                <th>ID</th>
                <th>用户名</th>
                <th>邮箱</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th>1</th>
                <th>root</th>
                <th>root@qq.com</th>
            </tr>
        </tbody>
    </table>
</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    <h1>用户登录</h1>
    <form>
        <p><input type="text" placeholder="用户名" /></p>
        <p><input type="password" placeholder="密码" /></p>
    </form>
</body>
</html>

s4 动态网站

修改了 s3.py 中函数 f2()f3(),实现时间的显示和数据库内容的读取。

def f2():
    f = open('time.html', 'r', encoding='utf-8')
    data = f.read()
    f.close()
    import time
    ctime = time.asctime(time.localtime(time.time()))
    data = data.replace('@@time@@', str(ctime))
    return bytes(data, encoding='utf-8')


def f3():
    import pymysql

    conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='db_test')
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 游标设置为字典类型

    cursor.execute("select id, username, password from userinfo")
    user_list = cursor.fetchall()

    conn.commit()
    cursor.close()
    conn.close()
    print(user_list)

    """
    要替换html文件中的@@content@
    将数据库中读取的数据改写为格式如:
    <tr>
        <th>id</th>
        <th>username</th>
        <th>password</th>
    </tr>
    """
    content_list = ""
    for row in user_list:
        tp = "<tr><td>%s</td><td>%s</td><td>%s</td></tr>" %(row['id'], row['username'], row['password'])
        content_list += tp
    content = "".join(content_list)

    f = open('userlist.html', 'r', encoding='utf-8')
    template = f.read()
    f.close()

    data = template.replace('@@content@@', content)
    return bytes(data, encoding='utf-8')

time.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>article</title>
</head>
<body>
    <h1>@@time@@</h1>
</body>
</html>

userlist.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>article</title>
</head>
<body>
    <table>
        <thead>
            <tr>
                <th>ID</th>
                <th>用户名</th>
                <th>密码</th>
            </tr>
        </thead>
        <tbody>
            @@content@@
        </tbody>
    </table>
</body>
</html>

过渡性总结

自己写网站

  • a. socket服务端
  • b. 根据URL不同返回不同的内容
    路由系统:URL -> 函数
  • c. 字符串返回给用户
    模板引擎渲染:HTML充当模板(特殊字符)、自己创造任意数据

Web框架

框架种类:

  • abc
    Tornado
  • [第三方a]+bc
    Django (应用python中wsgiref模块)
  • [第三方ac]+b
    flask(wsgiref、jinja2)

分类:

  • Django
  • 其他(轻量级框架)

Django入门

创建项目

基本指令:
安装:pip3 install django

django-admin startproject mysite
若没有添加环境变量,要在路径下执行。

其他常用命令:

python manage.py runserver ip:port (启动服务器,默认ip和端口为http://127.0.0.1:8000/)
python manage.py startapp appname (新建 app)
python manage.py syncdb (同步数据库命令,Django 1.7及以上版本需要用以下的命令)
python manage.py makemigrations (显示并记录所有数据的改动)
python manage.py migrate (将改动更新到数据库)
python manage.py createsuperuser (创建超级管理员)
python manage.py dbshell (数据库命令行)
python manage.py (查看命令列表)

项目建立完成得到如下文件夹:

mysite
├─── manage.py # 运行
└─── mysite
┈ ┈ ┈ ┈├─── __init__.py
┈ ┈ ┈ ┈├─── settings.py # 基本配置
┈ ┈ ┈ ┈├─── urls.py # 路由系统 url -> 函数
┈ ┈ ┈ ┈└─── wsgi.py # Web服务器网关接口 调用wsgiref模块 实现socket

基础配置

urls.py 文件中,urlpatterns 列表中增加路径;
引入 HttpResponse 模块,login 函数的返回值以此形式传递;
引入 HttpResponse 模块,可以读取其他文件,如 login.html 作为返回值。

from django.contrib import admin
from django.urls import path

from django.shortcuts import HttpResponse, render

def login(request):
    """
    处理用户请求,并返回内容
    :param request: 用户请求相关的所有信息(对象)
    :return:
    """
    # return HttpResponse('login')
    # 自动找到模板路径下的login.html文件,读取内容并返回给用户
    return render(request, 'login.html')


urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', login),
]

寻找文件的路径依据,在 settings.pyTEMPLATES 里进行了定义:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ...

templates 文件夹中的 login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
</head>
<body>
    <h1 style="color: cadetblue">用户登录</h1>
    <form>
        <p><input type="text" placeholder="用户名" /></p>
        <p><input type="password" placeholder="密码" /></p>
        <p><input type="submit" value="登录"></p>
    </form>
</body>
</html>

运行可看到页面:

也可以将样式写入CSS文件中,修改 login.html,加入样式链接:

<link rel="stylesheet" href="/sta/commons.css">

sta 文件夹下新建 commons.css 文件:

h1{
    color: cadetblue;
}

运行发现样式未应用,检查报错,发现CSS文件未能被找到;

原因是静态文件路径需要配置,在 setting.py 中最后修改静态路径:

STATIC_URL = '/static/' # 使用时前缀 /static
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'sta'),
)

修改 login.html 中的链接:

<link rel="stylesheet" href="/static/commons.css">

再运行时,样式应用成功。

*将 sta 文件夹直接命名未 static 更加和谐统一,日后将所有静态文件放在 static 目录下。
(静态文件:图片、JS、CSS)

完善登录功能

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link rel="stylesheet" href="/static/commons.css">
</head>
<body>
    <h1>用户登录</h1>
    <form method="post" action="/login/">
        <p><input type="text" placeholder="用户名" name="username"/></p>
        <p><input type="password" placeholder="密码" name="password"/></p>
        <p><input type="submit" value="登录"></p>
        {{ msg }}
    </form>
</body>
</html>

这里用户端返回的消息形式:<QueryDict: {'username': ['root'], 'password': ['123123']}>
urls.py

def login(request):
    """
    处理用户请求,并返回内容
    :param request: 用户请求相关的所有信息(对象)
    :return:
    """
    # return HttpResponse('login')
    # 自动找到模板路径下的login.html文件,读取内容并返回给用户
    if request.method == "GET":
        return render(request, 'login.html', {'msg': '请输入用户名和密码'})
    else:
        # 用户POST提交的数据(请求体)
        """
        usr = request.POST['username']
        psw = request.POST['password']
        这样的方式并不好,取决于html文件中的name,如果不匹配会报错
        """
        usr = request.POST.get('username')
        psw = request.POST.get('password')
        if usr == 'bernie' and psw == '123456':
            # 登录成功
            return redirect('http://www.baidu.com')
        else:
            # 登录失败
            return render(request, 'login.html', {'msg': '用户名或密码错误'})

首次访问,请求形式为 GET,将登录界面返回给用户;用户输入用户名和密码后,请求形式为 POST,则进行判断,登录成功则借助 redirect 重定位跳转到指定网址;否则重新将登录界面返回给用户,并给出错误提示信息。

总结

1. 创建project

2. 配置

模板路径 - templates目录
静态文件路径 - static目录

3. 额外配置

MIDDLEWARE'django.middleware.csrf.CsrfViewMiddleware', 注释掉

4. url对应关系

/login/ login

def login(request):

– request.method
– request.POST ->请求体
– request.GET ->请求头中的url中
(GET请求:只有request.GET有值;POST请求:request.GET和request.POST都可能有值)

– return HttpResponse(…)
– return render(request, ‘login.html’, {…})
– return redirect(‘要跳转的网址’或’/后缀/’)

5. 模板引擎的特殊标记

login.html
{{name}}

def login(request):
return render(request, ‘login.html’, {‘name’: ‘alex’})

html文件中的引用:

<p>{{ name }}</p>
<p>{{ users.0 }}</p>
<p>{{ users.1 }}</p>
<p>{{ user_dict.k1 }}</p>
<p>{{ user_dict.k2 }}</p>
<h3>循环</h3>
<ul>
{% for item in users %}
	<li> {{ item }} </li>
{% endfor %}
</ul>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值