Django知识碎片整理(二)

本文详细介绍了Django中Form的使用,包括as_p、as_table和as_ul方法。接着讲解了如何接收Form数据,使用include指令调用template组件,以及自定义simple_tag和inclusion_tag。此外,还探讨了Django视图的FBV和CBV的区别,request对象的常用属性,以及文件上传的实现过程。
摘要由CSDN通过智能技术生成

碎片一:Django窗体Form的使用

下面是django窗体form的实例:

#!/user/bin/env python
#!encoding=utf-8
from django import forms

'''django窗体应用'''

class ContactForm(forms.Form):
    CITY=[
        ['TP','Taipei'],
        ['TY','Taoyuang'],
        ['TC','Taichuang'],
        ['TN','Tainan'],
        ['KS','Kaohsiung'],
        ['NA','Others'],
    ]

    user_name=forms.CharField(label='您的姓名',max_length=50,initial='李大仁')
    user_city=forms.ChoiceField(label='居住城市',choices=CITY)
    user_school=forms.BooleanField(label='是否在学',required=False)
    user_email=forms.EmailField(label='电子邮件')
    user_message=forms.CharField(label='您的意见',widget=forms.Textarea)

下面是常见的字段格式设置方法:

字段格式名称 用法 说明
CharField CharField(label='您的姓名',max_length=50,initial='李大仁')label为本字段的标签(以下皆同),max_length设置长度为50,initial为字段中的默认值
ChoiceFieldChoiceField(label=‘居住城市’,choices=CITY) 设置下拉式菜单(即<select>标签),后面须与choices参数指定一个二维列表,如程序中的CITY
BooleanFieldBooleanField(label=‘是否在学’,required=False) 布尔值的字段,即checkbox标签,若required设置为False,则此checkbox在输入时也可以不用勾选
EmailFieldEmailField(label=‘电子邮件’) 具email验证功能的字段
CharField+forms.TextareaCharField(label=‘您的意见’,widget=forms.Textarea) 在CharField中以widget=forms.Textarea来扩展称为大量文字输入的字段,即<textarea>标签

在urls下配置相关的pattern,对应到views的函数,然后在views函数下写下函数代码:

def contact(request):
    '''form窗体'''
    form=ContactForm()
    return render(request,'contact.html',{'form':form})

最后编辑contact.html文件

<!-- contact.html -->
{% extends 'base.html' %}
{% block title %}联络管理员{% endblock %}
{% block content %}
    <div class="container">
        {% if message %}
        <div class="alert alert-warning">{{ message }}</div>
        {% endif %}
        <div class="panel panel-primary">
            <div class="panel-heading">
                <form name="my_form" action="." method="post">
                    {% csrf_token %}
                    <h3>写信给管理员</h3>
            </div>
            <div class="panel-body">
                {{ form.as_p }}
            </div>
            <div class="panel-footer">
                <input type="submit" value="提交">
                </form>
            </div>
        </div>
    </div>
{% endblock %}

 在上面我们可以看到利用了变量form与bootstrap的panel进行联合使用,在panel-body中使用到了{{  form.as_p }},下面对此进行介绍:

1、form.as_p:会以<p>段落格式的方式产生窗体的字段内容(但是并不会产生<form>...</form>,还有sumbit按钮也不会产生)

2、form.as_table:会以<table>段落格式的方式产生窗体的字段内容(但是并不会产省<table>...</table>,在网页中要自行加上这两个标签才能得到工整的排版)

3、from.as_ul:会以<ul>段落格式的方式产生窗体的字段内容,与上面相同

碎片二:接收Form的数据信息

先利用if判断请求的类型是否是template中设置的请求类型,如果是则开始检查并处理数据,若不是,那么就维持显示窗体的方式,实例如下:

def contact(request):
    '''form窗体'''
    #判断是否是post请求
    if request.method=='POST':
        form = ContactForm(request.POST)
        #检查数据合法性
        if form.is_valid():
            message='感谢您的来信。'
        else:
            message='请检查您输入的信息是否正确!'
    else:
        form=ContactForm()
        message='每个字段都必须输入...'
    return render(request,'contact.html',{'form':form,'message':message})

可以看到接收Form的数据利用form=ContactForm(request.POST)

碎片三:template模板的组件{% include xxx.html %}

在之前的碎片中,我们学习了template母版的开发以及母版的extends调用,下面介绍template组件的开发与调用

1、组件的开发

下面我们来开发图中的导航栏,当前的导航栏代码还放在母版当中,下面我们需要将这块代码抽离出来

创建一个nav.html文件,编写nav导航的代码,代码如下:

<!--编写导航条组件-->
<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container-fluid">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
                    aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="https://v3.bootcss.com/examples/dashboard/#">图书管理系统</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav navbar-right">
                <li><a href="https://v3.bootcss.com/examples/dashboard/#">Dashboard</a></li>
                <li><a href="https://v3.bootcss.com/examples/dashboard/#">Settings</a></li>
                <li><a href="https://v3.bootcss.com/examples/dashboard/#">Profile</a></li>
                <li><a href="https://v3.bootcss.com/examples/dashboard/#">Help</a></li>
            </ul>
            <form class="navbar-form navbar-right">
                <input type="text" class="form-control" placeholder="Search...">
            </form>
        </div>
    </div>
</nav>

2、组件调用

我们在母版中去调用nav.html文件,调用的nav.html在zujian文件夹下,使用{% include ‘zujian/nav.html’ %}来调用组件

<!--母版-->
<!DOCTYPE html>
<!-- saved from url=(0042)https://v3.bootcss.com/examples/dashboard/ -->
<html lang="zh-CN">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="https://v3.bootcss.com/favicon.ico">

    <title>图书管理系统</title>
    <!-- Bootstrap core CSS -->
    <link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <!-- Custom styles for this template -->
    <link href="/static/dashboard.css" rel="stylesheet">
    <link rel="stylesheet" href="/static/fontawesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="{% block css_url %}{% endblock %}">
</head>

<body>
<!--组件调用-->
{% include 'zujian/nav.html' %}

<div class="container-fluid">
    <div class="row">
        <div class="col-sm-3 col-md-2 sidebar">
            <ul class="nav nav-sidebar">
                <li {% if allusers %}class="active" {% endif %}><a href="/">用户列表<span class="sr-only">(current)</span></a>
                </li>
                <li {% if publishers %}class="active" {% endif %}><a href="/publisherlist/">出版社列表</a></li>
                <li {% if books %}class="active"{% endif %}><a href="/booklist/">书籍列表</a></li>
                <li {% if authors %}class="active"{% endif %}><a href="/authorlist/">作者列表</a></li>
            </ul>

        </div>
        {% block content %}{% endblock %}
    </div>
</div>

<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="/static/jquery-3.3.1.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script src="{% block sctipt_url %}{% endblock %}"></script>

</body>
</html>

注意:如果我们需要在继承母版的html当中调用组件html,那么组件html的调用一定要写在{% block xxx %}{% endblock %}当中才能生效

碎片四:自定义simple_tag

之前我们使用template的template_filter可以定义函数,但是参数只能是固定两个,不能定义多个参数的函数,所以下面介绍使用自定义simple_tag来定义多参数的函数

1、编写以及注册simple_tag自定义函数

#!/user/bin/env python
#!encoding=utf-8
from django import template

#生成实例
register=template.Library()

#申明注册函数
@register.simple_tag(name='mysum')
def mysum(arg1,arg2,arg3):
    '''自定义simple_tag'''
    return '{}+{}+{}'.format(arg1,arg2,arg3)

2、在template模板中调用simple_tag自定义函数,需要先导入mysimple_tag文件,然后调用自定义函数mysum,后面跟三个参数,参数之间利用空格隔开

3、启动服务可以在界面上看到函数运行的结果

碎片五:inclusion_tag代码块返回函数

inclusion_tag指定了一个函数,函数返回值,然后inclusion_tag会以html代码块的形式来渲染返回的值的信息,也就是说,inclusion_tag函数会将返回的值用html代码块来展示

1、自定义inclusion_tag函数

#!/user/bin/env python
#!encoding=utf-8
from django import template

#生成实例
register=template.Library()

#申明inclusion_tag函数,并以html代码块展示
@register.inclusion_tag('inclusion.html')
def getlist(n):
    '''inclusion_tag自定义函数'''
    datalist=[]
    for i in range(n):
        datalist.append(i)
        #将数据返回到inclusion.html代码块中
        return {'datalist':datalist}

2、创建对应的inclusion.html文件,里面使用datalist数据

<ul>
    {% for option in datalist %}
        <li>{{ option }}</li>
    {% endfor %}
</ul>

3、在template文件中调用inclusion_tag函数getlist,先调用指定myinclusion_tag文件,然后调用函数getlist,输入对应的参数10

4、查看界面,可以看到html代码块循环渲染了datalist的数据,并按照html代码块的ul列表展示出来

碎片六:Django视图的FBV和CBV

 1、FBV:function base view,基于函数定义的视图,在django中比较常见,定义一个函数来处理所有的业务逻辑代码,将所有的请求都发往这个函数中,通过逻辑进行相应处理,例如:

def editauthor(request,aid):
    '''编辑作者'''
    error_msg=''
    #获取作者信息
    author=Author.objects.get(id=aid)
    #获取书籍信息
    books=Book.objects.all()
    #判断请求是否是post
    if request.method=='POST':
        try:
            #获取请求数据
            name=request.POST.get('name',None)
            authorbooks=request.POST.getlist('books',None)
            #更新数据
            if len(name)!=0 and len(authorbooks)!=0:
                # 多对多数据的更新,需要先获取一个对象,再进行属性更新,再进行连表更新并保存
                author_obj=Author.objects.get(id=aid)
                author_obj.name=name
                author_obj.book.set(authorbooks)
                author_obj.save()
                return redirect('/authorlist/')
            else:
                error_msg='作者名称、编辑书籍不能为空!'
                return render(request,'editauthor.html',{'author':author,'error_msg':error_msg,'books':books})
        except:
            #更新失败
            error_msg='作者编辑失败,请重新编辑!'
            return render(request,'editauthor.html',{'author':author,'error_msg':error_msg,'books':books})
    return render(request,'editauthor.html',{'author':author,'error_msg':error_msg,'books':books})

FBV视图函数在urls中的配置:

 2、CBV:class base view,基于类定义的视图,定义一个类,然后分别定义接口请求方式的函数,比如get请求函数、post请求函数,当接口收到请求时,会根据请求的方式将请求分配到对应的函数中进行处理,这样做业务逻辑稍微清晰一些,需要导入django.views中的View,实例:

from django.views import View

#创建类CBV
class AddPublisher(View):
    '''出版社添加类'''
    #当借口请求是get时就获取的是get函数
    def get(self,request):
        error_msg=''
        return render(request, 'addpublisher.html', {'error_msg': error_msg})

    #当接口请求是post时就获取的是post函数
    def post(self,request):
        try:
            #获取请求数据
            name=request.POST.get('name',None)
            addr=request.POST.get('addr',None)
            #数据表添加
            if len(name)!=0 and len(addr)!=0:
                Publisher.objects.create(name=name,addr=addr)
                return redirect('/publisherlist/')
            else:
                error_msg='出版社名称、出版社地址不能为空!'
                return render(request,'addpublisher.html',{'error_msg':error_msg})
        except:
            #添加失败
            error_msg='出版社添加失败,请重新添加!'
            return render(request,'addpublisher.html',{'error_msg':error_msg})

CBV视图函数在urls中的配置:调用类名后,需要进行.as_view()处理

碎片七:request对象 

1. request.method    --> 获取请求的方法(GET、POST等)

2. request.GET       --> 通常用来获取URL里面的参数  
                    127.0.0.1:8000/edit_book/?id=1&name=yimi
                    request.GET --> {"id":1, "name":"yimi"}
                    request.GET.get("id")

3. request.POST      --> 用来获取POST提交过来的数据
                    request.POST.get("book_name")

4. request.path_info   --> 获取用户请求的路径(不包含IP和端口和URL参数)

5.request.body  -->请求体,byte类型,原始的request.POST数据(一般都不用)

碎片八:Django上传文件代码

在Django项目中实现文件上传,然后读取文件并生成到指定位置路径下,实例如下:

1、首先创建了上传文件的前端界面:(调用母版模板)

<!--调用母版-->
{% extends 'muban/basehtml.html' %}
{% block content %}
    <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
            <h1 class="page-header">用户列表页</h1>

            <div class="panel panel-primary">
                <!-- Default panel contents -->
                <div class="panel-heading">用户列表 <i class="fa fa-thumb-tack pull-right"></i></div>
                <div class="panel-body">
                    <div class="row" style="margin-bottom: 15px">
                        <div class="col-md-4">
                            <div class="input-group">
                                <input type="text" class="form-control" placeholder="Search for...">
                                <span class="input-group-btn">
                                    <button class="btn btn-default" type="button">搜索</button>
                                </span>
                            </div><!-- /input-group -->
                        </div><!-- /.col-md-4 -->
                        <div class="col-md-1 pull-right">
                            <h4 class="text-center"><a href="/adduser/">新增</a></h4>
                        </div>

                    </div><!-- /.row -->

                    <table class="table table-bordered">
                        <thead>
                        <tr>
                            <th>序号</th>
                            <th>id</th>
                            <th>账号</th>
                            <th>邮箱</th>
                            <th>电话</th>
                            <th>操作</th>
                        </tr>
                        </thead>
                        <tbody>
                            {% for user in allusers %}
        <tr>
        <td>{{ forloop.counter }}</td>
        <td>{{ user.id }}</td>
        <td>{{ user.username }}</td>
        <td>{{ user.email }}</td>
        <td>{{ user.mobile }}</td>
        <td>
            <a class="btn btn-danger" href="/deluser/{{ user.id }}">删除</a>
            <a class="btn btn-info" href="/edituser/{{ user.id }}">编辑</a>
        </td>
        </tr>
    {% endfor %}
                        </tbody>
                    </table>

                    <nav aria-label="Page navigation" class="text-right">
                        <ul class="pagination">
                            <li>
                                <a href="#" aria-label="Previous">
                                    <span aria-hidden="true">&laquo;</span>
                                </a>
                            </li>
                            <li><a href="#">1</a></li>
                            <li><a href="#">2</a></li>
                            <li><a href="#">3</a></li>
                            <li><a href="#">4</a></li>
                            <li><a href="#">5</a></li>
                            <li>
                                <a href="#" aria-label="Next">
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>
                        </ul>
                    </nav>
                </div>

            </div>
        </div>
{% endblock %}

2、 在views中定义上传文件处理的类CBV,接收到文件之后,进行解析读取,然后在指定的路径下写入文件内容

#创建类CBV--文件上传
class UploadFile(View):
    '''上传文件'''
    def get(self,request):
        '''get请求'''
        return render(request,'muban/uploadfile.html')

    def post(self,request):
        '''post请求:
        保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。从内存读取一次,写磁盘一次。
        但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中
        '''
        # 从请求的FILES中获取上传文件的文件名,file为页面上type=files类型input的name属性值
        filename = request.FILES["file_upload"].name
        # 指定文件存放路径
        files_path=os.path.join(os.path.dirname(os.path.dirname(__file__)),'files')
        setfile=os.path.join(files_path,filename)
        # # 在项目目录下新建一个文件
        with open(setfile, "wb") as f:
            # 从上传的文件对象中一点一点读
            for i in request.FILES["file_upload"].chunks():
                # 写入本地文件
                f.write(i)
        return HttpResponse("上传OK")

3、配置urls路径

4、测试:输入指定的路径,然后我们在前端上传文件,然后指定文件存放到指定的位置(在这里我上传到files文件夹中),可以看到在files目录下生成了我在前端上传的文件

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值