Django: How To Auto Fill all the Model form with the data on 'load' button click after accepting primary key as text input from the user

Viewed 2013

I am beginner in Django.

I have a below requirement in Django Model Form while creating a new record with the submission Form to perform .

1.In form processing i want to auto fill all the form fields based on user primary key text input. 2.User text input from step1 is the primary key of already created record in MySQL DB, which is created before while processing POST request when user filled the form manually all the form fields and clicked on submit.

Example:

Assume the database has 10 records .Each record has some 12 fields. To create new record(11th record) ,we initially click on button:"AddGSP" which opens a form waiting for user input. 11th record to be created has only one field value to be changed from 5th record. Instead of manually typing all the fields i want to autofill all the formdata based on user textinput .

As the user does not want to fill all the details present in the form, i created a input text with "load" button. If user enter:5 as text input and click on "load" button then the form should fill or (load) all the details same as 5th record from database and now the user need to modify only the required fields in the current form and click on submit creates a new record(say :11th).

Please let us know how to proceed further to load the form with the required data.?

Models.py:

class ApplyGSP(models.Model):
    """
    This class is used to Apply the GoogleSecurityPatches when the user requested to apply the GSP
    """
    user = models.CharField("User", max_length=100, default="")
    model_name = models.CharField(max_length=100, blank=True)
    model_no = models.CharField(max_length=100, blank=True)
    os_ver = models.ForeignKey(OSVersion, on_delete=models.CASCADE, verbose_name="os Version")
    chipset = models.ManyToManyField(Chipset)
    patch_level_to_be_applied = models.CharField(max_length=200, blank=True)
    rel_cycle = models.ForeignKey(ReleaseCycle, on_delete=models.CASCADE, verbose_name="Release Cycle")
    requested_time = models.DateTimeField(default=timezone.now)
    applied_gsp_count = models.IntegerField(null=True,default="")
    applied_security_patch_level = models.TextField(default="")
    from_sas_url = models.ForeignKey(SourceSASURL, on_delete=models.CASCADE, verbose_name="Source SAS URL")
    to_sas_url `enter code here`= models.URLField()
    def_src_manifest = models.ManyToManyField(DefaultSrcManifest)
    # from_manifest = models.CharField(max_length=200)
    # to_manifest = models.CharField(max_length=200)
    from_sw_version = models.IntegerField(null=True)
    to_sw_version = models.IntegerField(null=True)
    description = models.CharField(max_length=200)

    class Meta:
        verbose_name_plural = "ApplyGSPPatches"

    def __str__(self):
        return self.user + str(self.pk)

My Forms.py:
------------
class ApplyGSPForm(ModelForm):

    helper = FormHelper()
    class Meta:
        model = ApplyGSP

        fields = ['model_name', 'model_no', 'os_ver', 'chipset', 'patch_level_to_be_applied', 'rel_cycle','applied_gsp_count', 'from_sas_url', 'to_sas_url', 'def_src_manifest', 'from_sw_version',
'to_sw_version', 'description']

My Views.py:
----------
def apply_gsp_request_form(request, id=None):
    """
    :param request: Accept http request
    :param id: Id of Requested User record
    :return: http response
    """
    print("Inside Apply Google Security Patch Form:", id)
    print("request:", request.method)
    print("request.GET:",request.GET)
    load_input_value = request.GET.get('loaddata')
    print("load input value:",load_input_value)

    if id:
        action = 'edit'
        model = get_object_or_404(ApplyGSP, pk=id)
    else:
        action = 'submit'
        model = ApplyGSP()

    message = ""

    if request.method == 'POST':
        form = ApplyGSPForm(request.POST, instance=model)

        if form.is_valid():
            new_apply_gsp_request = form.save(commit=False)
            new_apply_gsp_request.user = request.user.username
            new_apply_gsp_request.save()
            return HttpResponseRedirect('/gspapp/ApplyGSPList')

    else:
        print("when the request is GET ,call ApplyGSPForm ")
        form = ApplyGSPForm(instance=model)

    context = {'form': form, 'Message': message, 'action': action}
    return render(request, 'ApplyGSP.html', context)
ApplyGSP.html:
--------------
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block static %}
{% endblock static %}

{% block content %}
            <form method="GET" role="form" action="">
                 <div class="input-group mb-2 float-left" style="padding-left:120px">
                        <div class="input-group-prepend">
                            <span class="input-group-text row-md-6" id="inputGroup-sizing-default">Load</span>
                        </div>
                        <input type="text" name="loaddata" class="form-control col-md-4" id="inputtext" aria-label="Default" aria-describedby="inputGroup-sizing-default">

                     <a href="{%url 'gspapp:ApplyGSPRequestForm' %}">
                        <button type="button" class="fas fa-sync-alt btn btn-secondary btn-lg" aria-describedby="inputtext"><span class="ml-1">Load</span></button>
                     </a>
                 </div>
            </form>

            <form method="POST" class="form" role="form" action="">
                <!-- The below CSRF Token makes form Secure -->
                {% csrf_token %}

                <div class="container">
                    <br>
                    <br>
                    {% crispy form %}
                        <button type="submit" class="btn btn-primary">
                            {% if action == "submit" %}
                                <span class="fas fa-plus"></span>Submit
                            {% else %}
                                <span class="fas fa-edit"></span>Update
                            {% endif %}
                        </button>
                        <button type="reset" class="btn btn-primary" aria-label="Close" data-dismiss="modal">
                            <span aria-hidden="true">&times;</span>Cancel
                        </button>
                </div>
            </form>

{% endblock content %}

{% block scripts %}
{% endblock scripts %}

urls.py:
------
urlpatterns = [

    path('ApplyGSPList/', login_required(views.ApplyGSPList.as_view(), login_url='/gspapp/login/'), name='ApplyGSPList'),
    path('ApplyGSPList/requestForm/', views.apply_gsp_request_form, name='ApplyGSPRequestForm'),
    re_path(r'^editApplyGSP/(?P<id>\d+)/$', views.apply_gsp_request_form, name='editApplyGSP'),   
]

Regards, N.Dilip Kumar.

1 Answers

I created a mixin which can be used with CreateView.

In template. Put a hidden field. I put two buttons in my template. One default submit and other fetch. If user clicked Fetch, I sent the Hidden field's input as FETCH otherwise SUBMIT.

In view

When form_valid is hit, I check that hidden field and if it is FETCH then I put the 'ID' in the session and redirect to the same view. What happens now? Now your session has stored the 'ID'. This 'ID' can be accessed in get_initial and there initial form data can be fed into the form looking that if 'ID' is in session. If 'ID' is in session then we feed the initial data and send the form.This function is called every time user requests but it will only fill initial data if it contains 'ID'. That is the logic/hack used here. I extracted out the logic in a mixin . All these functions are part of CreateView.

class CreateUser_FillDataAutomaticallyMixin:
 
    def get_initial(self, *args, **kwargs): 
        initial = super().get_initial(*args, **kwargs)
        if "new-user-ID" in self.request.session:
            # get data as dict/use django serializers 
            # example ::=  data =  get_data_from_database(self.request.session["new-user-ID"])
            for key, val in data.items():
                initial[key] = val 
            self.request.session.pop("new-user-ID")    
        return initial   
    
    def get_success_url(self):
        return reverse(...)
        
    def form_valid(self, form):
        if form.cleaned_data["request_type"]  == UserCreateForm.RequestType.SUBMIT:

           # if request  type is of submit do nothing and do usual   

           return super().form_valid(form)
    
        elif form.cleaned_data["request_type"]  == UserCreateForm.RequestType.FETCH:

            #  if request is of fetch then store the id as a session variable
             
            self.request.session["new-user-ID"] = form.cleaned_data["ID"]
            return redirect(...)   # 

    
Related