Django HTMX trigger upon change throws error

Upon change of the field ‘Party’ expected result is to bring upon all its details inside the partial template.
But error occurs as below,

  1. Error1:
    htmx.org@1.8.4:1 GET http://127.0.0.1:8000/entry/{%%20url%20’entry:selected-party’%20id%20%}?party=1 404 (Not Found)

  2. Error2:
    htmx.org@1.8.4:1 Response Status Error Code 404 from {% url ‘entry:selected-party’ id %}

  3. Error3:
    Page not found (404)
    Request Method: GET
    Request URL: http://127.0.0.1:8000/entry/{%25%20url%20’entry:selected-party’%20pk%20%25}?party=1
    Using the URLconf defined in djangoapp.urls, Django tried these URL patterns, in this order:

admin/
accounts/
[name=‘home’]
entry/ [name=‘index’]
entry/ add/ [name=‘add-entry’]
entry/ list/ [name=‘entries-list’]
entry/ addparty/ [name=‘add-party’]
entry/ party/int:pk [name=‘selected-party’]
masters/
The current path, entry/{% url ‘entry:selected-party’ pk %}, didn’t match any of these.
Unable to fix the error to achieve the expected result. So, request help with a solution or reason for this error. - Thank you!

views.py

@login_required
def SelectedParty(request, pk):  
    selectedPartyFields = Party.objects.get(pk=pk)
    context = {'selectedPartyFields': selectedPartyFields} 
    return render(request,'partials/SelectedParty.html',context)

Part of forms.py

class AddForm(forms.ModelForm):

	party = forms.ModelChoiceField(
        queryset=Party.objects.all(),
        widget=forms.Select(attrs={'style':'max-width: 14em', 
            'hx-get': "{% url 'entry:selected-party' id %}",
            'hx-target': '#selectedParty_DivId',
            'hx-trigger': 'change'
        })
    )

Part of the template

        <div id="selectedParty_DivId" class="col-md-6">
            {% include 'partials/SelectedParty.html' %}
        </div>

SelectedParty.html

Testing

<br>

Second line

{{ selectedPartyFields.Name }}

{{ selectedPartyFields.City }}

and the related urls.py

    path('party/<int:pk>',SelectedParty, name='selected-party'),

The reason you’re getting the error is because of this:

I think I understand what you’re trying to do here, you’re trying to generate a different hx-get attribute for each entry of the select list - but that’s not going to work this way. The template is being rendered by Django, but you’re not going to know what ID was selected until a selection is made - and that happens in the browser.

(What’s actually happening here is that that attribute is not being rendered by the rendering engine when that field is being rendered - notice that the url is the literal text supplied in the attribute. You can verify this by examining the HTML that was rendered to the browser. This means that this way of approaching it isn’t going to work for two separate and distinct reasons.)

What I do for situations like this is wrap the select field in a div, and put the hx-get on that div, along with using the hx-params attribute to include the field value as a GET parameter.

It’s not as “clean” as using the url parameters, but it works. (Which means there may be a better solution, but if there is, I’m not aware of it. I’m sure you could probably build something based on handling the configRequest event, but I’m not immediately convinced that would be “better”.)

Note: Also see Possibility to pass some parameters as path variables instead of in query string · Issue #1202 · bigskysoftware/htmx · GitHub - This appears to be related.

1 Like

Thank you Ken!
As per your suggestion, I did the following change with the div element.

<div class="input-group" name="party_name" 
                    hx-get = 'party/',
                    hx-target = '#selectedParty_DivId',
                    hx-trigger = 'change',
                    hx-include = '[name="party"]'
              >
                   <span class="input-group-text mb-3" style="padding-left:4%; padding-right:6%; width:110px;">
                         Party:&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
                    </span>
                   {% comment %} <label class="col-sm-2 col-form-label">Party: </label> {% endcomment %}
                   {{ addForm.party|as_crispy_field }}   

                   <button type="button" class="btn btn-secondary mb-3" 
                             hx-get="{% url 'entry:add-party' %}" 
                             hx-target="#dialog">
                        <i class="fa fa-plus"></i>
                   </button>
</div>

Now below is the error, Any further help? please.

Page not found (404)

Request Method: GET
Request URL: http://127.0.0.1:8000/entry/party/?party=1

Notice the URL being issued. Do you have a url definition matching that?
You’re not sending the variable as part of the url any more, it’s a GET variable that you would retrieve in the view.

Yes Ken, the above urls.py.

and the related view is as below. Am I doing it right?

@login_required
def SelectedParty(request): 
    party = request.Post['id']
    selectedPartyFields = Party.objects.get(pk=party)
    context = {'selectedPartyFields': selectedPartyFields} 
    return render(request,'partials/SelectedParty.html',context)

But that’s not the url being requested.

Notice the difference between the two.

The variable is being passed as a GET variable, not POST, and the variable name is not ‘id’.

Thank you Ken, I am about to reach the solution! Now with the modified codes, upon the first ‘Change’ event, i.e. of first selected value from the drop down, the details are brought up as soon as the value is selected.
But not working for any further changes and the following error shows up in console,

htmx.org@1.8.4:1 htmx:targetError

St @ htmx.org@1.8.4:1
Q @ htmx.org@1.8.4:1
Y @ htmx.org@1.8.4:1
lr @ htmx.org@1.8.4:1
(anonymous) @ htmx.org@1.8.4:1
i @ htmx.org@1.8.4:1
handleMouseUp_ @ unknown

unable to figure out the reason. - Please help. - Thank you!

The modified codes are as below,

modified div ( I now have created a form to bring up all the values)

               <div  
                    hx-get = "{% url 'entry:s-party' %}",
                    hx-target = '#selectedParty_DivId',
                    hx-trigger = 'change',
                    hx-include = '[name="party"]'
               >

modified view

@login_required
def SelectedParty(request): 
    selectedparty = request.GET.get('party')
    party = Party.objects.all().get(pk=selectedparty)
    form = PartyDetailsForm(instance=party)
    context = {'form':form,'party':party}
    return render(request, 'partials/SelectedParty.html', context)

SelectedParty.html

Testing

<br>

Second line


{{ form }}

It might help if you posted the actual html that was rendered for this, but I’m going to make the guess that you replaced the div having the id selectedParty_DivId with a div not having that id attribute.

This is the whole template:

<div class="row"> 
    <div class="col-md-6">
        <form id="entry-form" method="POST" Action="{{ request.path }}"  hx-swap="outerHTML" hx-trigger="Partyadded from:body">  
                {% csrf_token %} 

               <div 
                    {% comment %} hx-get = 'party/', {% endcomment %}
                    hx-get = "{% url 'entry:s-party' %}",
                    hx-target = '#selectedParty_DivId',
                    hx-trigger = 'change',
                    hx-include = '[name="party"]'
               >
                    <div class="input-group" name="party_name">
                         <span class="input-group-text mb-3" style="padding-left:4%; padding-right:6%; width:110px;">
                                   Party:&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
                              </span>
                         
                         {{ entryForm.party|as_crispy_field }} 
          
                         <button type="button" class="btn btn-secondary mb-3" 
                                   hx-get="{% url 'entry:add-party' %}" 
                                   hx-target="#dialog">
                              <i class="fa fa-plus"></i>
                         </button>
                    </div>
               </div>
              
               ...
		...
		...
            <br> 
            <input type="submit" class="btn btn-success">
        </form> 
    </div>  
    <div class="col-md-6">
        <div id="selectedParty_DivId" class="col-md-6">
            {% include 'partials/SelectedParty.html' %}
        </div>
    </div>
</div>

And the rendered html is only “partials/SelectedParty.html” which is an include in the above template.

Testing

<br>

Second line

{% comment %} {{ selectedPartyFields.Name }}

{{ selectedPartyFields.City }} {% endcomment %}

{{ form }}

Only the first change event triggers the include part as expected. But the same has to happen for second change and further too, which is not happening.

I don’t want to see the template, I want to see the actual HTML that was rendered and sent to the browser - both before and after selecting an item.

You meant this?

Before_Change i.e on load of the page

After_Change i.e after selection of value in the drop down

Close - I want to see the actual HTML that is creating those displays.

Dear Ken,
The below html code is the one which delivers that whole page.
Sorry I actually didn’t get what you meant by actual html.

Still, by adding the below htmx along with other htmx in the div, expected result is achieved.

hx-swap=“innerHTML”

Without your explanation, it wouldn’t have happened. Thank you very much!!!

The actual html is what you’re sending to the browser. It’s the output after the template has been rendered. It’s what you see by examining the page in your browser’s developer tools.

oh!
:slight_smile: got it now. - Thanks Ken!