解決済
Djangoで Drag & drop
Django
Web
データベース
2023/03/23 11:19

実現したいこと

Djangoでタスクサイトを作っております。

ドラッグアンドドロップでタスクを移動させる時、

SQL Server のストアドプロシージャを呼び出して、DBに保存したいです。

発生している問題

データベースに保存できてない

具体的にエラーです。

System check identified no issues (0 silenced).
March 05, 2022 - 21:53:02
Django version 2.1.15, using settings 'pjmain.settings'
Starting development server at http://127.0.0.1:8000/  
Quit the server with CTRL-BREAK.
[05/Mar/2022 21:53:05] "GET /todo/mytaskview HTTP/1.1" 200 21840
[05/Mar/2022 21:53:05] "GET /static/Scripts/drag_drop.js?time=202201251100 HTTP/1.1" 304 0
[05/Mar/2022 21:53:06] "GET /static/Scripts/bootstrap.js.map HTTP/1.1" 200 254480
[05/Mar/2022 21:53:06] "GET /static/css/bootstrap.css.map HTTP/1.1" 200 511248
Internal Server Error: /todo/updateList
Traceback (most recent call last):
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\utils\deprecation.py", line 90, in __call__
    response = self.process_request(request)
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\middleware\common.py", line 53, in process_request
    path = self.get_full_path_with_slash(request)
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\middleware\common.py", line 86, in get_full_path_with_slash
    raise RuntimeError(
RuntimeError: You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/todo/updateList/ (note the trailing slash), or set APPEND_SLASH=False in your Django settings.
[05/Mar/2022 21:53:07] "POST /todo/updateList HTTP/1.1" 500 21178

ソースコード

①DBテーブル構成

■DBタスク
CREATE TABLE [dbo].[DBタスク](
	[タスクID] [int] IDENTITY(1,1) NOT NULL,
	[重要事項] [bit] NOT NULL,
	[状態] [nvarchar](50) NULL,
	[タイトル] [nvarchar](100) NULL,
	[期限日時] [datetime2](7) NULL,
	[登録日時] [datetime2](7) NULL,
	[登録者CD] [nvarchar](20) NULL,
	[備考] [nvarchar](max) NULL,
PRIMARY KEY CLUSTERED 
(
	[タスクID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

■DBコラム
CREATE TABLE [dbo].[DBコラム](
	[コラムID] [int] IDENTITY(1,1) NOT NULL,
	[タイトル] [nvarchar](100) NULL,
	[タスク配列] [nvarchar](1000) NULL,
PRIMARY KEY CLUSTERED 
(
	[コラムID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

②Django側

■html and ajax

{% block head %}
    <link href="{% static 'css/workflow.css' %}" rel="stylesheet" />
    <link href="{% static 'css/columns.css' %}" rel="stylesheet" />
    <link rel="stylesheet" href="//code.jquery.com/ui/1.13.1/themes/base/jquery-ui.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <script language="JavaScript">
        $(document).ready(function(){  
            function slideout(){
                setTimeout(function(){
                        $("#response").slideUp("slow", function () {
                    });
                }, 2000);
            }
            
            $("#response").hide();
            $(function() {
                $("#list ul").sortable({ opacity: 0.8, cursor: 'move', update: function() {
                var item_order = new Array();
                $('ul.reorder li').each(function() {
                    item_order.push($(this).attr("id"));
                }); 
                var order_string = 'order='+item_order;
                $.ajax({
                    method: "POST",
                    url: "/todo/updateList",
                    data: order_string,
                    cache: false,
                    success: function(data){    
                        $("#response").html(data);
                        $("#response").slideDown('slow');
                        slideout();
                    }
                });               
                }         
                });
                });
            
        });
    </script>
{% endblock %}
{% block contents %}

<form form method="post" id="frmApply">
    {% csrf_token %}
        <div style="width:300px;">
            <div id="list">
                <div id="response"></div>
                <ul class="reorder">
                    {% for row in list_リスト_コラム %}
                        <li id="{{row.id}}">{{row.タイトル}}
                        <div class="clear"></div>
                        </li>
                    {% endfor %}
                </ul>
            </div>
        </div>
</form>
{% endblock %}

■urls.py

from django.urls import path
from . import views_todo

app_name = 'todo'

urlpatterns = [
    path('mytaskview', views_todo.MyTaskView, name="MyTaskView"),
    path('todo/', views_todo.TaskAdd, name='ToDoRegist'),
    path('updateList/', views_todo.updateList, name="updateList"),
]

■view (※views_todo)

# Import
from ast import In
from distutils.util import strtobool
import os
import pyodbc
import json
import uuid

# From
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .views import *    # 2022/01/23 グエン Add
from datetime import date, datetime
from .models import sortables as Sortable
from django.views.generic import View

today_date = date.today()

def connect_db():
    strconn = 'Driver={ODBC Driver 17 for SQL Server};' + 'Server=momo19;' + 'Database=svn_todo;' + 'UID=sa;' + 'PWD=svn-256'
    # ---------------
    conn = pyodbc.connect(strconn, autocommit=True)
    return conn


@login_required
def MyTaskView(request):
    template_name = 'todo/index.html'

    list_作業者 = Exec_StoredProc_GetList('CAL_リスト_作業者', [request.user.username]) #sel_分類()
    list_リスト_コラム = Exec_StoredProc_GetList('CAL_リスト_コラム',[])

    param = {'list_作業者': list_作業者,
            'list_リスト_コラム': list_リスト_コラム,
            }

    return render(request, template_name, param)

@login_required
def updateList(request):
    conn = connect_db()
    cur = conn.cursor()
    if request.method == 'POST':
        cur.execute("SELECT * FROM DBコラム")    
        number_of_rows = cur.rowcount      
        getorder = request.form['order']    
        print(getorder)
        order = getorder.split(",", number_of_rows)
        print(order)
        count=0  
        for value in order:
            count +=1
            print(count)                       
            cur.execute("UPDATE DBコラム SET タスク配列 = %s WHERE id = %s ", [count, value])
            conn.commit()       
        cur.close()
        
    return HttpResponse("リダイレクト成功")

自分で試したこと

view or urls は何かエラーがあるようで
ご確認よろしくお願い致します。

補足情報

参考にしたサイトです。

https://jqueryui.com/sortable/

回答 10件
login
回答するにはログインが必要です

エラーにあるように、ajaxでupdateListをコールするときにスラッシュが抜けています。

/todo/updateList/

1

ベストアンサーを選択すると、クローズします。

使い方がまだ分からないですが、
どのように、クローズしますか?

解決して良かったです。

クローズお願いします。

1

はる先生、ありがとうございました。

自分で解決しました。

よろしくお願いいたします。

1

updateの文法を入れ見ましたが

まだ、直していないですね。

SQL Server のストアドプロシージャで Updateしたいので、モデルを使わないですね。

1

2つのパラメータが指定されているとエラーが出てますね。

cur.execute("UPDATE DBコラム SET タスク配列 = %s WHERE コラムID = %s ", (count, value))

updateの文法か、モデルを見直してみてください。

1

今まで、少し調整しました。

@csrf_exempt    #2022/03/05 add
def updateList(request):
    conn = connect_db()
    cur = conn.cursor()
    if request.method == 'POST':
        cur.execute("SELECT * FROM DBコラム")    
        number_of_rows = cur.rowcount   
        #getorder = request.form['order']       #2022/03/05 mod
        getorder = request.POST['order']        #2022/03/05 mod
        print(getorder)
        order = getorder.split(",", number_of_rows)
        print(order)
        count=0  
        for value in order:
            count +=1
            print(count)                       
            #cur.execute("UPDATE DBコラム SET タスク配列 = %s WHERE id = %s ", [count, value])
            cur.execute("UPDATE DBコラム SET タスク配列 = %s WHERE コラムID = %s ", [count, value])
            conn.commit()       
        # cur.close()
        result = cur.fetchone()
        cur.close
        conn.close
    return result

以下のエラーになります。

System check identified no issues (0 silenced).
March 06, 2022 - 00:00:06
Django version 2.1.15, using settings 'pjmain.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
3,2,1
['3', '2', '1']
1
Internal Server Error: /todo/updateList/
Traceback (most recent call last):
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 124, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\nguyen\Desktop\PYTHON_開発\Schedule_Todo\Development\20220222_2300_Drag_Drop\todo\views_todo.py", line 70, in updateList
    cur.execute("UPDATE DBコラム SET タスク配列 = %s WHERE コラムID = %s ", [count, value])
pyodbc.ProgrammingError: ('The SQL contains 0 parameter markers, but 2 parameters were supplied', 'HY000')
[06/Mar/2022 00:00:10] "POST /todo/updateList/ HTTP/1.1" 500 21110

上記、Updateの箇所はNGでしょうか。

または、getorder、orderをちゃんと取りました。

        print(getorder)  = 3,2,1
        print(order)  = ['3', '2', '1']

今はrunserverすると、以下のエラーになります。

Internal Server Error: /todo/updateList/
Traceback (most recent call last):
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 124, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\nguyen\AppData\Local\Programs\Python\Python39\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "C:\Users\nguyen\Desktop\PYTHON_開発\Schedule_Todo\Development\20220222_2300_Drag_Drop\todo\views_todo.py", line 60, in updateList
    getorder = request.form['order']
AttributeError: 'WSGIRequest' object has no attribute 'form'
[05/Mar/2022 23:06:48] "POST /todo/updateList/ HTTP/1.1" 500 20962

はる先生、ありがとうございました。
/todo/updateList/
先程、スラッシュを入れてみましたが、エラーが表示しました。

System check identified no issues (0 silenced).
March 05, 2022 - 22:41:50
Django version 2.1.15, using settings 'pjmain.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
[05/Mar/2022 22:41:52] "GET / HTTP/1.1" 200 5524
[05/Mar/2022 22:41:54] "GET /static/css/workflow.css HTTP/1.1" 200 2435
[05/Mar/2022 22:41:54] "GET /static/Scripts/jquery-3.4.1.min.js HTTP/1.1" 200 88145
[05/Mar/2022 22:41:54] "GET /static/Scripts/bootstrap.js HTTP/1.1" 200 144033
[05/Mar/2022 22:41:54] "GET /static/Scripts/portal.js?time=20220123 HTTP/1.1" 200 2519
[05/Mar/2022 22:41:54] "GET /media/media/images/Chelsea.png HTTP/1.1" 200 533385
[05/Mar/2022 22:41:57] "GET /todo/mytaskview HTTP/1.1" 200 21841
[05/Mar/2022 22:41:57] "GET /static/Scripts/todo_modal.js?time=202201251100 HTTP/1.1" 200 4229
[05/Mar/2022 22:41:57] "GET /static/Scripts/drag_drop.js?time=202201251100 HTTP/1.1" 200 0
Forbidden (CSRF token missing or incorrect.): /todo/updateList/
[05/Mar/2022 22:42:03] "POST /todo/updateList/ HTTP/1.1" 403 2556
1