adamchainz / django-htmx

Extensions for using Django with htmx.
https://django-htmx.readthedocs.io/
MIT License
1.58k stars 140 forks source link

Detection of partial htmx request in the presence of hx-history #410

Open brablc opened 8 months ago

brablc commented 8 months ago

Python Version

3.11.6

Django Version

4.2.6

Package Version

1.17

Description

The documentation says the detection of a partial htmx request should be: if request.htmx:. However in the presence of hx-history anywhere on the page, when navigating back to this page a full page needs to be returned. To properly handle this situation it is actually necessary to use: if request.htmx and not request.htmx.history_restore_request:.

I would suggest adding something like request.htmx_partial_request.

adamchainz commented 8 months ago

I’ll consider it if there is more support for the idea. I am not sure how many people use the history feature.

viktor2097 commented 8 months ago

This happens due to the fact that the htmx part is HTTP cached just by the URL, so it doesn't really know the difference between a htmx request and a full page request This is mentioned under the cache section

You need to set Vary: HX-Request or Vary: Accept to make sure the it's cached based on headers as well

I think a lot of people will use the history feature, intentionally or not. For example, if you filter on data, you probably use hx-push-url="true" to make sure that the request gets pushed to the url, so you can copy paste the URL and share it with others. Without either of the vary headers specified, if you go to a new url, and then click the back button in the browser, it would only return the partial.

It's easy to add the headers yourself, but I do would like to see it added to the library, since it's a subtle "bug" that you might not notice unless you properly test moving back and forth between your pages while having features that rely on history. Question is if this feature should be opt-in or opt-out, but definitely deserves a spot in documentation.

brablc commented 8 months ago

You are correct on the importance of Vary header, but this is not my scenario - there is actually no caching involved at all.

I am just saying that if you ever use hx-history="false" in your application, then checking for request.htmx is not enough.

viktor2097 commented 8 months ago

You are correct on the importance of Vary header, but this is not my scenario - there is actually no caching involved at all.

I am just saying that if you ever use hx-history="false" in your application, then checking for request.htmx is not enough.

Could you provide an example that demonstrates this issue? I'm missing some detail. if hx-history="false" is set, then going back for me fully reloads the page as there is no caching.

I tried having hx-history set globally, and then used a history feature like hx-push-url, and then the issue of going back not doing a full page reload appears, then the Vary: Accept header solved that for me.

brablc commented 8 months ago

Could you provide an example that demonstrates this issue? I'm missing some detail. if hx-history="false" is set, then going back for me fully reloads the page as there is no caching.

The problem seems to be introduced here: https://github.com/bigskysoftware/htmx/pull/2013 .

Checking for request.htmx is not enough.

A way to simulate (even without using hx-history) is:

  1. navigate to a page with soma partial content,
  2. navigate to another page
  3. delete local storage history
  4. press back button

Now the fresh partial content would load to the top window. Backend should had generated full page.

viktor2097 commented 8 months ago

I tried to reproduce and "simulate" according to your instructions, and it works as expected with backend generating a full page on back button (with Vary: Accept)

What version of HTMX are you on? What browser? Maybe something else is different for me

brablc commented 8 months ago

I tried to reproduce and "simulate" according to your instructions, and it works as expected with backend generating a full page on back button (with Vary: Accept)

I have created a demo: https://github.com/brablc/htmx-sandbox . It uses latest htmx 1.9.10 and I run Firefox, but this should not matter.

adamchainz commented 1 month ago

You need to set Vary: HX-Request or Vary: Accept to make sure the it's cached based on headers as well

In reference to this, I have added some docs for setting Vary in #464.


I’m still not exactly sure whether to change anything about request.htmx or to add another attribute. It doesn’t seem many people have found this issue, so maybe the “partial rendering” pattern isn't that popular, actually.