django-viewssimplemodal

Can I programmatically cause a modal window to popup in Django views.py?


I want to programmatically cause a modal window to popup in Django views.py when a user enters a record ID, telling the user whether or not that record exists.

Currently the user enters the ID (shpid) into the first field of a blank form. The intention, then, is for the remainder of the form to be completed by the user if the record does not exist or, after confirmation via the popup, to display the record data for the user to update, if it does exist.

How can I achieve that?

The shipment model is:

class Shipment(models.Model):
    shpid = models.CharField(max_length=20, unique=True)
    awb = models.CharField(max_length=20,blank=True,default="")
    pod = models.CharField(max_length=100,blank=True,default="")
    coldate = models.DateField(null=True,blank=True)
    deldate = models.DateField(null=True,blank=True)
    recipient = models.CharField(max_length=100,blank=True,default="")
    status = models.CharField(max_length=100,blank=True,default="")
    sts_date = models.DateField(null=True,blank=True)
    costs = models.DecimalField(max_digits=14,decimal_places=2,default=0.0)

I have 2 shipment forms, AddShpForm and UpdateShpForm, the only difference being that the attribute of shpid is set to readonly in the Update form.

AddShpForm is:

class AddShpForm(ModelForm):

    class Meta:
        model = Shipment
        fields = '__all__'
        widgets = {
            "shpid": TextInput(attrs={'autofocus': 'autofocus','style':'max-width:120px'}),
            # (UpdateShpForm) -- "shpid": TextInput(attrs={'readonly':True,'style':'max-width:120px','style':'background-color:gainsboro'}),

            "costs": TextInput(attrs={'style':'max-width:200px'}),
            "coldate": DateInput(attrs={'type': 'date','style':'max-width:180px'}),
            "deldate": DateInput(attrs={'type': 'date','style':'max-width:180px'}),
            "sts_date": DateInput(attrs={'type': 'date','style':'max-width:180px'}),

        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['shpid'].label = "Shipment ID"
        self.fields['awb'].label = "AWB"
        self.fields['pod'].label = "POD"
        self.fields['coldate'].label = "Collection Date"
        self.fields['deldate'].label = "Delivery Date"
        self.fields['recipient'].label = "Recipient"
        self.fields['status'].label = "Status"
        self.fields['sts_date'].label = "Status Date"
        self.fields['costs'].label = "Costs"

        self.helper = FormHelper()
        self.form_method = 'post'
        self.helper.layout = Layout(
            Row (
                Column('shpid',css_class='form-group col-md-2 mb-0 pe-4'),
                Column('status',css_class='form-group col-md-4 mb-0 ps-2 pe-2'),
                Column('sts_date', css_class='form-group col-md-4 mb-0 ps-4'),
            ),
            Row(
                Column('awb',css_class='form-group col-md-6 mb-0 pe-4'),
                Column('pod',css_class='form-group col-md-6 mb-0 pe-4'),
            ),
            Row(
                Column('coldate', css_class='form-group col-md-3 mb-0 pe-4'),
                Column('deldate', css_class='form-group col-md-3 mb-0 ps-2 pe-2'),
                Column('recipient', css_class='form-group col-md-6 mb-0 ps-4 pe-4'),
            ),
            Field('costs'),
            ButtonHolder(
                Submit('submit', 'Add Shipment', css_class='ml-n2 btn-lg fw-bolder'),

                css_class='center'
            )
        )

My current views.py for to add/update the shipment is:

def add_shipment(request,pk, orderid):
    if request.method == 'POST':
        shp_form = AddShpForm(request.POST)
        if shp_form.is_valid():
            shpid = shp_form.cleaned_data['shpid']
            shp_form.save()
            shpmt = Shipment.objects.get(shpid=shpid)
            order = Order.objects.get(pk=pk)
            order.shipment = shpmt
            order.save()
            messages.success(request,f'Shipment: {shpid} - saved and attached to Order: {order.orderid}')
            return redirect('tracker:list_orders','open')
        else:                     #  <---  I want to add the popup here
            shp_form = UpdateShpForm()
            return render(request, 'tracker/add_shipment.html', {'form': shp_form})
    else:
        shp_form = AddShpForm()
        return render(request,'tracker/add_shipment.html',{'form':shp_form})

add_shipment is called by clicking a link in the list_orders ListView


Solution

  • in your input field where user enters the 'shipid' you can onchange or onblur event handler and trigger a backend API call to validate and fetch ship details and accordingly can show the modal

    the code will look like this

    in html

    <input type="text" id="shipid" />
    

    in js using jquery

    $('#shipid').change(function(){
        $.ajax({
          url: 'https://test.example.com/check-ship-details/{id}',
          method: 'GET',
          success: function(response) {
            console.log(response);
            
            // if shipid do not have details
            if (!response.has_details) {
                // trigger show modal
                update_details.modal('show');
            }
            
          },
          error: function(xhr, status, error) {
            console.error(error);
          }
        });
    })
    

    in views.py

    def check_ship_details(request, id):
        // check if details exists
        return response