Django

Prerequisite

视频教程

一、跟着教程学 Django

视频:Learn Django by Building an Online Marketplace – Python Tutorial for Beginners
Github 仓库:Puddle | Django
PS:这两个半小时信息量巨大,建议直接看,重要的是理解思路,不要跟着敲代码,不然敲一天都敲不完

常用命令:

  • 下载 Django pip install django django-cors-headers
  • 构建新环境(名为 puddle)django-admin startproject puddle
  • 构建应用程序(名为 core)python manage.py startapp core
  • 生成一个新的迁移文件 python manage.py makemigrations
  • 将这些迁移文件应用到数据库 python manage.py migrate
  • 创建管理员 python manage.py createsuperuser
    • 用户名:admin
    • 邮箱:admin@puddle.com
    • 密码:ilovedjango
  • 查看命令作用 python manage.py help
  • 开启当前环境 python manage.py runserver

小技巧:

  • VSCode 中的 HTML 文件,输入 ! 即可创建一个模板

启动项目

首先进入 puddle 文件下输入如下命令

# 更新数据库
python manage.py makemigrations
python manage.py migrate

# 创建管理员
python manage.py createsuperuser
# admin
# admin@puddle.com
# ilovedjango

# 启动
python manage.py runserver

http://127.0.0.1:8000/admin 网址登入,进入管理员后台,添加如下数据:

  • Categories
    • Toys
    • Clothes
    • Furniture
  • Items
    • shoe1
    • chair1
    • chair2
    • teddy bear
    • toy car
  • Users
    • xiaoming / qweiop123
    • xiaohong / asdjkl456
    • xiaozhang / zxcbnm789

整体文件的结构

下面是主体 Project

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py

manage.py:一个命令行工具,管理 Django 的交互脚本
mysite/__init__.py:说明这文件夹是个包,可以引用(一般情况下的项目,每个文件夹都要加)
mysite/settings.py:项目的配置文件
mysite/urls.py:路由文件,所有的任务都是从这里开始分配,相当于 Django 驱动站点的目录
mysite/wsgi.py:一个基于 WSGI 的 web 服务器进入点,提供底层的网络通信功能,通常不用关心
mysite/asgi.py:一个基于 ASGI 的 web 服务器进入点,提供异步的网络通信功能,通常不用关心

下面是应用 app

polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

__init__.py:一个空文件,指示 Python 将该目录视为 Python 包
admin.py:该文件定义了 Django 管理后台中注册该应用程序所需的模型
apps.py:该文件定义了该应用程序的配置
models.py:该文件定义了 Django 中的模型类,用于处理应用程序与数据库之间的数据交互
tests.py:该文件定义了应用程序的测试用例
views.py:该文件定义了处理 HTTP 请求的视图函数
migrations/:该目录用于存放该应用程序的数据库迁移文件
static/:该目录存放应用程序的静态文件,如 CSS、JavaScript 等
templates/:该目录存放应用程序的模板文件,用于渲染 HTML 页面

应用 app 中可能还包含

polls/
    urls.py
    forms.py

urls/:该文件定义了 URL 路由规则的模块,URL 是用于定位 Web 应用程序中特定资源的地址
forms/:该文件定义了表单的模块,表单是用于收集用户输入数据的界面元素

该项目主要内容

manage.py
db.sqlite3
puddle/
    settings.py
    urls.py
core/
    templates/
        base.html
        contact.html
        index.html
        login.html
        signup.html
    forms.py
    urls.py
    views.py
item/
    templates/
        detail.html
        form.html
        items.html
    forms.py
    urls.py
    views.py
    admin.py
    models.py
dashboard/
    templates/
        index.html
    urls.py
    views.py
conversation/
    templates/
        detail.html
        inbox.html
        new.html
    forms.py
    urls.py
    views.py
    admin.py
    models.py

就挑重点讲了

puddle/urls.py

urlpatterns = [
    path('', include('core.urls')),
    path('items/', include('item.urls')),
    path('dashboard/', include('dashboard.urls')),
    path('inbox/', include('conversation.urls')),
    path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

include 相当于多级路由,一般用于项目核心 urls.py,这个核心共指向四个界面,分别是:

  • /,主页
  • /items/,商品界面
  • /dashboard/,自己的商品面板
  • /inbox/,对话箱
  • /admin/,账号登入窗口

puddle/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'conversation',
    'core',
    'dashboard',
    'item',
]

...

STATIC_URL = 'static/'
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'

INSTALLED_APPS 下面要接上已创建的 app 应用;最后三行代表静态资源(参考这样的写法)

core/urls.py

urlpatterns = [
    path('', views.index, name='index'),
    path('contact/', views.contact, name='contact'),
    path('signup/', views.signup, name='signup'),
    path('login/', auth_views.LoginView.as_view(template_name='core/login.html', authentication_form=LoginForm), name='login'),
]

这样的写法就不是多级路由了,就代表了具体的功能:

  • /,主页
  • /contact/,联系页面,类似于友链
  • /signup/,注册页面
  • /login/,登入页面

core/views.py

def index(request):
    items = Item.objects.filter(is_sold=False)[0:6]
    categories = Category.objects.all()

    return render(request, 'core/index.html', {
        'categories': categories,
        'items': items,
    })

def contact(request):
    return render(request, 'core/contact.html')

def signup(request):
    if request.method == 'POST':
        form = SignupForm(request.POST)

        if form.is_valid():
            form.save()

            return redirect('/login/')
    else:
        form = SignupForm()

    return render(request, 'core/signup.html', {
        'form': form
    })

index 函数表示主页;contact 函数表示联系页面;signup 函数包含了注册页面和登入页面,逻辑是首先进入 signup 网页,此时填写完资料再回车(发送 POST 请求),此时资料会保存到数据库中,并重定向到 login 界面

core/templates/xxx.html

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <script src="https://cdn.tailwindcss.com"></script>

    <title>{% block title %}{% endblock %} | Puddle</title>
</head>

<body>
        <nav class="py-6 px-6 flex justify-between items-center border-b border-gray-200">
            <a href="/" class="text-xl font-semibold">Puddle</a>
            ...
</body>
{% extends 'core/base.html' %}

{% block title %}Contact{% endblock %}

{% block content %}
    <h1>The contact page</h1>
{% endblock %}

最主要的就是这个 tailwindcss 样式,全部 html 文件都以 class 的形式使用到了它,当然,也非常好看!
基本模板就是 base.html,其他都是以它的基础扩大沿伸(比如上面的 contact.html)

core/forms.py

class LoginForm(AuthenticationForm):
    username = forms.CharField(widget=forms.TextInput(attrs={
        'placeholder': 'Your username',
        'class': 'w-full py-4 px-6 rounded-xl'
    }))
    password = forms.CharField(widget=forms.PasswordInput(attrs={
        'placeholder': 'Your password',
        'class': 'w-full py-4 px-6 rounded-xl'
    }))

class SignupForm(UserCreationForm):
    class Meta:
        model = User
        fields = ('username', 'email', 'password1', 'password2')
    
    username = forms.CharField(widget=forms.TextInput(attrs={
        'placeholder': 'Your username',
        'class': 'w-full py-4 px-6 rounded-xl'
    }))
    email = forms.CharField(widget=forms.EmailInput(attrs={
        'placeholder': 'Your email address',
        'class': 'w-full py-4 px-6 rounded-xl'
    }))
    password1 = forms.CharField(widget=forms.PasswordInput(attrs={
        'placeholder': 'Your password',
        'class': 'w-full py-4 px-6 rounded-xl'
    }))
    password2 = forms.CharField(widget=forms.PasswordInput(attrs={
        'placeholder': 'Repeat password',
        'class': 'w-full py-4 px-6 rounded-xl'
    }))

这是用于数据收集的文件,一般来讲(比如 SignupForm 类)都有个 Meta 元类,指定了要收集的名称,下面则是收集的类别(比如 TextInput、EmailInput 等),而特殊的(比如 LoginForm 类)则是在 urls.py 已经隐式的添加了,故不用添加 Meta 元类

其他的文件略,大体一致

二、看博客学 Django

参考博客:

解决跨域问题

# 在 setting.py 中额外添加如下内容即可

INSTALLED_APPS = [
    "corsheaders",
]

MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware",
    "corsheaders.middleware.CorsMiddleware",
]

# 允许全部来源
CORS_ORIGIN_ALLOW_ALL = True # 如果为 True,将不使用白名单,并且将接受所有来源,默认为 False

配置 MySQL 数据库

# 在 setting.py 中修改如下内容即可

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'MySQL',
        'USER': 'root', # 用户名
        'PASSWORD': 'root', # 密码
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

三、学习新框架 Django-Ninja

Ninja 官网:Django Ninja Tutorial
学习视频:Python-Django-Ninja基础入门教程
学习博客:Python系列-Django-Ninja

Ninja 大致用法

PS:我个人感觉 Django Ninja 和 Flask 没什么区别啊?前者只是把流程简化了一下(把 views.py 中的内容放在 api.py 中)

  • 下载 Django-Ninja 库:pip install django-ninja
  • xxx/api.pyxxx/urls.py 中添加所需
# api.py
from ninja import NinjaAPI

api = NinjaAPI()

# urls.py
from employee.api import api # 也可以用路由拆分 from api import api

urlpatterns = [
    ...
    path("api/", api.urls),
]
  • 添加新 app 应用:python manage.py startapp employee
  • xxx/settings.pyINSTALLED_APPS 中添加 employee
  • 万能 api 测试文档,支持查看与测试 api(包括 GET、POST 等):http://127.0.0.1:8000/api/docs

下面代码是 Django-Ninja 的增删改查示例

PS:装饰器中的形参是用于规范数据,如 response=EmployeeOut 表示函数的 return 返回的一定是 EmployeeOut 类型数据

from datetime import date
from typing import List
from ninja import NinjaAPI, Schema
from django.shortcuts import get_object_or_404
from employees.models import Employee


api = NinjaAPI()


class EmployeeIn(Schema):
    first_name: str
    last_name: str
    department_id: int = None
    birthdate: date = None


class EmployeeOut(Schema):
    id: int
    first_name: str
    last_name: str
    department_id: int = None
    birthdate: date = None


@api.post("/employees")
def create_employee(request, payload: EmployeeIn):
    employee = Employee.objects.create(**payload.dict())
    return {"id": employee.id}


@api.get("/employees/{employee_id}", response=EmployeeOut)
def get_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    return employee


@api.get("/employees", response=List[EmployeeOut])
def list_employees(request):
    qs = Employee.objects.all()
    return qs


@api.put("/employees/{employee_id}")
def update_employee(request, employee_id: int, payload: EmployeeIn):
    employee = get_object_or_404(Employee, id=employee_id)
    for attr, value in payload.dict().items():
        setattr(employee, attr, value)
    employee.save()
    return {"success": True}


@api.delete("/employees/{employee_id}")
def delete_employee(request, employee_id: int):
    employee = get_object_or_404(Employee, id=employee_id)
    employee.delete()
    return {"success": True}
posted @ 2023-03-18 21:34  筱团  阅读(158)  评论(0编辑  收藏  举报