0

I know this question may be duplicates of many in stackoverflow. But those didn't help me out. I tried this but didn't succeed without refreshing.

My models.py is:

class Messages(models.Model):
    id = models.CharField(max_length=8, primary_key=True)
    messages = models.TextField()

This is my html

    <form action="{% url 'messages' %}" method="post" id="new_message_form">
        {% csrf_token %}
        <label for="">message</label><br>
        <textarea id="message" cols="30" rows="10"></textarea><br>
        <button type="submit">Submit</button>
    </form>

This is my views.py:

def messages(request):
    if request.method == "POST":
        message = Messages()
        message.messages = request.POST['message']
        message.save()
        return redirect('messages')

    return render(request, 'app/messages.html', context)

And this is my script:

    $(document).on('submit', '#new_message_form', function(e){
        e.preventDefault();
        $.ajax({
            type: 'POST',
            url: '/messages/',
            data: {
                message: $('#message').val(),
                csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
            },
            success:function(){
                alert("New message created!")
            }
        });
    });

This results in MultiValueDictKeyError

Instead I tried

message.messages = request.POST.get('message', False)

That only gets the value from the input and passes. But I cannot submit it without refreshing. Can anyone help me?

EDIT 1 - MultiValueDictKeyError

Internal Server Error: /messages/
Traceback (most recent call last):
  File "C:\Users\mowli\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\utils\datastructures.py", line 76, in __getitem__
    list_ = super().__getitem__(key)
KeyError: 'message'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\mowli\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\mowli\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\mowli\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\mowli\Desktop\Projects\gcepac\app\views.py", line 17, in messages
    message.messages = request.POST['message']
  File "C:\Users\mowli\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\utils\datastructures.py", line 78, in __getitem__
    raise MultiValueDictKeyError(key)
django.utils.datastructures.MultiValueDictKeyError: 'message'
[16/Apr/2020 18:12:30] "POST /messages/ HTTP/1.1" 500 90361

EDIT 2 Actually the form is not even submitted when using this

message.messages = request.POST.get('message', False)

This submits the form with the value 'False' in the db. Once the form is submitted I should get an alert right? So please omit this part.

Community
  • 1
  • 1
Mowli
  • 67
  • 7

2 Answers2

1

Solution 1

Let's address the problem, There're 2 solutions. The easy one which is just a better solution to remove useless pain. put the script in your HTML file, And use this line

csrfmiddlewaretoken: '{%csrf_token%}'

instead of

csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),


Solution 2

The other solution is fixing your own solution. AJAX buttons are not submit buttons, They are just buttons, Remove the action from the form and change the button type to button and it should work.


EDIT: The problem is not in the csrf_token, However I wanted to show the first solution as an easier way to achieve what you need.


BUG 2 Why is this not working, I've answered this before
Ahmed I. Elsayed
  • 2,013
  • 2
  • 17
  • 30
  • Since I am already using the script inside a html form, Solution 1 didn't work. If I am going wrong with `csrf token`, I think i should get csrf error. And for Solution 2, removing the `action` and changing the type to `button` didn't make any change. Also, I guess the very first parameter `$document.on('submit'....` refers the type `submit` of the button. Am I wrong? – Mowli Apr 16 '20 at 15:34
  • Nope, It refers to the submit event of the form itself, The button just triggers the event – Ahmed I. Elsayed Apr 16 '20 at 15:45
  • Solution 1 didn't work because the `csrf_token` is not the problem as I said in the edit – Ahmed I. Elsayed Apr 16 '20 at 15:46
  • However, the solution didn't work. Do your have any other working methods? – Mowli Apr 17 '20 at 07:12
  • From your answer, I can understand that the newly created object cannot be rendered immedietly, But why isn't the form being submitted? – Mowli Apr 17 '20 at 11:52
  • From my answer, AJAX can't return redirects, It's async, If you return a redirect, It will return the HTML of the page instead of redirecting to the page itself – Ahmed I. Elsayed Apr 17 '20 at 11:59
  • But i still wonder, how did that guy submitted the form in that video! Anyways, Thanks for your time taking awhile. – Mowli Apr 17 '20 at 12:36
  • There's nothing dark going in here, He didn't return a redirect, He returned an HttpResponse – Ahmed I. Elsayed Apr 17 '20 at 12:45
0

I noticed a problem on your script.

csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken').val(),

If you copied that exactly as it is what's causing the error. Try this.

csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
muremwa
  • 35
  • 6