0

I have a form that I am trying to implement with Ajax, after inputing some content on the textbox, when I click on the sumbit button using my mouse, everything works fine (page didnt refresh, data posted on database, and new data displayed on the page). But when I try to submit data by pressing enter, the page is displaying only the serialized data from my form (nothing more, html file do not work)and it says in the console:

Resource interpreted as Document but transferred with MIME type application/json: "http://localhost:8000/try/".

current page looks exactly like this after pressing enter button(nothing more):

{"task": {"id": 52, "todo": "wws", "author": 1, "completed": false}}

these are the data that came from my form.

this is my views.py

class TodoList(View):
    def get(self, request):
        todo_list = ToDo.objects.filter(author_id=request.user.id)
        form = AddTodo()
        context = {
            'todo_list': todo_list,
            'form': form,
        }
        return render(request, 'trylangto/try.html', context)

    def post(self, request):
        form = AddTodo(request.POST)
        if form.is_valid():
            form.instance.author_id = request.user.id
            new_form = form.save()
            return JsonResponse({'task': model_to_dict(new_form)}, status=200)
        else:
            return redirect('trylang:todo-list')
        return redirect('trylang:todo-list')

this is my main.js:

$(document).ready(function(){

    $("#createbutton").click(function(){
        var formdata = $("#addtodoform").serialize();

        $.ajax({
            url: $("#addtodoform").data('url'),
            data: formdata,
            type: 'post',
            success: function(response){
                $("#tasklist").append('<div class="card mb-1" ><div class="card-body">'+ response.task.todo +'<button type="button" class="close"><span aria-hidden="true">&times;</span></button></div></div>')
            }
        });
    });
});

and here is my template:

{% extends 'base.html' %}
{% load crispy_forms_tags %}


{% block content %}
    {% if user.is_authenticated %}
        <div class="media content-section">
            <form class="media-body pt-3" method="POST" id="addtodoform" data-url="{% url 'trylang:todo-list' %}">
                {% csrf_token %}
                <legend><h5>add new tasks</h5></legend>
                <fieldset class="form-group ">
                    {{ form|crispy}}
                </fieldset>
                <button class="btn btn-outline-info float-right" type="button" id="createbutton">add</button>
            </form>
        </div>
    {% endif %}

    <div id="tasklist">
        {% for task in todo_list %}
        <div class="card mb-1" >
            <div class="card-body">
                {{task.todo}}
                <button type="button" class="close">
                  <span aria-hidden="true">&times;</span>
                </button>
            </div>
        </div>
        {% endfor %}
    </div>
{% endblock %}

UPDATE: I am including my models.py just in case

class ToDo(models.Model):
    todo = models.CharField(max_length=500)
    date_posted = models.DateTimeField(default=timezone.now, editable=False)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='users')
    completed = models.BooleanField(default=False)


this is what I get on the console when I use console.log(formdata):

csrfmiddlewaretoken=N91OUGSd6kBFkB1E2DMZuMW6qJD7cc3frPprwGMLTuupcg6PKYtt44jA4z5Lx6xX&todo=this%20is%20the%20content%20of%20my%20textbox

1 Answers1

0

You don't need model_to_dict. So, try:

if form.is_valid():
            form.instance.author_id = request.user.id
            new_form = form.save()
            return JsonResponse({'task': new_form}, status=200)
        else:
            return redirect('trylang:todo-list')
        return redirect('trylang:todo-list')

EDIT

You are submitting the form not through ajax. When you click button it was submitting the form. So, e.preventDefault() should do the job.

$(document).ready(function(){

    $("#createbutton").click(function(e){
        e.preventDefault();  <--- You were missing this
        var formdata = $("#addtodoform").serialize();

        $.ajax({
            url: $("#addtodoform").data('url'),
            data: formdata,
            type: 'post',
            success: function(response){
                $("#tasklist").append('<div class="card mb-1" ><div class="card-body">'+ response.task.todo +'<button type="button" class="close"><span aria-hidden="true">&times;</span></button></div></div>')
            }
        });
    });
});
Biplove Lamichhane
  • 3,995
  • 4
  • 14
  • 30
  • hi i tried your answer but i get an error: ```TypeError at /try/ Object of type ToDo is not JSON serializable``` and on the browser's console it says: ```Failed to load resource: the server responded with a status of 500 (Internal Server Error)``` but data were being posted on the database. – newbie programmer Oct 01 '20 at 16:04
  • I have editted. Pls, review. Just change in `js` should do the job. – Biplove Lamichhane Oct 01 '20 at 16:25
  • thanks! now its working! but i did a few things before it worked. 1st, the attribute of my submit button before was ```type='button'``` the video that im following said that it should be ```type=button``` then changed it to ```type='submit'```, still not working, lastly i tried to bring back the ```model_to_dict``` then it worked. any idea why there should be ```model_to_dict``` in the code for it to work? – newbie programmer Oct 01 '20 at 17:23
  • Because [`JSONResponse`](https://docs.djangoproject.com/en/dev/ref/request-response/#jsonresponse-objects), *first* parameter, *data*, should be a *dict* instance. But, `new_form` is model instance. So, we do `model_to_dict`. You can use serializers also to work without `model_to_dict` as said in docs. Also [see](https://stackoverflow.com/questions/21925671/convert-django-model-object-to-dict-with-all-of-the-fields-intact). And, `type=button` was also submitting the form, that's weired. I have no idea about that sadly. – Biplove Lamichhane Oct 02 '20 at 03:30