[PYTHON] Ajax in Django (using generic class view)

A search for "Django Ajax" hits some articles, but most of them were function-based views, so I'll explain the code using the generic view.

General-purpose view If you are not familiar with it, let's get started there.

-Introduction to class-based generic views in Django and sample usage -Collect Django's generic class views and mention the implementation

This is my personal opinion, but I think one of the big benefits of adopting Django is the use of class-based generic views. ~~ ** I think this is probably a best practice **. ~~

Finished product image

GitHub-skokado / django_ajax: Django + Ajax sample

The input character string is displayed on the screen.

Decide the specifications easily.

--User accesses / greet with a browser --The value entered in the form (name) is sent by the POST method. -* The destination path of the POST method is the same as the screen display / greet --views.py identifies Ajax request (XMLHttpRequest) and separates it from other processing

1.gif

Code commentary

The components are largely below.

--ʻUrls.py: Routing (URL binding) --forms.py: Define forms for users to enter data --views.py: Describe request processing. --Use the generic view FormView --UseRequest.is_ajax () to identify Ajax requests --Template (ʻindex.html): HTML to display. This article also includes jQuery.

Preparation

Make sure you've created your Django project and Django application properly.

Describe the routing rule in ʻurls.py`.

urls.py

The only path to use is / greet.

django_ajax/urls.py


from django.urls import path

from . import views


urlpatterns = [
    path('greet/', views.GreetView.as_view(), name='greet'),
]

forms.py

Just type name

greeting/forms.py


from django import forms


class GreetForm(forms.Form):
    name = forms.CharField(label='What's your name?')

index.html

--Form part

<Div id =" result "> Hello subordinate element of, [name] 's! The word is added. (That process is described in jQuery)

<h1>Let's Greeting!</h1>
<form action="" method="post">{% csrf_token %}
    {{ form }}
    <button type="submit">Send</button>
</form>

<div id="result">
    <!--Here is the greeting<p>Tag elements are added-->
</div>

--Script part

I think it can be read that the jQuery part also conforms to the above specifications. Also, I need jQuery (not slim), so load it.

<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
//Set an event listener for the submit button. Describe Ajax processing inside
$("form").submit(function(event) {
    event.preventDefault();
    var form = $(this);
    $.ajax({
      url: form.prop("action"),
      method: form.prop("method"),
      data: form.serialize(),
      timeout: 10000,
      dataType: "text",
    })
    .done(function(data) {
        $("#result").append("<p>" + data + "</p>");
    })
});
</script>
ʻindex.html`
<h1>Let's Greeting!</h1>
<form action="" method="post">{% csrf_token %}
    {{ form }}
    <button type="submit">Send</button>
</form>

<div id="result">
    <!-- Will be replaced with inputed text by Ajax -->
</div>

<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script>
//Set an event listener for the submit button. Describe Ajax processing inside
$("form").submit(function(event) {
    event.preventDefault();
    var form = $(this);
    $.ajax({
      url: form.prop("action"),
      method: form.prop("method"),
      data: form.serialize(),
      timeout: 10000,
      dataType: "text",
    })
    .done(function(data) {
        $("#result").append("<p>" + data + "</p>");
    })
});
</script>

views.py

Define one GreetView that inherits from FormView

greeting/views.py


from django.http import HttpResponse
from django.views.generic import FormView

from . import forms

# Create your views here.
class GreetView(FormView):
    template_name = 'index.html'  #Template name(html file name)
    form_class = forms.GreetForm
    success_url = '/greet'

    def post(self, request, *args, **kwargs):
        form = self.get_form(self.form_class)
        if form.is_valid():
            if request.is_ajax():
                """Separate Ajax processing into another method"""
                print('### Ajax request')
                return self.ajax_response(form)
            #Handling POST methods other than Ajax
            return super().form_valid(form)
        #What to do if the form data is incorrect
        return super().form_invalid(form)

    def ajax_response(self, form):
        """Method that returns a response to jQuery"""
        name = form.cleaned_data.get('name')
        return HttpResponse(f'Hello,{name}San!')

By the way

Regarding ʻif request.is_ajax ():inviews.py`, the official documentation says:

reference- Request and response objects|Django documentation| Django

(Hannari Japanese translation)

HttpRequest.is_ajax()

HTTP_X_REQUESTED_WITH header'XMLHttpRequest'In a string
Checks if the request is via XMLHttpRequest and returns True.
Many modern JavaScript libraries send this header.

That is, this method can only be used if the request header HTTP_X_REQUESTED_WITH is set to XMLHttpRequest. jQuery seems to set this properly. *** I tried a little without using jQuery (plain JavaScript), but it didn't work **.

Rewrite the GreetView of views.py as follows and take a look at the request header.

class GreetView(FormView):
    template_name = 'greet.html'
    form_class = forms.GreetForm
    success_url = '/greet'

    def post(self, request, *args, **kwargs):
        #★ Addition
        for k, v in request.META.items():
            print(k, v)
        # ...(The same applies below)

--Result

...
HTTP_ACCEPT text/plain, */*; q=0.01
HTTP_X_REQUESTED_WITH XMLHttpRequest  # <=this
HTTP_USER_AGENT Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36
...

Summary

So far, we've included a Django Ajax sample with a generic view. I think it's implemented more concisely than the other articles. Besides, I would like to try what can be done in combination with StreamingHttpResponse

Recommended Posts

Ajax in Django (using generic class view)
How to use bootstrap in Django generic class view
How to upload files in Django generic class view
How to uniquely identify the source of access in the Django Generic Class View
DJango Note: From the beginning (using a generic view)
Getting started and using sample class-based generic views in Django
Create a simple CRUD app using Django's generic class view
Deploy Django in 3 minutes using docker-compose
Like button implementation in Django + Ajax
Information recording memo using session in Django
CSS environment created in 10 minutes using Django
Django function-based view
View drug reviews using a list in Python
Django tutorial summary for beginners by beginners ④ (Generic View)
Django class-based view
Specify the view URL in your Django template
Try using an object-oriented class in R (R6 method)
Forms in Django
case class in python
Write decorator in class
View images in Matplotlib
Model changes in Django
Django2 View configuration pattern
Try using Django templates.html
Class notation in Python
[Django 2.2] How do you display relation destinations in Django? [List View]
Create a shogi game record management app using Django 4 ~ Create View ~
How to generate a query using the IN operator in Django
Create an easy-to-use follow model in Django using ManyToManyField through