johnyang

Django中Ajax表单提交

Ajax是以一种与服务器交换数据的技术,可以在不重载整个页面的情况下更新网页的一部分。它也可以运用在Django项目的表单中,与普通的views函数不一样的是:表单所在的网页上必须有JavaScript脚本,该脚本一方面对提交数据给view方法,另一方面根据view返回的response对现有的页面进行调整。

下面是一个简单的例子,通过这个例子,总结其步骤和需要注意的地方。

  • 首先是html
# base.html
<!DOCTYPE html>
<html lang="">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title Page</title>
    <!-- Bootstrap CSS -->
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn\'t work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.3/html5shiv.js"></script>
    <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
    <!-- jQuery -->
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<!-- Bootstrap JavaScript -->
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
{% block body_block %}
{% endblock %}
 </body>
</html>
# testAjax.html
{% extends \'base.html\' %}
{% block body_block %}
<h4>FeedBack</h4>
<div class="row">
    <div id="feedbackmessage">
        Hell
    </div>
</div>
<form  method="POST" id="feedbackform" action=\'{% url "testapp:feedback" %}\'>
    {% csrf_token %}
    <div class="row">
        <div class="col-md-12">
            {{ form.comment }}
        </div>
    </div>
    {{ form.name.as_hidden }}
    {{ form.email.as_hidden }}
    {{ form.gender.as_hidden }}
    <input type="submit" value="Submit feedback" class="btn btn-primary">
</form>

<script>
    $(document).ready(function(){
        $(\'#feedbackform\').submit(function(event){
            event.preventDefault()
            $.ajax({data:$(this).serialize(),
            type:$(this).attr(\'method\'),
            url:$(this).attr(\'action\'),
            success:function(response){
                console.log(response);
                if (response[\'success\']){
                    $(\'#feedbackmessage\').html(\'<div class="alert alert-success"> Successsfully sent feedback</div>\');
                    $(\'#feedbackform\').addClass(\'hidden\');
                };
                if (response[\'error\']){
                    $(\'#feedbackmessage\').html("<div class=\'alert alert-danger\'>"+
                    response[\'error\'][\'comment\']+"</div>");
                }
            },
            error:function (request,status,error){
                console.log(request.responseText);
            }
            })
        })
    })
</script>
{% endblock %}

这里需要注意的是在JQuery下的Ajax的脚本中,event.preventDefault方法必须要调用,因为这个方法意味着阻止元素发生默认行为(详见https://www.runoob.com/jquery/event-preventdefault.html),如果没有阻止的话,ajax技术就没有办法运用,在提交了表单后,页面直接返回view方法返回的response页面,而不会根据ajax的逻辑来修改页面。(ajax简介:https://www.runoob.com/jquery/jquery-ref-ajax.html

  • url
#主urls.py
from django.contrib import admin
from django.urls import include
from django.urls import path

urlpatterns = [
    path(\'admin/\', admin.site.urls),
    path(\'testapp/\',include(\'testapp.urls\',namespace=\'testapp\')) #定义命名空间

]
#app中的urls.py
from django.conf.urls import url 
from testapp import views 
from django.views.generic import TemplateView
app_name=\'testapp\' #定义命名空间
urlpatterns=[
    url(r\'^testDebug\',views.testDebug,name=\'testDebug\'),
    url(r\'^feedback/$\',views.feedback,name=\'feedback\'),
]
  • views.py
def feedback(request):
    if request.POST:
        form=ContactForm(request.POST)
        if form.is_valid():
            return JsonResponse({\'success\':True})
        else:
            return JsonResponse({\'error\':form.errors})
    form=ContactForm(initial={\'email\':\'784@qq.com\',\'name\':\'yy\',\'gender\':\'a\'})
    return render(request,\'testapp/testAjax.html\',{\'form\':form})
  • forms.py
from django import forms 
class ContactForm(forms.Form):
    name=forms.CharField(required=False)
    email=forms.EmailField(label=\'Your Email\')
    comment=forms.CharField(widget=forms.Textarea)
    gender=forms.ChoiceField(choices=((\'a\',\'male\'),(\'b\',\'female\'),(\'c\',\'人妖\')))
    def clean_name(self):
        name=self.cleaned_data.get(\'name\',\'\')
        if \'y\' not in name:
            raise forms.ValidationError(\'y not in name\')
        return name 
image-20200920121757006

填写,提交后:

image-20200920122132177

Django中文件上传

与普通的view函数及

不一样的是:bound form中还需要传入request.FILES, html中的中还应该有enctype=\'multipart/form-data\',该属性规定在发送到服务器之前应该如何对表单数据进行编码,\'multipart/form-data\'即不对字符进行编码,在使用包含文件上传控件的表单中必须使用该值。

  • html
{% extends \'base.html\' %}
{% block body_block %}
<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    <ul>
        {{ form.as_ul }}
    </ul>
    <input type="submit" value="submit img/vedio" class="btn btn-primary">
</form>
{% endblock %}
  • forms.py
class SharingForm(forms.Form):
    video=forms.FileField()
    photo=forms.FileField(widget=forms.ClearableFileInput(attrs={\'multiple\':True}))
    
  • views.py
from django.conf import settings 
def save_upload_file_to_media_root(f):
    with open(\'%s/%s\'%(settings.MEDIA_ROOT,f.name),\'wb+\') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

def uploadFile(request):
    if request.method==\'POST\':
        form=forms.SharingForm(request.POST,request.FILES)
        if form.is_valid():
            for field in request.FILES.keys():
                for formfile in request.FILES.getlist(field):
                    save_upload_file_to_media_root(formfile)
        return HttpResponse(\'OK,Upload successfully\')
    else:
        form=forms.SharingForm()
    return render(request,\'banners/upload.html\',{\'form\':form})

效果:

提交:

查看项目下的media文件夹:

分类:

技术点:

相关文章: