Django - 如何处理前端的ajax form submit 请求?通过json返回处理结果,不要重定向(redirect)

问题背景

在web应用开发中,经常遇到需要诸如用户注册提交个人信息,或者录入商品信息的需求。在浏览器上一般以一个Form表单来包含用户所有需要输入的控件。那么浏览器需要在用户输入完所有信息之后, 将表单里面的相关数据传送给后台,完成数据的录入。

Form submit

在火狐的开发者教程中,对Form submit有很好的说明和解释mozilla's sending and retrieving form data。 在文中有提到, form表单中的action定义了表单数据将会被发往什么地方。说到这里, 就不得不提一下Post/Redirect/Get

PRG都被上升到了防止表单重复提交数据的一种Web设计模式。 说的是应用在比如像在电商提交订单这种场景下,总不能让客户重复提交订单吧。字面意思是,后端在收到用户提交的表单数据,并在正确处理之后, 应该让前端重定向到另外一个URL。 就笔者看来,虽然并不能完全理解,但总之对于什么设计模式, 什么最佳实践,还是应该心存敬畏,能遵从的就遵从。

Ajax submit

对于使用ajax来提交form表单, 请先看一下以下链接。

Ajax提交是浏览器在后台发送请求至服务器, 也是在后台接受到服务器返回的结果再做处理;
Form submit处理是在提交数据之后, 后台返回重定向命令, 浏览器再收到之后,去访问命令中指明的URL。

另外Ajax是部分刷新浏览器, 无法处理重定向命令。

问题: Reverse for *** not found. *** is not a valid view function or pattern name.

说了这么多, 是因为笔者在Django后台处理ajax上传的表单数据的时候, 心心念念的要实现重定向/PRG。
在使用redirect方法的时候,出现了该问题,在网上搜索了一会,发现大家比较少遇到该问题,主要搜索到的信息是在template中使用url的时候相关的信息。

  • urls.py
urlpatterns = [
    url(r'^$', views.SkuView.as_view(), name='sku'),
    # download sku template
    url(r'^download/$', views.download, name='download'),
    # sku import / add
    url(r'^skuimport/$', views.skuimport.as_view(), name='skuimport'),

    #  book query 
    url(r'^book/query/$', views.books.as_view(), name='books'),

    # add book 
    url(r'^add/$', views.addBook.as_view(), name='addBook')

]
  • views.py
class addBook(generic.View):
    def get(self, request):
        if request.method == "GET":
            print "addBook get GET reqeuest"
            dumpRequest(request)
            return render(request, 'p_bookAdd.html');

    def post(self, request):
        if request.method == "POST":
            error = ''
            success = ''
            dumpRequest(request)
            form = bookAddForm(request.POST)
            if form.is_valid():
                isbn = form.cleaned_data['isbn']
                if Book.objects.filter(isbn = isbn).exists():
                    error = "ISBN %d book exist !" %(isbn)
                else:
                    success = "True"
                    b = Book(**form.cleaned_data)
                    b.save()

                resp = {
                    'success': success,
                    'error': error
                }
                return redirect('addBook')

Django报错的信息如下:

Internal Server Error: /sku/add/
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11.9-py2.7.egg/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11.9-py2.7.egg/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11.9-py2.7.egg/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11.9-py2.7.egg/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11.9-py2.7.egg/django/views/generic/base.py", line 88, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/fall4u/PycharmProjects/Django-metronic-learn/sku/views.py", line 111, in post
    return redirect('addBook')
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11.9-py2.7.egg/django/shortcuts.py", line 56, in redirect
    return redirect_class(resolve_url(to, *args, **kwargs))
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11.9-py2.7.egg/django/shortcuts.py", line 147, in resolve_url
    return reverse(to, args=args, kwargs=kwargs)
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11.9-py2.7.egg/django/urls/base.py", line 91, in reverse
    return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
  File "/usr/local/lib/python2.7/dist-packages/Django-1.11.9-py2.7.egg/django/urls/resolvers.py", line 497, in _reverse_with_prefix
    raise NoReverseMatch(msg)
NoReverseMatch: Reverse for 'addBook' not found. 'addBook' is not a valid view function or pattern name.

其实报错原因已经指出的很明显呢, 就是redirect的参数不对, 看起来应该不是addBook。
但是让人疑惑的是官方文档给出的例子就是如此,没有更多其他信息。

解决办法

将redirect的参数改为0return redirect('sku:addBook'),看来还是命名空间的问题。

Django 处理ajax form 请求

言归正传, Django处理form请求, 一般按照以下步骤处理

  1. 验证form数据请求是否合法(is_valid)
  2. 处理form数据,比如保持数据库什么的
  3. 构造json数据返回
def post(self, request):
    if request.method == "POST":
        error = ''
        success = ''
        form = bookAddForm(request.POST)
        if form.is_valid():
            isbn = form.cleaned_data['isbn']
            if Book.objects.filter(isbn = isbn).exists():
                error = "ISBN %d book exist !" %(isbn)
            else:
                success = "True"
                b = Book(**form.cleaned_data)
                b.save()
            resp = {
                'success': success,
                'error': error
            }
            return HttpResponse(json.dumps(resp), content_type="application/json")
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,475评论 4 372
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,744评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,101评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,732评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,141评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,049评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,188评论 2 320
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,965评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,716评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,867评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,341评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,663评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,376评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,200评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,990评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,179评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,979评论 2 279

推荐阅读更多精彩内容