栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Django框架零基础入门

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Django框架零基础入门

目录
  • 前言
  • 1. 实操第一个项目
  • 2. 模板
  • 3. 模型
  • 4. 表单模板
    • 4.1 Django Form类
    • 4.2 表单渲染
  • 5. 视图
  • 6. 路由
  • 7. Auth组件
  • 8. Cookie和Session
  • 9. Nginx与uwsgi部署配置

前言

关于这部分知识点
主要参考了网上各大博客以及知乎等进行总结

链接如下:
W3Cschool的python Django
菜鸟教程的python Django


Django是免费开源的web框架,可搭建高性能优雅的网站

组成部分:映射器、URL分发器、视图系统、模板系统等

内置应用:可扩展的认证系统、动态站点管理页面、站点地图工具、CSRF、轻量级标记语言模板库等

优缺点
优点:强大的URL路由配置、自动管理后台、全套解决方案(组件)
缺点:手写URL配置、模板功能弱、系统耦合大等

安装Django
在安装之前要提前安装上python,之后才可安装Django,具体步骤如下:

1. 实操第一个项目

使用 django-admin 来创建 HelloWorld 项目,通过以下命令进行:django-admin startproject HelloWorld

通过dir或者tree看清目录结构

各个目录的层级结构如下:

  • manage.py: 实用的命令行工具,与 Django 项目进行交互
  • init.py: 空文件表明python包
  • settings.py: Django 项目配置
  • urls.py: URL 声明以及驱动网站的目录
  • wsgi.py: WSGI 兼容的 Web 服务器的入口,主要用来运行项目

退回上一层目录执行python manage.py runserver,该命令主要是启动项目

成功执行项目之后,通过http://127.0.0.1:8000/访问

出现如下页面代表项目构建完成

如果要创建自个的项目文件,在manage.py

2. 模板

模板主要是快速生成并且呈现出页面,页面主要的构成是模板加数据
模板一般分为两个部分:

  • 静态页面
  • 动态填充(通过模板语言动态构建页面内容)

模板文件的使用
主要通过视图函数中的模板语言生成html页面,在将其页面信息返回到浏览器显示
加载模板文件template,定义模板文件(RequestContext)传递数据,使用传递的数据替换相应的变量

from django.shortcuts import render
from django.template import loader,RequestContext
from django.http import HttpResponse


# 产生视图函数的代码
def my_render(request,template_path,context={}):
  # 1.加载模板文件,获取一个模板对象
  temp = loader.get_template(template_path)
  # 2.定义模板上下文,给模板传递数据
  context = RequestContext(request, context)
  # 3.模板渲染,产生一个替换后的html内容
  res_html = temp.render(context)
  # 4.返回应答
  return HttpResponse(res_html)
  
# /index
def index(request):
  # return my_render(request,'booktest/index.html') 这是自己封装的render
  # 其实Django已经封装好了,可以直接使用
  return render(request,'booktest/index.html')

模板语言:{% 代码段 %}

  • 遍历列表:{% for i in 列表 %}
  • 列表不为空时执行:{% empty %}
  • 列表为空时执行:{% endfor %}
  • 加上关键字reversed则倒序遍历:{% for x in 列表 reversed %}以及{% endfor %}

关于模板语言的更多使用,可看官方讲解:
官方文档对其模板语言讲解

3. 模型

模型是数据的信息来源,类似JAVA的MVC中的M(model)
每一个模型都是django.db.models.Model的子类,而且都代表数据表中的字段
Django提供自动生成数据库的访问API

如下示例:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=30)

上面的字段都指定类属性(映射到数据库列中),会创建一个数据库表:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "name" varchar(30) NOT NULL
);

在定义每个模型数据时,如下注意事项:

  • 定义模型需要指定字段类型,属性=models.字段类型(选项)
  • 不可使用连续下划线以及关键字

而且Django根据数据可以确定这些信息(当前选择的数据库支持字段的类型、渲染管理表单时使用的html控件)

模型字段类型大致有如下:(常用如下)

字段类描述
AutoField根据 ID 自动递增的 IntegerField
BooleanField真假值字段。如需使用null 值,使用 NullBooleanField
CharField字符串字段,针对长度较小的字符串。大量文本应该使用 TextField 。必须参数:max_length ,即字段的最大长度(字符个数)
DateField日期, datetime.date 实例表示。 auto_now ,每次保存对象时自动设为当前日期 ;auto_now_add ,创建对象时自动设为当前日期。
DateTimeField日期和时间,datetime.datetime 实例表示。可选参数:auto_now ,每次保存对象时自动设为当前日期 ;auto_now_add ,创建对象时自动设为当前日期。
EmailField类似CharField ,可用EmailValidator 验证输入。max_length 的默认值为 254
FileField文件上传字段
FilePathField类似 CharField ,限定只能在文件系统中的特定目录里选择文件
ImageField继承FileField ,主要是验证上传的对象是不是有效的图像。增加了 height 和 width 两个属性。需要Pillow库
4. 表单模板

如果个人网站中需要输入数据,则需要使用到表格
Django提供了工具和库可以为其构建表单来接受输入数据并且处理后响应输入数据

在HTML中的表单,都是以

...

Django处理表单数据的过程:试图获取请求,执行操作(从模型中读取数据),生成并返回HTML页面中(传递一个包含显示数据的上下文)

表单处理更加详细的过程:

  • 默认表单(可能有空白字段或者初始值)还未被绑定
  • 提交数据,将其绑定到表单(需要重新显示表单)
  • 清理之前的数据并且验证数据

如果数据无效(显示某个字段的错误消息)
如果数据有效,执行下一步操作(保存数据还是发送邮件等)
完成操作后,会重定向到另外一个页面

表单分为两种:GET和POST
一般GET请求方式是通过url的连接方式,一般通过?占位符的数据拼接到url。其缺点就是不安全
POST请求方式是将其表单数据打包,通过编码的形式进行传输到服务器,服务器接收之后对其响应

4.1 Django Form类

关于表单类主要有两个,一个是django.forms.Form 或其子类创建django.forms.ModelForm(这个类对其BaseForm继承的功能细节比较少,此处不讲,但直接添加或编辑Django模型,可以省下很多时间)

该组件核心是这个Django Form类,Form类表述一种形式并确定其工作方式和外观
模型类的字段映射到数据库字段,表单类的字段映射到HTML表单元素

实例化、处理以及呈现表单主要通过如下步骤:

  • 视图层获取(数据库获取)
  • 传递给模板上下文(之后扩展为HTML表单)

其构建形式如下:(创建一个简单的表单以此获取用户名)

通过your name这个action动作,使用post将其表单数据返回到URL,如果模板上下文中还有current_name这个变量,将勇气来填充your_name这个变量

form类书写格式:

from django import forms

class NameForm(forms.Form):
# 字段最大允许长度由max_length定义,在html格式中,定义是100(所以浏览器要放置用户输入超过这个数量)
    your_name = forms.CharField(label='Your name', max_length=100)

怎么放置超出这个数量限制,主要通过服务器验证表单
Form实例有一个is_valid()方法(所有字段验证程序),如果有效,则返回true,而且表单的数据都是放在cleaned_data属性
表单具体如下:



具体其逻辑层面的代码:

from django.http import HttpResponseRedirect
from django.shortcuts import render

from .forms import NameForm

def get_name(request):
    # 请求为post
    if request.method == 'POST':
        # 创建一个表单实例,并填充来自请求的数据。也就是将数据绑定到表单
        form = NameForm(request.POST)
        # 验证数据合法
        if form.is_valid():
            # 合法则通过数据,cleaned_data属性中找到所有经过验证的表单数据
            # 之后将其http重定向发送到浏览器
            return HttpResponseRedirect('/thanks/')

    # 不是post则不给表单实例
    else:
        form = NameForm()

	# 上面的数据是post,但是数据无效,则会返回带有表单的的模板,表单未绑定,而是将其先前提交的数据填充入内
    return render(request, 'name.html', {'form': form})

关于其html的表单:

{% csrf_token %} {{ form }}

表单内的字段以及所有属性都通过Django模板语言进行压缩成为html:{{ form }}

通过以上的代码模块,可以知道一些函数知识点:

  • is_valid() 验证数据是否合法
  • cleaned_data属性中找到所有经过验证的表单数据
  • is_bound验证表单是否绑定了数据
4.2 表单渲染

在html界面中,渲染的画面需要自已加标签,本身form表单的标签,都要自已提供submit以及form标签等

如果还有其他的渲染选项,可通过如下:

  • {{ form.as_table }}将它们呈现为包装在 标签中的表格单元格
  • {{ form.as_p }}将它们包裹在

    标签中

  • {{ form.as_ul }}将它们包裹在
  • 标签中

以上这些都需要自已提供

或
    元素

    如果需要手动渲染表单,可以不让Django进行解压缩表单字段,例如{{ form.name_of_field }}

    {{ form.non_field_errors }}
    
    {{ form.subject.errors }} {{ form.subject }}
    {{ form.message.errors }} {{ form.message }}
    {{ form.subject.errors }} {{ form.subject.label_tag }} {{ form.subject }}
    • {{ form.non_field_errors }}显示错误信息列表,显示成为无序列表
    5. 视图

    视图函数主要是接受web请求并且返回web响应(放在哪里都可以,一般放在views.py)

    视图层中有两个重要的对象:HttpRequest 请求对象(简称 request 对象)与响应对象(HttpResponse)

    request对象
    以下GET与POST都是类似字典的对象
    通过GET请求:

    def manong(request):
        name = request.GET.get("name")
        return HttpResponse('姓名:{}'.format(name))
    

    通过POST方法:

    def manong(request):
        name = request.POST.get("name")
        return HttpResponse('姓名:{}'.format(name))
    

    通过body传参(在非HTTP中用的比较多,例如:二进制图片、XML、Json 等)

    def manong(request):
        name = request.body
        print(name)
        return HttpResponse("码农研究僧")
    

    通过path传参
    获取URL的路径部分,数据类型是字符串

    def manong(request):
        name = request.path
        print(name)
        return HttpResponse("码农研究僧")
    

    通过method传参:具体和上面一样,换成request.method即可(获取当前请求的方式,数据类型是字符串,且结果为大写。)

    HttpResponse 对象
    主要的三种响应形式有:HttpResponse()、render()、redirect()

    def manong(request):
    	# 可以返回文本(以字符串形式)
        # return HttpResponse("码农研究僧")
    	# 字符串也可返回html标签
        return HttpResponse("码农研究僧")
    
    
    # 返回文本
    # 第一个参数为 request
    # 第二个参数为字符串(页面名称)
    # 第三个参数为字典(可选参数,向页面传递的参数)
    def manong(request):
        name ="码农研究僧"
        return render(request,"manong.html",{"name":name})
    
    # 重定向,跳转新页面,一般用于 form 表单提交后
    def manong(request):
        return redirect("/index/")
    

    render 和 redirect 是在 HttpResponse 的基础上进行了封装:

    • render:底层返回的是 HttpResponse 对象
    • redirect:底层继承的是 HttpResponse 对象
    6. 路由

    路由主要是URL与Django建立映射关系

    Django1.1.x 使用的版本还是url方法(目前大部分公司还用的这种)
    对于这种版本需要自己手动添加正则首位限制符号

    from django.conf.urls import url # 用 url 需要引入
    
    urlpatterns = [
        url(r'^admin/$', admin.site.urls),
        url(r'^index/$', views.index), # 普通路径
        url(r'^articles/([0-9]{4})/$', views.articles), # 正则路径
    ]
    

    Django2.2.x之后的版本都是使用path以及re_path

    • path:用于普通路径,不需要自己手动添加正则首位限制符号,底层已经添加
    • re_path:用于正则路径,需要自己手动添加正则首位限制符号
    from django.urls import re_path # 用re_path 需要引入
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index), # 普通路径
        re_path(r'^articles/([0-9]{4})/$', views.articles), # 正则路径
    ]
    

    正则路径的分组可以分为无名分组和有名分组,注意事项是views的形参名要与url的组名一致
    无名分组按位置传参,一一对应(除了request,去他形参数量要与urls的分组一致)

    # urls
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path("^index/([0-9]{4})/$", views.index),
    ]
    
    # view
    from django.shortcuts import HttpResponse
    
    def index(request,year):
        print(year) # 一个形参代表路径中一个分组的内容,按顺序匹配
        return HttpResponse('码农研究僧')
    

    有名分组:(?P<组名>正则表达式),传参与位置顺序无关

    # urls
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path("^index/(?P[0-9]{4})/(?P[0-9]{2})/$", views.index),
    ]
    
    # view
    from django.shortcuts import HttpResponse
    def index(request, year, month):
        print(year,month) # 一个形参代表路径中一个分组的内容,按关键字对应匹配
        return HttpResponse('码农研究僧')
    

    有名分组的路由分发(主要是因为多个app共用一个urls,后期不好维护),使得每个app目录都有自已的urls

    # 总的urls
    from django.contrib import admin
    from django.urls import path,include # 从 django.urls 引入 include
    urlpatterns = [
        path('admin/', admin.site.urls),
        path("app01/", include("app01.urls")),
        path("app02/", include("app02.urls")),
    ]
    
    # 第一个urls
    from django.urls import path,re_path 
    from app01 import views # 从自己的 app 目录引入 views 
    urlpatterns = [ 
        re_path(r'^login/(?P[0-9]{2})/$', views.index, ),
    ] 
    
    # 第二个urls
    from django.urls import path,re_path
    from app02 import views # 从自己的 app 目录引入views 
    urlpatterns = [ 
        re_path("^xxx/(?P[0-9]{4})/$", views.xxx), 
    ]
    

    后期的维护中还有一个点,如果更改了url,后期不好维护,所以使用反向解析

    • 普通路径:
      使用name其一个别名
    # urls
    path("login1/", views.login, name="login")
    
    # views,通过反向解析
    return redirect(reverse("login"))
    
    # 在模板html代码中,通过 {% url "路由别名" %} 反向解析。
    
    • 正则路径:(无名分组)
    # urls
    re_path(r"^login/([0-9]{2})/$", views.login, name="login")
    
    # views
    return redirect(reverse("login",args=(10,)))  # args=(符合正则匹配的参数,)
    
    # 在templates中的html利用反向解析
     
    
    • 正则路径(有名分组)
    # urls
    re_path(r"^login/(?P[0-9]{4})/$", views.login, name="login")
    
    # views
    return redirect(reverse("login",kwargs={"year":3333})) # kwargs={"分组名":符合正则匹配的参数}
    
    # 在templates中的html利用反向解析
    
    

    接下来引入另外一个概念:命名空间(因为每个app目录的URL定义的相同路由的别名,会导致URL解析错误)

    普通路径:include(("app名称:urls","app名称"))
    示例代码:

    path("app01/", include(("app01.urls","app01"))) 
    path("app02/", include(("app02.urls","app02")))
    

    之后在代码模块中这么引用:

    # urls
    path("login/", views.login, name="login")
    
    # views
    # reverse("app名称:路由别名")
    return redirect(reverse("app01:login")
    
    # templates中的html使用别名
     # {% url "app名称:路由别名" %}
    

    Django允许根据需要涉及URL,需要创建一个URLconf的python配置模块,并且URL的路径表达式到python函数(视图函数)的映射

    示例URL的配置文件:

    from django.urls import path
    ​
    from . import views
    ​
    urlpatterns = [
        path('articles/2003/', views.special_case_2003),
        path('articles//', views.year_archive),
    ]
    
    • 要从URL中捕获值(可以包括路径转换器),需要使用尖括号
    • 前置URL无需添加斜杆,但是后置URL需要添加斜杆
    • URL的匹配通过顺序进行

    上面提到的路径转换器,大致都有如下:

    • int 匹配零或正整数
    • slug 匹配有ASCII字母或者数字以及连字符和下划线字符组成的任何条形字符串
    • uuid 匹配格式化的UUID
    • str 匹配任何非空字符串,但除了’/’
    • path 匹配任何非空字符串,包括’/’

    如果urlpatterns包含其他的url模块,则需要通过include引入

    from django.urls import include, path
    ​
    urlpatterns = [
        path('community/', include('aggregator.urls')),
    ]
    

    或者以下示例:

    from django.urls import include, path
    ​
    # 取别名
    from apps.main import views as main_views
    from credit import views as credit_views
    ​
    extra_patterns = [
        path('reports/', credit_views.report),
    ]
    ​
    urlpatterns = [
        path('', main_views.homepage),
        path('help/', include('apps.help.urls')),
        path('credit/', include(extra_patterns)),
    ]
    

    上面的链接,访问的/credit/reports/URL将由credit_views.report()处理

    包括使用额外的参数填充url以及include中等等
    详情链接可看:
    W3Cschool 的 处理 HTTP请求
    官网对此部分的讲解

    7. Auth组件

    这个组件一般用在用户的登录注册上

    导入代码模块:

    # 对应数据库
    from django.contrib.auth.models import User
    

    通过代码生成数据库的数据
    主要代码如下:

    # 明文
    User.objects.create(username='码农研究僧',password='123')
    
    # 密文
    User.objects.create_user(username='码农研究僧',password='123')
    

    对应的函数讲解:

    • create():创建一个普通用户,密码是明文的。
    • create_user():创建一个普通用户,密码是密文的。
    • create_superuser():创建一个超级用户,密码是密文的,要多传一个邮箱 email 参数。

    以上三个函数的参数都有username、password

    数据库的数据已经创建好了,通过代码模块验证
    需要导入如下模块:(如果验证成功,会返回用户对象,否则为none)

    from django.contrib import auth
    

    验证数据的代码模块:

    # 返回的request为用户对象
    def login(request):
        if request.method == "GET": 
            return render(request, "login.html")
            
        username = request.POST.get("username")
        password = request.POST.get("pwd")
        # 此处为验证码
        valid_num = request.POST.get("valid_num") 
        # 传入数据的时效
        keep_str = request.session.get("keep_str")
        if keep_str.upper() == valid_num.upper():
            user_obj = auth.authenticate(username=username, password=password)
            print(user_obj.username)
    

    在上面的代码模块中,验证成功后加以登录通过
    完整代码如下:

    def login(request):
        if request.method == "GET":
            return render(request, "login.html")
        username = request.POST.get("username")
        password = request.POST.get("pwd")
        valid_num = request.POST.get("valid_num")
        keep_str = request.session.get("keep_str")
        if keep_str.upper() == valid_num.upper():
            user_obj = auth.authenticate(username=username, password=password)
            print(user_obj.username)
    
            if not user_obj:
                return redirect("/login/")
            else:
    
                auth.login(request, user_obj)
                # 此行代表如果还未登陆的时候  输入index界面,直接返回自定义的界面中
                path = request.GET.get("next") or "/index/"
                print(path)
                # 重定向到新网页页面
                return redirect(path)
        else:
            return redirect("/login/")
    

    本身上面的代码模块都是以session进行存储,如果要清空这个是session的数据,需要将其user赋值为匿名用户
    主要的代码函数如下:

    def logout(request):
        ppp = auth.logout(request)
        print(ppp) # None
        return redirect("/login/")
    
    8. Cookie和Session

    关于Cookie和Session这两个东西,一直都是经典中的经典

    本身HTTP是一种无状态的协议(每次登录检索的时候,都是单独连接到web服务器,服务器不保留任何的数据)

    这一部分的知识,学习链接主要用这个比较多:菜鸟教程的代码模块
    Django设置Cookie
    代码如下:

    # 设置Cookie
    rep.set_cookie(key,value,...) 
    rep.set_signed_cookie(key,value,salt='xxx',...)
    
    # 获取Cookie
    request.COOKIES.get(key)
    
    # 删除Cookie
    rep =HttpResponse || render || redirect 
    rep.delete_cookie(key)
    

    配合实际例子的代码模块:

    # ==models.py==
    class UserInfo(models.Model):
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
    
    # ==urls.py==
    from django.contrib import admin
    from django.urls import path
    from cookie import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('login/', views.login),
        path('index/', views.index),
        path('logout/', views.logout),
        path('order/', views.order)
    
    # ==views.py==
    def login(request):
        if request.method == "GET":
            return render(request, "login.html")
        username = request.POST.get("username")
        password = request.POST.get("pwd")
    
        user_obj = models.UserInfo.objects.filter(username=username, password=password).first()
        print(user_obj.username)
    
        if not user_obj:
            return redirect("/login/")
        else:
            rep = redirect("/index/")
            rep.set_cookie("is_login", True)
            return rep
           
    def index(request):
        print(request.COOKIES.get('is_login'))
        status = request.COOKIES.get('is_login') # 收到浏览器的再次请求,判断浏览器携带的cookie是不是登录成功的时候响应的 cookie
        if not status:
            return redirect('/login/')
        return render(request, "index.html")
    
    
    def logout(request):
        rep = redirect('/login/')
        rep.delete_cookie("is_login")
        return rep # 点击注销后执行,删除cookie,不再保存用户状态,并弹到登录页面
       
    def order(request):
        print(request.COOKIES.get('is_login'))
        status = request.COOKIES.get('is_login')
        if not status:
            return redirect('/login/')
        return render(request, "order.html")
    

    以下三个界面如下:

    //login.html
    
    
    
        
        Title
    
    
     
    用户登录
    
        {% csrf_token %}
        

    用户名:

    密码:

    //index.html Title

    index 页面。。。 注销 //order.html Title

    order 页面。。。 注销

    Django Session
    Seesion不一样的点,就是数据都是保存在数据库中
    第一次请求的时候服务器会返回一个sessionid(服务器会返回一个sessionid的随机字符串),第二次请求的时候根据sessionid来判断是哪个用户执行操作

    关于Django的session,一共有三个字段:

    • session_key:随机字符串,sessionid的值
    • session_data:用户的信息,即多个 request.session[“key”]=value,且是密文。
    • expire_date:记录的过期时间(默认14天)

    django.session 表中保存的是浏览器的信息,而不是每一个用户的信息。 因此, 同一浏览器多个用户请求只保存一条记录(后面覆盖前面),多个浏览器请求才保存多条记录。

    # session设置
    request.session["key"] = value
    
    # session获取
    request.session.get('key')
    
    # 删除session的整条记录(包括 session_key、session_data、expire_date 三个字段)
    request.session.flush()
    
    # 删除 session_data 里的其中一组键值对
    del request.session["key"]
    

    具体完整的代码:结合上面部分Cookie的代码模块:

    # ==urls.py
    from session import views as session_views
    
    urlpatterns = [
        path('session_login/', session_views.login),
        path('s_index/', session_views.s_index),
        path('s_logout/', session_views.s_logout),
    ]
    
    
    # == views.py
    def login(request):
        if request.method == "GET":
            return render(request, "login.html")
        username = request.POST.get("username")
        password = request.POST.get("pwd")
    
        user_obj = models.UserInfo.objects.filter(username=username, password=password).first()
        print(user_obj.username)
    
        if not user_obj:
            return redirect("/session_login/")
        else:
            request.session['is_login'] = True
            request.session['user1'] = username
            return redirect("/s_index/")
    
    
    def s_index(request):
        status = request.session.get('is_login')
        if not status:
            return redirect('/session_login/')
        return render(request, "s_index.html")
    
    
    def s_logout(request):
       # del request.session["is_login"] # 删除session_data里的一组键值对
        request.session.flush() # 删除一条记录包括(session_key session_data expire_date)三个字段
        return redirect('/session_login/')
        
    

    模板文件的html代码

    
    
    
        
        Title
    
    
    

    session_index 页面。。。{{ request.session.user1 }} 注销

    9. Nginx与uwsgi部署配置

    关于这一部分的讲解可看我之前的文章:
    uwsgi启动django以及uwsgi.ini的配置参数详解

    如果对其中的Nginx不大了解,详情可看我之前这些文章:
    Nginx配置静态网页访问(图文界面)
    Nginx从入门到精通(全)

    转载请注明:文章转载自 www.mshxw.com
    我们一直用心在做
    关于我们 文章归档 网站地图 联系我们

    版权所有 (c)2021-2022 MSHXW.COM

    ICP备案号:晋ICP备2021003244-6号