How to render a field request without refreshing the page?

I have a form with a few fields, the first being where a person enters their ID #, which is tied to a separate model for verification. I made this function get_employee_name, which returns the name based on the ID from the other model, but I'm not sure how to display it in the page, right on the top, without refreshing after the person tabs/clicks out? I'm not too familiar with html, but I was reading an ajax GET request would do the trick, but I'm not sure how to approach this.

This is basically so the person knows that the ID # they entered matches their name before proceeding to fill the rest out.

views.py

class EnterExitArea(CreateView):
    model = EmployeeWorkAreaLog
    template_name = "enter_exit_area.html"
    form_class = WarehouseForm

    def form_valid(self, form):
        emp_num = form.cleaned_data['adp_number']
        area = form.cleaned_data['work_area']
        station = form.cleaned_data['station_number']

        if 'enter_area' in self.request.POST:
            form.save()
            return HttpResponseRedirect(self.request.path_info)

        elif 'leave_area' in self.request.POST:
            form.save()
            EmployeeWorkAreaLog.objects.filter(adp_number=emp_num, work_area=area, station_number=station).update(time_out=datetime.now())
            return HttpResponseRedirect(self.request.path_info)


def get_employee_name(request):
    adp_number = request.POST.get('adp_number')
    employee = Salesman.objects.get(adp_number=adp_number)
    employee_name = employee.slsmn_name
    return employee_name

models.py

class EmployeeWorkAreaLog(TimeStampedModel, SoftDeleteModel, models.Model):
    employee_name = models.CharField(max_length=25)
    adp_number = models.ForeignKey(Salesman, on_delete=models.SET_NULL, help_text="Employee #", null=True, blank=False) #(max_length=50, help_text="Employee #", blank=False)
    ...

    def __str__(self):
        return self.adp_number

forms.py

class WarehouseForm(AppsModelForm):
    class Meta:
        model = EmployeeWorkAreaLog
        widgets = {
            'adp_number': ForeignKeyRawIdWidget(EmployeeWorkAreaLog._meta.get_field('adp_number').remote_field, site),
        }
        fields = ('adp_number', 'work_area', 'station_number')

enter_exit_area.html

{% extends "base.html" %}
{% block main %}
    <form id="warehouseForm" action="" method="POST" data-stations-url="{% url 'operations:ajax_load_stations' %}" novalidate >
        {% csrf_token %}

        <div>
            <div>
                {{ form.adp_number.help_text }}
                {{ form.adp_number }}
            </div>
            <div>
                {{ form.work_area.help_text }}
                {{ form.work_area }}
            </div>
            <div>
                {{ form.station_number.help_text }}
                {{ form.station_number }}
            </div>
        </div>

        <div>
            <div>
                <button type="submit" name="enter_area" value="Enter">Enter Area</button>
                <button type="submit" name="leave_area" value="Leave">Leave Area</button>
            </div>
        </div>
    </form>

{% endblock main %}

Solution 1:

We'll use ajax, with jQuery so be sure you have jQuery before you read.

first, you've to create an endpoint to GET, go to urls.py & add an endpoint say

path('/myserver/getID/', views.get_employee_name, name="whatever")

now, this calls get_employee_name right? Let's now call it in JS without refreshing.

here's the basic syntax ->

$.ajax({THIS IS A SIMPLE DICT})

ajax takes parameters

  • type which is the request type
  • url which is the request URL which we just made above (not the full url, you're specifying the endpoint from where you're located on the website so you just use /myserver/getID/)
  • it also takes data which is a dictionary with your posted data (yes a dictionary inside the bigger ajax dictionary
  • it CAN take success which is a function to call after getting the response with status 200 (success) and that success function can have the parameter response which is your response
  • it CAN take error which is a function that gets called after an error & takes error as argument

enough talking...

$.ajax({
    url: 'myserver/getID',
    type: 'GET',
    data: // don't specify this, we're not posting any data,
    success: function (response) {console.log(response.data)}, //this will be what returned from python
    error: function (error){console.log(error)}
})

this is a simple ajax request

NOTE, if you return a redirect from python & accept it from ajax, it won't work, ajax can't redirect, be sure to remember that because most of the time people ask why redirect('mylink') doesn't work after I return it from ajax.

Another NOTE is the when dealing with post requests with ajax, you must include the csrf token which can be included by

csrfmiddlewaretoken: '{%csrf_token%}'

You can use Fetch API too if you want, or even normal XMLhttprequest.

Solution 2:

Sounds like you have a few questions and should split them up but just to answer the main question in your title, "How to render a field request without refreshing the page?", this is how you do that part with some DOM manipulation. This is basic HTML and JavaScript you would need to fit into your project.

Once you get the name back from your lookup, you just need to insert the value into the DOM and that will render it, not requiring a refresh. Here's a simple example:

var clickMe = function() {
  var element = document.getElementById('heading');
  
  // Do your AJAX and lookup something...
  element.textContent = "Name Lookup From Server Request";
}
<div>
  <h1 id="heading"></h1>
  <button onclick="clickMe()">Click Me</button>
</div>