【学習ノート】Python Web開発ファミリーバケット2

ウェブサイトについて知る

  • デフォルトで書き込まれる静的エフェクト
  • 動的:Webフレームワークの機能が必要です。
    ここに画像の説明を挿入
    現在、データ ストレージに使用できるものは次のとおりです。
  • txtファイル
  • エクセルファイル
  • プロフェッショナル ソフトウェア: データベース管理システム
    MySQL/Oracle/SQLServer/DB2/Access...
    ここに画像の説明を挿入

7 MysQL

7.1 MySQL のインストール

MySQL は本質的にはソフトウェアです。

  • 8.x
  • 5.x
    わずかに

7.2 MySQLの起動

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

7.3 MySQLコマンド

7.3.1 データベース管理(フォルダー)

ここに画像の説明を挿入

7.3.2 データシート(ファイル)の管理

やや
チャー、速い。varchar、スペースを節約します。

7.4 例: 従業員管理

ここに画像の説明を挿入

7.4.2 MySQLを操作するためのPython

接続を作成し、カーソルを作成し、カーソルを実行して SQL ステートメントを実行してから切断します。

import pymysql

# 1.连接MySQL
conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="xxxx", charset="utf8", db='unicom')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)


# 2.发送指令
cursor.execute("insert into admin(username, password, mobile) values('张三', 'qwe123', '155555')")
conn.commit()

# 3.关闭连接
cursor.close()
conn.close()

SQL を動的に実行します。SQL スプライシングを行うために文字列フォーマットを使用しないでください。セキュリティ リスクが発生します。 SQL インジェクション

sql = "insert into admin(username, password, mobile) values(%s, %s, %s)"
cursor.execute(sql, ["李四", "qwe123", "1999999"])

sql = "insert into admin(username, password, mobile) values(%(n1)s, %(n2)s, %(n3)s)"
cursor.execute(sql, {
    
    "n1": "王五",  "n2": "qwe123", "n3": "1999999"})
conn.commit()
  • data
    fetchall をクエリしてすべてのデータを取得します。
    fetchone で条件を満たす最初のデータを取得します。
import pymysql

# 1.连接MySQL
conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="xxxxx, charset="utf8", db='unicom')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

# 2.发送指令
sql = "select * from admin where id > 2 "
cursor.execute(sql)
datalist = cursor.fetchall()
for row_dict in datalist:
    print(row_dict)

# 3.关闭连接
cursor.close()
conn.close()

ここに画像の説明を挿入

8. ケース: Flask+MySQL

ここに画像の説明を挿入

from flask import Flask, render_template, request
import pymysql

app = Flask(__name__)

@app.route("/add/user", methods=["GET", "POST"])
def add_user():
    if request.method == "GET":
        return render_template("add_user.html")

    username = request.form.get("user")
    password = request.form.get("pwd")
    mobile = request.form.get("mobile")

    # 1.连接MySQL
    conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", password="xxxx", charset="utf8", db="unicom")
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 2.执行SQL
    sql = "insert into admin(username, password, mobile) values(%s, %s, %s)"
    cursor.execute(sql, [username, password, mobile])
    conn.commit()
    # 3.关闭连接
    cursor.close()
    conn.close()

    return "添加成功"


@app.route("/show/user")
def show_user():
    # 1.连接MySQL
    conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", password="xxxx", charset="utf8", db="unicom")
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    # 2.执行SQL
    sql = "select * from admin"
    cursor.execute(sql)
    data_list = cursor.fetchall()
    # 3.关闭连接
    cursor.close()
    conn.close()

    print(data_list)
    return render_template("show_user.html", data_list=data_list)


if __name__ == '__main__':
    app.run()

9 イニシャルジャンゴ

9.1 ジャンゴをインストールする

インストール後、django-amin.exe と django モジュールが作成されます。
ここに画像の説明を挿入

9.2 プロジェクトの作成

9.2.1 ターミナル内

ここに画像の説明を挿入

9.2.2 Pycharm

わずかに
ここに画像の説明を挿入
ここに画像の説明を挿入

9.3 アプリ

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

9.4 クイックスタート

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

9.4.1 別のページを書く

ここに画像の説明を挿入

9.4.2 テンプレート

ここに画像の説明を挿入

9.4.3 静的ファイル

ここに画像の説明を挿入
ここに画像の説明を挿入

9.5 テンプレートの構文

ここに画像の説明を挿入

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <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>
    {% for item in n2 %}
        <span>{
   
   { item }}</span>
    {% endfor %}
</div>
<hr/>
<div>{
   
   { n3 }}</div>

<div>{
   
   { n3.name }}</div>
<div>{
   
   { n3.salary }}</div>
<div>{
   
   { n3.role }}</div>

<div>
    {% for k, v in n3.items %}
        <li>{
   
   { k }} = {
   
   { v }}</li>
    {% endfor %}
</div>
<hr>
{
   
   { n4.1 }}
{
   
   { n4.1.name }}
{% for item in n4 %}
    <div>{
   
   { item.name }}{
   
   { item.salary }}</div>
{% endfor %}

<hr>
{% if n1 == "韩超" %}
    <h1>哒哒哒</h1>
{% else %}
    <h1>嘟嘟嘟</h1>
{% endif %}

{% if n1 == "韩超" %}
    <h1>哒哒哒</h1>
{% elif n1 == "xxx" %}
    <h1>bibibi</h1>
{% else %}
    <h1>嘟嘟嘟</h1>
{% endif %}
</body>
</html>

事例:擬似ユニコムニュースセンター

クローラーが動画报错:Expecting value: line 1 column 1 (char 0)を参照できる場合

def news(request):
    import requests
    # 请求头添加浏览器信息
    headers = {
    
    
        'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    }
    url = "http://www.chinaunicom.com.cn/api/article/NewsByIndex/2/2023/06/news"
    res = requests.get(url, headers=headers)

    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">
    <title>Title</title>
</head>
<body>
<h1>联通新闻中心</h1>
<ul>
    {% for item in news_list %}
        <li>{
   
   { item.news_title }} 时间: {
   
   { item.post_time }} </li>
    {% endfor %}
</ul>
</body>
</html>

9.6 リクエストとレスポンス

from django.shortcuts import render, HttpResponse, redirect


def index(request):
    return HttpResponse("欢迎使用")


def user_list(request):
    return render(request, "user_list.html")


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


def tpl(request):
    name = "韩超发方法"
    roles = ["管理员", "CEO", "保安"]
    user_info = {
    
    "name": "张三", "salary": 10000, "role": "CTO"}
    data_list = [
        {
    
    "name": "张三", "salary": 10000, "role": "CTO"},
        {
    
    "name": "李四", "salary": 10000, "role": "CTO"},
        {
    
    "name": "王五", "salary": 10000, "role": "CTO"},
    ]
    return render(request, "tpl.html", {
    
    "n1": name, "n2": roles, "n3": user_info, "n4": data_list})


def news(request):
    import requests
    # 请求头添加浏览器信息
    headers = {
    
    
        'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    }
    url = "http://www.chinaunicom.com.cn/api/article/NewsByIndex/2/2023/06/news"
    res = requests.get(url, headers=headers)

    data_list = res.json()
    print(data_list)

    return render(request, "news.html", {
    
    "news_list": data_list})

def something(request):
    # request是一个对象,封装了用户通过发送过来的所有请求相关数据

    # 1.获取请求方式 GET/POST
    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")

リダイレクトについて: Web フレームワークはリダイレクトされた Web サイトをブラウザーに返し、ブラウザーは独自にその Web サイトを要求します。

ケース: ユーザーログイン

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 HttpResponse("登陆成功")
        return redirect("https://www.baidu.com/")
    
    # return HttpResponse("登陆失败")
    return render(request, 'login.html', {
    
    "error_msg": "用户名或密码错误"})

9.7 データベースの操作

Django はデータベースの開発と運用が容易であり、ORM フレームワークが内部で提供されています。
ここに画像の説明を挿入

9.7.1 サードパーティモジュールのインストール

pip install mysqlclient

9.7.2 ORM

ここに画像の説明を挿入
ここに画像の説明を挿入

DATABASES = {
    
    
    'default': {
    
    
    'ENGINE': 'django.db.backends.mysql',
    'NAME':'dbname',
    'USER': 'root',
    'PASSWORD': 'xxx',
    'HOST': '',
    'PORT': '',
    }
}

9.7.3 ジャンゴアクションテーブル

ここに画像の説明を挿入
ここに画像の説明を挿入

# 生成数据库同步脚本
python manage.py makemigrations
# 迁移处理表
python manage.py migrate

注: 表内
ここに画像の説明を挿入

9.7.4 テーブル内のデータ

from app01.models import Department, UserInfo
def orm(request):
    # 测试ORM操作表中的数据
    ### 1.新建
    # 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", age=29)

    ### 2.删除
    # UserInfo.objects.filter(id=3).delete()
    # Department.objects.all().delete()

    ### 3.获取数据
    # data_list = [对象-行, 对象-行, 对象-行] QuerySet类型

    # data_list = UserInfo.objects.all()
    # for obj in data_list:
    #     print(obj.id, obj.name, obj.password, obj.age)

    # data_list = UserInfo.objects.filter(id=4)
    # print(data_list)

    # row_obj = UserInfo.objects.filter(id=4).first()
    # print(row_obj.id, row_obj.name, row_obj.password, row_obj.age)

    ### 4.更新数据
    # UserInfo.objects.all().update(password=999)
    UserInfo.objects.filter(id=4).update(age=999)

    return HttpResponse("成功")

事例: ユーザー管理

ここに画像の説明を挿入
他の人の Web サイトにリダイレクトするには、完全な URL を記述する必要があります。自分のサイトへのリダイレクトは必要ありません。

10 ジャンゴ開発

テーマ: 従業員管理システム

10.1 新しいプロジェクト

設定の「DIRS」の内容を削除します。テンプレートフォルダーを削除します。

10.2 アプリの作成

ここに画像の説明を挿入
アプリを作成する
アプリを登録する

10.3 テーブル構造の設計(django)

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

10.4 MySQL でのテーブルの作成

ここに画像の説明を挿入

10.5 静的ファイル管理

ここに画像の説明を挿入

10.6 部門管理

ここに画像の説明を挿入

10.6.1 部門リスト

期待される効果:
ここに画像の説明を挿入
コードの詳細はビデオで説明されています

10.7 テンプレートの継承

ここに画像の説明を挿入

10.8 ユーザー管理

ここに画像の説明を挿入
テンプレート構文では括弧は使用できません。括弧を追加する必要がある場所を読み取ると、括弧が自動的に追加されます。
テンプレートの構文は Python の構文とは少し異なります。
ここに画像の説明を挿入
ここに画像の説明を挿入

10.8.1 Form について初めて知る

views.py
ここに画像の説明を挿入

10.8.3 モデルフォーム

モデル.py

from django.db import models

# Create your models here.
class Department(models.Model):
    """部门表"""
    title = models.CharField(verbose_name="", max_length=32)

    def __str__(self):
        return self.title


class UserInfo(models.Model):
    """员工表"""
    name = models.CharField(verbose_name="姓名", max_length=16)
    password = models.CharField(verbose_name="密码", max_length=64)
    age = models.IntegerField(verbose_name="年龄")
    account = models.DecimalField(verbose_name="账户余额", max_digits=10, decimal_places=2, default=0)
    create_time = models.DateTimeField(verbose_name="入职时间")
    depart = models.ForeignKey(to="Department", to_field="id", on_delete=models.CASCADE)

    gender_choices = (
        (1, "男"),
        (2, "女"),
    )
    gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices)

views.py

from django import forms


class UserModelForm(forms.ModelForm):
    class Meta:
        model = models.UserInfo
        # fields = ["name", "password", "age", "account", "create_time"]
        fields = "__all__"

def user_model_form_add(request):
    form = UserModelForm()
    return render(request, "user_model_form_add.html", {
    
    "form": form})

モデルフォーム内のDepartmentテーブルをフェッチする場合、まずmodels.Department.objects.all()を通じてクエリセットをフェッチし、次にその中のオブジェクトを走査して出力します。
ただし、この出力の結果は、Department オブジェクトです。
したがって、部門を書き直す必要があります

  • スタイルを追加する方法
    ここに画像の説明を挿入
class UserModelForm(forms.ModelForm):
    class Meta:
        model = models.UserInfo
        # fields = ["name", "password", "age", "account", "create_time"]
        fields = "__all__"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs = {
    
    "class": "form-control", "placeholder": field.label}

def user_model_form_add(request):
    if request.method == "GET":
        form = UserModelForm()
        return render(request, "user_model_form_add.html", {
    
    "form": form})

    form = UserModelForm(data=request.POST)
    if form.is_valid():
        # 数据合法,保存到数据库
        # {'name': '123', 'password': '123', 'age': 123, 'account': Decimal('0'), 'create_time': datetime.datetime(2011, 11, 11, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='UTC')), 'depart': <Department: 营销部>, 'gender': 1}
        form.save()
        return redirect('/user/list/')
        print(form.cleaned_data)
    # 校验失败(在页面上显示错误信息)
    return render(request, "user_model_form_add.html", {
    
    "form": form})

設定のLANGUAGE_CODEを「zh-hans」に変更すると、プロンプト情報が中国語になります。

10.8.4 ユーザーの編集

ここに画像の説明を挿入
ここに画像の説明を挿入

10.8.5 削除

わずかに

10.9 エリート番号管理

10.9.1 テーブル構造

ここに画像の説明を挿入

class PrettyNumber(models.Model):
    """靓号表"""
    mobile = models.CharField(verbose_name="手机号", max_length=11)
    price = models.IntegerField(verbose_name="价格", default=0)
    level_choices = (
        (1, "1级"),
        (2, "2级"),
        (3, "3级"),
        (4, "4级"),
    )
    level = models.SmallIntegerField(verbose_name="级别", choices=level_choices, default=1)
    status_choices = (
        (1, "已占用"),
        (2, "未使用")
    )
    status = models.SmallIntegerField(verbose_name="状态", choices=status_choices, default=2)

データベースシミュレーションでデータを自分で作成する

10.9.2 プレミアム番号のリスト

ここに画像の説明を挿入

10.9.3 新しいアカウントの作成

ここに画像の説明を挿入

10.9.3.1 認証

方法 1: 正規表現

from django.core.validators import RegexValidator
class PrettyModelForm(forms.ModelForm):

    mobile = forms.CharField(
        label="手机号",
        validators=[RegexValidator(r'^1\d{10}', '手机号格式错误')]
    )
    class Meta:
        model = models.PrettyNumber
        fields = "__all__"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs = {
    
    "class": "form-control", "placeholder": field.label}

方法 2: フック方法

from django.core.exceptions import ValidationError
class PrettyModelForm(forms.ModelForm):
    class Meta:
        model = models.PrettyNumber
        fields = "__all__"

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs = {
    
    "class": "form-control", "placeholder": field.label}

    def clean_mobile(self):
        txt_mobile = self.cleaned_data['mobile']
        if len(txt_mobile) != 11:
            raise ValidationError("格式错误")
        return txt_mobile

10.9.4 プリティナンバーの編集

class PrettyEditModelForm(forms.ModelForm):
    # mobile = forms.CharField(disabled=True, label="手机号")

    class Meta:
        model = models.PrettyNumber
        fields = ["mobile", "price", "level", "status"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs = {
    
    "class": "form-control", "placeholder": field.label}


def pretty_edit(request, nid):
    """编辑靓号"""
    row_object = models.PrettyNumber.objects.filter(id=nid).first()

    if request.method == "GET":
        form = PrettyEditModelForm(instance=row_object)
        return render(request, "pretty_edit.html", {
    
    "form": form})

    form = PrettyEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect("/pretty/list/")

    return render(request, "pretty_edit.html", {
    
    "form": form})

ここに画像の説明を挿入
プリティナンバー削除

def pretty_delete(request, nid):
    models.PrettyNumber.objects.filter(id=nid).delete()
    return redirect("/pretty/list/")

10.9.5 携帯電話番号の検索

ここに画像の説明を挿入

コメントは真ん中の二重アンダースコアです

def pretty_list(request):
    data_dict = {
    
    }
    search_data = request.GET.get("q", "")
    if search_data:
        data_dict["mobile__contains"] = search_data

    # 排序,id表示asc,-id表示desc
    queryset = models.PrettyNumber.objects.filter(**data_dict).order_by("-level")
    return render(request, "pretty_list.html", {
    
    "queryset": queryset, "search_data": search_data})
<div style="margin-bottom: 10px" class="clearfix">
   <a class="btn btn-success" href="/pretty/add/">
        <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
        新建靓号
    </a>
    <div style="float: right; width: 300px">
        <form method="get">
            <div class="input-group">
                <input type="text" name="q" class="form-control" placeholder="Search for..." value="{
     
     { search_data }}">
                <span class="input-group-btn">
                <button class="btn btn-default" type="submit">
                <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
                </button>
                </span>
            </div>
        </form>
    </div>
</div>

10.9.6 ページング

ユーザーがアクセスしたいページ番号に基づいて開始位置と終了位置を計算します。

 page = int(request.GET.get('page', 1))
    page_size = 10
    start = (page-1) * page_size
    end = page * page_size
    # 排序,id表示asc,-id表示desc
    queryset = models.PrettyNumber.objects.filter(**data_dict).order_by("-level")[start:end]

from django.utils.safestring import mark_safe
Python バックエンドが HTML 文字列を書き込み、それをフロントエンド HTML に渡したい場合は、 make_safe を使用して page_str_list 文字列をラップする必要があります。

def pretty_list(request):
    data_dict = {
    
    }
    search_data = request.GET.get("q", "")
    if search_data:
        data_dict["mobile__contains"] = search_data

    page = int(request.GET.get('page', 1))
    page_size = 10
    start = (page-1) * page_size
    end = page * page_size
    # 排序,id表示asc,-id表示desc
    total_count = models.PrettyNumber.objects.filter(**data_dict).order_by("-level").count()
    queryset = models.PrettyNumber.objects.filter(**data_dict).order_by("-level")[start:end]

    total_page_count, div = divmod(total_count, page_size)
    if div:
        total_page_count += 1


    # 计算出,显示当前页的前5页,后5页
    plus = 5
    if total_page_count <= 2 * plus:
        # 数据库中数据比较少
        start_page = 1
        end_page = total_page_count
    else:
        # 数据库数据比较多
        if page <= plus:
            start_page = 1
            end_page = 2 * plus + 1
        elif (page + plus) > total_page_count:
            start_page = total_page_count - 2 * plus
            end_page = total_page_count
        else:
            start_page = page - plus
            end_page = page + plus

    # 页码
    page_str_list = []

    page_str_list.append('<li><a href="?page={}">首页</a></li>'.format(1))

    # 上一页
    if page > 1:
        prev = '<li><a href="?page={}">上一页</a></li>'.format(page - 1)
    else:
        prev = '<li><a href="?page={}">上一页</a></li>'.format(1)

    page_str_list.append(prev)

    for i in range(start_page, end_page + 1):
        if i == page:
            ele = '<li class="active"><a href="?page={}">{}</a></li>'.format(i, i)
        else:
            ele = '<li><a href="?page={}">{}</a></li>'.format(i, i)
        page_str_list.append(ele)

    # 下一页
    if page < total_page_count:
        next = '<li><a href="?page={}">下一页</a></li>'.format(page + 1)
    else:
        next = '<li><a href="?page={}">下一页</a></li>'.format(total_page_count)
    page_str_list.append(next)

    # 尾页
    page_str_list.append('<li><a href="?page={}">尾页</a></li>'.format(total_page_count))

    page_string = mark_safe("".join(page_str_list))


    return render(request, "pretty_list.html", {
    
    "queryset": queryset, "search_data": search_data, 'page_string': page_string})
  • パッケージのページネーション クラス
"""
自定义的分页组件,以后如果想要使用这个分页组件,你需要做如下几件事:

在视图函数中:
    def pretty_list(request):
        # 1.根据情况筛选数据
        queryset = models.PrettyNumber.objects.all()

        # 2.实例化分页对象
        page_object = Pagination(request, queryset)

        context = {
            "queryset": page_object.page_queryset, # 分完页的数据
            'page_string': page_object.html()      # 生成的页码
        }
        return render(request, "pretty_list.html", context)

在HTML页面中:
        {% for obj in queryset %}
            {
    
    {obj.xx}}
        {% endfor %}

        <ul class="pagination">
            {
    
    { page_string }}
        </ul>

"""
from django.utils.safestring import mark_safe


class Pagination(object):

    def __init__(self, request, queryset, page_size=10, page_param="page", plus=5):
        """
        :param request: 请求的对象
        :param queryset: 符合条件的数据(根据这个数据进行分页处理)
        :param page_size: 每页显示多少条数据
        :param page_param: 在URL中传递的获取分页的参数
        :param plus: 显示当前页的 前或后几页(页码)
        """
        page = request.GET.get(page_param, "1")
        if page.isdecimal():
            page = int(page)
        else:
            page = 1
        self.page = page
        self.page_size = page_size
        self.start = (page - 1) * page_size
        self.end = page * page_size

        self.page_queryset = queryset[self.start:self.end]

        # 排序,id表示asc,-id表示desc
        total_count = queryset.count()
        total_page_count, div = divmod(total_count, page_size)
        if div:
            total_page_count += 1
        self.total_page_count = total_page_count
        self.plus = plus

    def html(self):
        if self.total_page_count <= 2 * self.plus:
            # 数据库中数据比较少
            start_page = 1
            end_page = self.total_page_count
        else:
            # 数据库数据比较多
            if self.page <= self.plus:
                start_page = 1
                end_page = 2 * self.plus + 1
            elif (self.page + self.plus) > self.total_page_count:
                start_page = self.total_page_count - 2 * self.plus
                end_page = self.total_page_count
            else:
                start_page = self.page - self.plus
                end_page = self.page + self.plus

        # 页码
        page_str_list = []

        page_str_list.append('<li><a href="?page={}">首页</a></li>'.format(1))

        # 上一页
        if self.page > 1:
            prev = '<li><a href="?page={}">上一页</a></li>'.format(self.page - 1)
        else:
            prev = '<li><a href="?page={}">上一页</a></li>'.format(1)

        page_str_list.append(prev)

        for i in range(start_page, end_page + 1):
            if i == self.page:
                ele = '<li class="active"><a href="?page={}">{}</a></li>'.format(i, i)
            else:
                ele = '<li><a href="?page={}">{}</a></li>'.format(i, i)
            page_str_list.append(ele)

        # 下一页
        if self.page < self.total_page_count:
            next = '<li><a href="?page={}">下一页</a></li>'.format(self.page + 1)
        else:
            next = '<li><a href="?page={}">下一页</a></li>'.format(self.total_page_count)
        page_str_list.append(next)

        # 尾页
        page_str_list.append('<li><a href="?page={}">尾页</a></li>'.format(self.total_page_count))

        search_sting = """
            <li>
                <form style="float: left; margin-left: -1px" method="get">
                    <div class="input-group" style="width: 200px">
                        <input type="text" name="page" class="form-control" placeholder="页码">
                        <span class="input-group-btn">
                            <button class="btn btn-default" type="submit">跳转</button>
                        </span>
                    </div>
                </form>
            </li>
        """
        page_str_list.append(search_sting)

        page_string = mark_safe("".join(page_str_list))
        return page_string

request.GET のディープ コピー urlencode() を使用して、以前の条件を取得します。

import copy
query_dict = copy.deepcopy(request.GET)
query_dict._mutable = True
self.query_dict = query_dict
self.page_param = page_param

10.9.7 時間プラグイン

わずかに

10.10 モデルフォームとブートストラップ

ここに画像の説明を挿入
ここに画像の説明を挿入

事業者が多い場合はビュー機能を分割可能

10.11 管理者の操作

class Admin(models.Model):
    """管理员"""
    username = models.CharField(verbose_name="用户名", max_length=32)
    password = models.CharField(verbose_name="密码", max_length=64)

インポート時:
モジュールを作成するときは、通常、組み込みモジュールが最初に作成され、次にサードパーティ モジュール、最後にカスタム モジュールが作成されます。短いモジュールが
上にあります。

  • パスワードの整合性チェック
    django-clean: 参考: https://pythonjishu.com/django-clean/
class AdminModelForm(BootStrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        widget=forms.PasswordInput
    )

    class Meta:
        model = models.Admin
        fields = ["username", "password", "confirm_password"]
        widgets = {
    
    
            "password": forms.PasswordInput
        }

    def clean_confirm_password(self):
        print(self.cleaned_data)
        pwd = self.cleaned_data.get("password")
        confirm = self.cleaned_data.get("confirm_password")
        if confirm != pwd:
            raise ValidationError("密码不一致,请重新输入")
        # 返回什么,此字段以后保存到数据库就是什么
        return confirm

def admin_add(request):
    """ 添加管理员 """
    title = "新建管理员"
    if request.method == "GET":
        form = AdminModelForm()
        return render(request, 'change.html', {
    
    "form": form, "title": title})


    form = AdminModelForm(data=request.POST)
    if form.is_valid():

        form.save()
        return redirect('/admin/list')
    return render(request, "change.html", {
    
    'form': form, "title": title})

render_value=True をプラグインに追加すると、エラーが報告された後も元の値が保持されます。

  • パスワードのMD5暗号化
import hashlib

def md5(data_string):
    salt = 'xxxxxxxx'
    obj = hashlib.md5(salt.encode('utf-8'))
    obj.update(data_string.encdoe('utf-8'))
    return obj.hexdigest()

設定に SECRET_KEY の値があり、ソルトとして使用されます

class AdminModelForm(BootStrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        widget=forms.PasswordInput(render_value=True)
    )

    class Meta:
        model = models.Admin
        fields = ["username", "password", "confirm_password"]
        widgets = {
    
    
            "password": forms.PasswordInput(render_value=True)
        }

    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        return md5(pwd)

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get("password")
        confirm = md5(self.cleaned_data.get("confirm_password"))
        if confirm != pwd:
            raise ValidationError("密码不一致,请重新输入")
        # 返回什么,此字段以后保存到数据库就是什么
        return confirm

10.12 ユーザーログイン

10.12.1 ユーザー認証 - Cookie とセッション

  • http プロトコルの特徴
    ステートレス & ショート リンク
    ここに画像の説明を挿入
  • クッキーとセッションとは何ですか?
    ここに画像の説明を挿入

Django はデフォルトでセッションをデータベースに置きます

from django.shortcuts import render, HttpResponse, redirect
from django import forms
from app01 import models
from app01.utils.encrypt import md5


class LoginForm(forms.Form):
    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput,
        required=True
    )
    password = forms.CharField(
        label="密码",
        widget=forms.PasswordInput(render_value=True)
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
                field.widget.attrs['placeholder'] = field.label
            else:
                field.widget.attrs = {
    
    
                    "class": "form-control",
                    "placeholder": field.label
                }

    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        return md5(pwd)


def login(request):
    if request.method == 'GET':
        form = LoginForm()
        return render(request, 'login.html', {
    
    'form': form})

    form = LoginForm(data=request.POST)
    if form.is_valid():
        print(form.cleaned_data)
        # 校验用户名和密码
        admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            form.add_error("password", "用户名或密码错误")
            return render(request, 'login.html', {
    
    'form': form})
        # 用户名和密码正确
        # 网站要生成一个字符串;写到用户浏览器的cookie中,再写入到session中
        request.session["info"] = {
    
    'id': admin_object.id, 'name': admin_object.username}

        return redirect('/admin/list/')
    return render(request, 'login.html', {
    
    'form': form})

10.12.2 ログイン

ログインしていないユーザーは、URL 経由で管理者リスト ページにアクセスできません。

ここに画像の説明を挿入

10.12.3 ミドルウェアの経験

ビュー機能にアクセスするにはミドルウェアを経由する必要があり、戻るにはミドルウェアを経由する必要があります。
ミドルウェアを通過できない場合は、直接戻ってください。

ここに画像の説明を挿入

  • ミドルウェアの定義
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class M1(MiddlewareMixin):
    """中间件1"""

    def process_request(self, request):
        print("M1.进来了")
        return HttpResponse("无权访问")


    def process_response(self, request, response):
        print("M1.走了")
        return response


class M2(MiddlewareMixin):
    """中间件1"""

    def process_request(self, request):
        print("M2.进来了")

    def process_response(self, request, response):
        print("M2.走了")
        return response
  • ミドルウェアの適用
    settings.pyにミドルウェアを登録する
MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    'app01.middleware.auth.M1',
    'app01.middleware.auth.M2',
]
  • ミドルウェアの process_request メソッド

process_request メソッドに戻り値がない場合 (return None)、そのまま続行できます。
戻り値がある場合、戻り値は一般にビュー関数の戻り値と同様です

10.12.4 ミドルウェアによるログイン検証の実装

  • ミドルウェアを書く
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect

class AuthMiddleware(MiddlewareMixin):
    """中间件1"""

    def process_request(self, request):
        # 0.排除那些不需要登录就能访问的页面
        # request.path_info获取当前用户请求的URL /login/
        if request.path_info == "/login/":
            return


        # 1.读取当前访问用户的session信息,如果能读到,说明登陆过:
        info_dict = request.session.get("info")
        print(info_dict)
        if info_dict:
            return

        # 2.如果没有登陆过,重新回到登录页面
        return redirect('/login/')
  • アプリケーションミドルウェア
MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    'app01.middleware.auth.AuthMiddleware',
]

10.12.5 ログアウト

def logout(request):
    """ 注销 """
    request.session.clear()

    return redirect('/login/')

10.13 画像検証コード

ここに画像の説明を挿入

10.13.1 Python を使用して画像を生成する

pip install pillow

参考文献:
https://www.cnblogs.com/wupeiqi/articles/5812291.html

10.14 Ajaxリクエスト

ここに画像の説明を挿入

10.14.1 GETリクエスト

# html中
 $.ajax({
         url: "/task/ajax/",
         type: "get",
         data:{
             n1: 123,
             n2: 456
         },
         success: function(res){
             console.log(res);
         }
     })
def task_ajax(request):
    print(request.GET)
    return HttpResponse("成功了")

10.14.2 POSTリクエスト

投稿リクエストを送信するときに使用できます免除csrft oken

# html中
 $.ajax({
         url: "/task/ajax/",
         type: "post",
         data:{
             n1: 123,
             n2: 456
         },
         success: function(res){
             console.log(res);
         }
     })
from django.shortcuts import render, redirect, HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def task_ajax(request):
    print(request.POST)
    return HttpResponse("成功了")

10.14.3 バインディングイベント

{% extends 'layout.html' %}

{% block content %}
    <div class="container">
        <h1>任务管理</h1>
        <h3>示例1</h3>
        <input id="btn1" type="button" class="btn btn-primary" value="点击" onclick="clickMe();"/>
    </div>
{% endblock %}



{% block js %}
    <script type="text/javascript">
        $(function () {
      
      
            // 页面框架加载完成之后代码自动执行
            bindBtn1Event();
        })

        function bindBtn1Event() {
      
      
            $("#btn1").click(function () {
      
      
                $.ajax({
      
      
                    url: "/task/ajax/",
                    type: "post",
                    data: {
      
      
                        n1: 123,
                        n2: 456
                    },
                    success: function (res) {
      
      
                        console.log(res);
                    }
                })
            })
        }
    </script>
{% endblock %}

10.14.4 ajaxリクエストの戻り値

  • フロントエンド
{% extends 'layout.html' %}

{% block content %}
    <div class="container">
        <h1>任务管理</h1>
        <h3>示例1</h3>
        <input id="btn1" type="button" class="btn btn-primary" value="点击"/>
    </div>
{% endblock %}



{% block js %}
    <script type="text/javascript">
        $(function () {
      
      
            // 页面框架加载完成之后代码自动执行
            bindBtn1Event();
        })

        function bindBtn1Event() {
      
      
            $("#btn1").click(function () {
      
      
                $.ajax({
      
      
                    url: "/task/ajax/",
                    type: "post",
                    data: {
      
      
                        n1: 123,
                        n2: 456
                    },
                    dataType: "JSON",
                    success: function (res) {
      
      
                        console.log(res);
                        console.log(res.status);
                        console.log(res.data);
                    }
                })
            })
        }
    </script>
{% endblock %}
  • バックエンドの戻り値は
    通常、シリアル化する必要がある json 辞書です。
import json
from django.shortcuts import render, redirect, HttpResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def task_ajax(request):
    print(request.POST)
    data_dict = {
    
    "status": True, "data": [11, 22, 33, 44]}
    json_string = json.dumps(data_dict)
    return HttpResponse(json_string)

Django はシリアル化メソッド JsonResponse も提供します。

{
    
    % extends 'layout.html' %}

{
    
    % block content %}
    <div class="container">
        <h1>Ajax学习</h1>

        <h3>示例1</h3>
        <input id="btn1" type="button" class="btn btn-primary" value="点击1"/>

        <h3>示例2</h3>
        <input type="text" id="txtUser" placeholder="用户名"/>
        <input type="text" id="txtAge" placeholder="年龄"/>
        <input id="btn2" type="button" class="btn btn-primary" value="点击2"/>

        <h3>示例3</h3>
        <form id="form3">
            <input type="text" name="user" placeholder="用户名"/>
            <input type="text" name="age" placeholder="年龄"/>
            <input type="text" name="email" placeholder="邮箱"/>
            <input type="text" name="more" placeholder="介绍"/>
        </form>
        <input id="btn3" type="button" class="btn btn-primary" value="点击3"/>
    </div>
{
    
    % endblock %}



{
    
    % block js %}
    <script type="text/javascript">
        $(function () {
    
    
            // 页面框架加载完成之后代码自动执行
            bindBtn1Event();
            bindBtn2Event();
            bindBtn3Event();
        })

        function bindBtn1Event() {
    
    
            $("#btn1").click(function () {
    
    
                $.ajax({
    
    
                    url: "/task/ajax/",
                    type: "post",
                    data: {
    
    
                        n1: 123,
                        n2: 456
                    },
                    dataType: "JSON",
                    success: function (res) {
    
    
                        console.log(res);
                        console.log(res.status);
                        console.log(res.data);
                    }
                })
            })
        }

        function bindBtn2Event() {
    
    
            $("#btn2").click(function () {
    
    
                $.ajax({
    
    
                    url: "/task/ajax/",
                    type: "post",
                    data: {
    
    
                        name: $("#txtUser").val(),
                        age: $("#txtAge").val()
                    },
                    dataType: "JSON",
                    success: function (res) {
    
    
                        console.log(res);
                        console.log(res.status);
                        console.log(res.data);
                    }
                })
            })
        }

        function bindBtn3Event() {
    
    
            $("#btn3").click(function () {
    
    
                $.ajax({
    
    
                    url: "/task/ajax/",
                    type: "post",
                    data: $("#form3").serialize(),
                    dataType: "JSON",
                    success: function (res) {
    
    
                        console.log(res);
                        console.log(res.status);
                        console.log(res.data);
                    }
                })
            })
        }
    </script>
{
    
    % endblock %}

10.14.5 ケース

{% extends 'layout.html' %}

{% block content %}
    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">表单</div>
            <div class="panel-body">
                <form id="formAdd" novalidate>
                    <div class="clearfix">
                        {% for field in form %}
                            <div class="col-xs-6">
                                <div class="form-group" style="position: relative; margin-bottom: 20px;">
                                    <label>{
   
   { field.label }}</label>
                                    {
   
   { field }}
                                    <span class="error-msg" style="color:red;position: absolute;"></span>
                                </div>
                            </div>
                        {% endfor %}
                    </div>
                    <div class="col-xs-12">
                        <button id="btnAdd" type="button" class="btn btn-primary">提 交</button>
                    </div>
                </form>
            </div>
        </div>

        <hr/>
        <h1>Ajax学习</h1>

        <h3>示例1</h3>
        <input id="btn1" type="button" class="btn btn-primary" value="点击1"/>

        <h3>示例2</h3>
        <input type="text" id="txtUser" placeholder="用户名"/>
        <input type="text" id="txtAge" placeholder="年龄"/>
        <input id="btn2" type="button" class="btn btn-primary" value="点击2"/>

        <h3>示例3</h3>
        <form id="form3">
            <input type="text" name="user" placeholder="用户名"/>
            <input type="text" name="age" placeholder="年龄"/>
            <input type="text" name="email" placeholder="邮箱"/>
            <input type="text" name="more" placeholder="介绍"/>
        </form>
        <input id="btn3" type="button" class="btn btn-primary" value="点击3"/>
    </div>
{% endblock %}



{% block js %}
    <script type="text/javascript">
        $(function () {
      
      
            // 页面框架加载完成之后代码自动执行
            bindBtn1Event();
            bindBtn2Event();
            bindBtn3Event();
            bindBtnAddEvent();
        })

        function bindBtn1Event() {
      
      
            $("#btn1").click(function () {
      
      
                $.ajax({
      
      
                    url: "/task/ajax/",
                    type: "post",
                    data: {
      
      
                        n1: 123,
                        n2: 456
                    },
                    dataType: "JSON",
                    success: function (res) {
      
      
                        console.log(res);
                        console.log(res.status);
                        console.log(res.data);
                    }
                })
            })
        }

        function bindBtn2Event() {
      
      
            $("#btn2").click(function () {
      
      
                $.ajax({
      
      
                    url: "/task/ajax/",
                    type: "post",
                    data: {
      
      
                        name: $("#txtUser").val(),
                        age: $("#txtAge").val()
                    },
                    dataType: "JSON",
                    success: function (res) {
      
      
                        console.log(res);
                        console.log(res.status);
                        console.log(res.data);
                    }
                })
            })
        }

        function bindBtn3Event() {
      
      
            $("#btn3").click(function () {
      
      
                $.ajax({
      
      
                    url: "/task/ajax/",
                    type: "post",
                    data: $("#form3").serialize(),
                    dataType: "JSON",
                    success: function (res) {
      
      
                        console.log(res);
                        console.log(res.status);
                        console.log(res.data);
                    }
                })
            })
        }

        function bindBtnAddEvent() {
      
      
            $("#btnAdd").click(function () {
      
      
                $(".error-msg").empty();

                $.ajax({
      
      
                    url: "/task/add/",
                    type: "post",
                    data: $("#formAdd").serialize(),
                    dataType: "JSON",
                    success: function (res) {
      
      
                        if (res.status) {
      
      
                            alert("添加成功");
                        } else {
      
      
                            {
      
      #console.log(res.error);#}
                            $.each(res.error, function(name, data){
      
      
                                // console.log(name, data);
                                $("#id_" + name).next().text(data[0])
                            })
                        }
                    }
                })
            })
        }
    </script>
{% endblock %}

10.15 Django 開発 - コンテンツのレビュー

ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

10.16 注文

テーブル構造
ここに画像の説明を挿入

class Order(models.Model):
    """ 订单 """
    oid = models.CharField(verbose_name="订单号", max_length=64)
    title = models.CharField(verbose_name="名称", max_length=32)
    price = models.IntegerField(verbose_name="价格")
    status_choices = (
        (1, "待支付"),
        (2, "已支付")
    )
    status = models.SmallIntegerField(verbose_name="状态", choices=status_choices, default=1)
    admin = models.ForeignKey(verbose_name="管理员", to="Admin", on_delete=models.CASCADE)

form.instance.oid=...ユーザーが入力していない値を追加することによって

import random
from datetime import datetime
from django.shortcuts import render, redirect, HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
from app01.utils.bootstrap import BootStrapModelForm
from app01 import models


class OrderModelForm(BootStrapModelForm):
    class Meta:
        model = models.Order
        # fields = "__all__"
        exclude = ["oid"]


def order_list(request):
    form = OrderModelForm
    return render(request, 'order_list.html', {
    
    'form': form})


@csrf_exempt
def order_add(request):
    form = OrderModelForm(data=request.POST)
    if form.is_valid():
        # title=? price=? status=? admin_id?
        # print(form.cleaned_data)
        form.instance.oid = datetime.now().strftime("%Y%m%d%H%M%S") + str(random.randint(1000, 9999))
        form.save()
        return JsonResponse({
    
    "status": True})

    return JsonResponse({
    
    "status": False, 'error': form.errors})

$("#formAdd")は jQuery オブジェクトと$("#formAdd")[0]DOM オブジェクトであり、reset() メソッドがあります。

ここに画像の説明を挿入

10.17 チャート

  • 海外のハイチャート。
  • eチャート、国内。

10.18 ファイルのアップロード

10.18.1 基本操作

{% extends 'layout.html' %}

{% block content %}
    <div class="container">
        <form method="post" enctype="multipart/form-data">
            {% csrf_token %}
            <input type="text" name="username">
            <input type="file" name="avatar">
            <input type="submit" value="提交">
        </form>
    </div>
{% endblock %}
from django.shortcuts import render, HttpResponse


def upload_list(request):
    if request.method == "GET":
        return render(request, 'upload_list.html')
    # print(request.POST) # 请求体传递过来的数据
    # print(request.FILES) # 发过来的文件
    file_object = request.FILES.get("avatar")
    # print(file_object.name)
    f = open(file_object.name, mode='wb')
    for chunk in file_object.chunks():
        f.write(chunk)
    f.close()

    return HttpResponse("...")

10.18.2 ケース: データの一括アップロード

 <form method="post" enctype="multipart/form-data" action="/depart/multi/">
      {% csrf_token %}
      <div class="form-group">
          <input type="file" name="exc">
      </div>
      <input type="submit" value="上传" class="btn btn-info btn-sm">
 </form>
def depart_multi(request):
    """批量上传"""
    # 1.获取用户上传的文件对象
    file_object = request.FILES.get("exc")

    # 2.对象传递给openpyxl, 由openpyxl读取文件的内容
    wb = load_workbook(file_object)
    sheet = wb.worksheets[0]

    # 3.循环获取每一行数据
    for row in sheet.iter_rows(min_row=2):
        text = row[0].value
        exists = models.Department.objects.filter(title=text).exists()
        if not exists:
            models.Department.objects.create(title=text)

    return redirect("/depart/list/")

10.18.3 ケース: 混合データ (フォーム)

ページを送信するとき: ユーザーはデータとファイルを入力します (入力を空にすることはできず、エラーが報告されます)。

  • フォームは HTML タグを生成できます: type=file
  • フォームの検証
  • form.cleaned_data はデータ + ファイル オブジェクトを取得します
{% extends "layout.html" %}

{% block content %}
    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title">{
   
   { title }}</h3>
            </div>
            <div class="panel-body">
                <form method="post" enctype="multipart/form-data" novalidate>
                    {% csrf_token %}

                    {% for field in form %}
                        <div class="form-group">
                            <label>{
   
   { field.label }}</label>
                            {
   
   { field }}
                            <span style="color: red">{
   
   { field.errors.0 }}</span>
                        </div>
                    {% endfor %}
                    <button type="submit" class="btn btn-primary">提 交</button>
                </form>
            </div>
        </div>
    </div>
{% endblock %}
from django.shortcuts import render, HttpResponse
import os
from app01 import models


def upload_list(request):
    if request.method == "GET":
        return render(request, 'upload_list.html')
    # print(request.POST) # 请求体传递过来的数据
    # print(request.FILES) # 发过来的文件
    file_object = request.FILES.get("avatar")
    # print(file_object.name)
    f = open(file_object.name, mode='wb')
    for chunk in file_object.chunks():
        f.write(chunk)
    f.close()

    return HttpResponse("...")


from django import forms
from app01.utils.bootstrap import BootStrapForm


class UpForm(BootStrapForm):
    bootstrap_exclude_fields = ['img']
    name = forms.CharField(label="姓名")
    age = forms.IntegerField(label="年龄")
    img = forms.FileField(label="头像")


def upload_form(request):
    title = "Form上传"
    if request.method == "GET":
        form = UpForm()
        return render(request, 'upload_form.html', {
    
    "title": title, "form": form})

    form = UpForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        print(form.cleaned_data)
        # 读取到内容, 自己处理每个字段的内容
        # 1.读取图片内容,写入到文件夹中,并获取文件的路径
        image_object = form.cleaned_data.get('img')
        db_file_path = os.path.join("static", "img", image_object.name)
        file_path = os.path.join("app01", "static", "img", image_object.name)
        f = open(file_path, mode='wb')
        for chunk in image_object.chunks():
            f.write(chunk)
        f.close()
        # 将图片的文件路径写入到数据库
        models.Boss.objects.create(
            name=form.cleaned_data['name'],
            age=form.cleaned_data['age'],
            img=db_file_path,
        )
        return HttpResponse("...")
    return render(request, 'upload_form.html', {
    
    "title": title, "form": form})

10.19.4 メディアを有効にする

ここに画像の説明を挿入
urls.py で設定します。

from django.urls import path, re_path
from django.views.static import serve
from django.conf import settings
urlpatterns = {
    
    
	re_path(r'^media/(?P<path>.*)', serve, {
    
    'document_root': settings.MEDIA_ROOT}, name='media'),
}

settings.py で設定します。

import os
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"

10.19.5 ケース: 混合データ (フォーム)

import os
from django.shortcuts import render, HttpResponse
from django.conf import settings
from app01 import models


def upload_list(request):
    if request.method == "GET":
        return render(request, 'upload_list.html')
    # print(request.POST) # 请求体传递过来的数据
    # print(request.FILES) # 发过来的文件
    file_object = request.FILES.get("avatar")
    # print(file_object.name)
    f = open(file_object.name, mode='wb')
    for chunk in file_object.chunks():
        f.write(chunk)
    f.close()

    return HttpResponse("...")


from django import forms
from app01.utils.bootstrap import BootStrapForm


class UpForm(BootStrapForm):
    bootstrap_exclude_fields = ['img']
    name = forms.CharField(label="姓名")
    age = forms.IntegerField(label="年龄")
    img = forms.FileField(label="头像")


def upload_form(request):
    title = "Form上传"
    if request.method == "GET":
        form = UpForm()
        return render(request, 'upload_form.html', {
    
    "title": title, "form": form})

    form = UpForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        print(form.cleaned_data)
        # 读取到内容, 自己处理每个字段的内容
        # 1.读取图片内容,写入到文件夹中,并获取文件的路径
        image_object = form.cleaned_data.get('img')
        # media_path = os.path.join(settings.MEDIA_ROOT, image_object.name)
        media_path = os.path.join("media", image_object.name)
        f = open(media_path, mode='wb')
        for chunk in image_object.chunks():
            f.write(chunk)
        f.close()
        # 将图片的文件路径写入到数据库
        models.Boss.objects.create(
            name=form.cleaned_data['name'],
            age=form.cleaned_data['age'],
            img=media_path,
        )
        return HttpResponse("...")
    return render(request, 'upload_form.html', {
    
    "title": title, "form": form})

ケース: 混合データ (ModalForm)

models.py 内

class City(models.Model):
    name = models.CharField(verbose_name="名称", max_length=32)
    age = models.IntegerField(verbose_name="人口")
    # 本质上数据也是CharField,帮你自动保存数据,支持upload_to
    img = models.FileField(verbose_name="Logo", max_length=128, upload_to='city/')

モデルフォームの定義

class UpModelForm(BootStrapModelForm):
    bootstrap_exclude_fields = ['img']

    class Meta:
        model = models.City
        fields = "__all__"

ビュー

def upload_modal_form(request):
    """基于modelform"""
    title = "ModelForm上传文件"
    if request.method == 'GET':
        form = UpModelForm()
        return render(request, 'upload_form.html', {
    
    "form": form, "title": title})
    form = UpModelForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # 对于文件,自动保存:
        # 字段 上传的路径写入到数据库
        form.save()
        return HttpResponse("上传成功")
    return render(request, 'upload_form.html', {
    
    "form": form, "title": title})

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/zhangyifeng_1995/article/details/131379611