Search code examples
javascriptpython-3.xdjangoformsdjango-forms

Error 500 rom Djanjo when trying to send my form data in JavaScript to my Django Url


I am trying to build a ToDo List in Djanjo and I am having issues while trying to build the edit view functionality, below is my home.html file

<div class="col-md-7 col-lg-7" style="height: 450px; overflow: scroll;">
                <!-- List of all the tasks for the day -->

                {% for task in tasks %}

                <div class="card m-1">
                    <div class="card-body">
                        <span id="task_{{ task.pk }}_text">{{ task.task }}</span>
                        <span style="position: relative; float: right;">
                            <a href="{% url 'mark_as_done' task.pk %}"class="btn btn-success"><i class="fa fa-check"></i> Mark as Done</a>
                            <a href="{% url 'delete_task' task.pk %}" class="btn btn-danger"><i class="fa fa-trash"></i></a>
                            <!-- When this button is clicked, a textbox/form will appear, after it appears and you press submit task
                                is updated -->
                            <a onclick="showTextBox('{{ task.pk }}')" class="btn btn-primary"><i class="fa fa-pencil"></i></a>
                            <form id="textbox_{{ task.pk }}" onsubmit="saveValue(event, '{{ task.pk }}')" method="post">
                                {% csrf_token %}
                                <input type="text" id="inputValue_{{ task.pk }}" name="edited_task" placeholder="Update task">
                                <input type="submit" value="Submit">
                            </form>
                        
                        </span>
                    </div>
                </div>
               
                {% endfor %}

            </div>``

Next is my script, where I try to send the data to the backend

 <script>

   
        function showTextBox(key){
            /*console.log(100);
            console.log(`textbox_${key}`);*/
            var textbox = document.getElementById(`textbox_${key}`);
            textbox.classList.toggle('hidden-textbox');
        }

        function saveValue(event,key){
            /*each task object has a primary key associated to it*/
            event.preventDefault();
            var primary_key=key;
            var enteredValue = document.getElementById(`inputValue_${primary_key}`).value;
           const base="{% url 'edit' 123 %}".slice(0, -4);
           const url=`${base}${primary_key}/`;
            fetch(url, {
            method: 'POST',
            headers: {
                        'Content-Type': 'application/json',
                        'X-CSRFToken': '{{ csrf_token }}'
                    },
        body: JSON.stringify({ value: enteredValue }),
      })
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => console.error('Error:', error));
      
        }

      
   
    </script>

Below is my urls.py

from django.urls import path
from . import views

urlpatterns=[

    path('addTask/',views.addTask, name="addTask"),
    path('mark_as_done/<int:pk>',views.mark_as_done, name="mark_as_done"),
    path('mark_as_undone/<int:pk>',views.mark_as_undone, name="mark_as_undone" ),
    path('edit/<int:pk>/',views.edit, name="edit"),
    path('delete_task/<int:pk>/',views.delete_task, name="delete_task")
]

below is the views.py

def edit(request,pk):
     
     enteredValue= request.POST.get('edited_task')
     get_task=get_object_or_404(Task,pk=pk)
     get_task.task=enteredValue
     get_task.save()
     return redirect('home')
        

and last but not least is the models.py

from django.db import models

# Create your models here.
class Task(models.Model):
    task = models.CharField(max_length=300)
    is_completed= models.BooleanField(default=False)
    created_at=models.DateTimeField(auto_now_add=True)
    updated_at=models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.task

Everything bar the edit function is working as intended. Any ideas on what the issue could be?

I tried trouble shooting and debugging the code, and I think it may have to do with the url in my fetch, but I have tried so many different variations and nothing is working. I want the task to be changed to whatever you submit in the form. enter image description here

enter image description here


Solution

  • It seems that the issue IntegrityError will be raised if your enteredValueis of None type. Make sure you are sending in valid value.

    HANDLE JSON PAYLOAD

    In addition to, modify your edit view. Since you are not using forms directly but via fetch api, you cannot use request.POST.get to get your edited_task data as this will only work if your content_type is set to application/x-www-form-urlencoded. Now, you can change your content type in your javascript and also your payload encoding if you want.

    But since you are opting to use application/json you have to extract the json payload from the request.body attribute instead like this:

    import json # do this at the top
    from django.views.decorators.http import require_POST # move to top
    
    @require_POST
    def edit(request,pk):
        
        data = json.loads(request.body)
        enteredValue= data.get('edited_task')
        get_task=get_object_or_404(Task,pk=pk)
        
        if enteredValue is not None:
            get_task.task = enteredValue
            get_task.save()
            get_task.task=enteredValue
            get_task.save()
        return redirect('home')
    

    This way you will only update the task if a non-NULL value is provided which will avoid the not NULL CONSTRAINT error.

    Also, in your javascript call (fetch api), your payload does not have the correct key. Your view is expecting edited_task.

    Change this portion of the code:

    body: JSON.stringify({ value: enteredValue }),
    

    To this:

    body: JSON.stringify({ edited_task: enteredValue }),