You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
redirect_field_name on SpecFormView, SpecFormSetView and SpecConfirmView: a page returns where it was opened from.None by
default, which reads nothing. Named - "next", as Django's LoginView
names it - the URL the post or its query carries under that key is read as LoginView reads it, the post's value first, and used only where url_has_allowed_host_and_scheme allows it against the request's own host,
with https required on a secure request. A success redirects there in
place of get_success_url(result), an override included, and under htmx
answers HX-Redirect to it; a spec-result fragment still answers in
place. An unsafe URL is ignored, and the success goes where it went before. get_redirect_url() answers the safe URL, or "".
It survives a refused post. The context carries redirect_field_name and next, the safe URL, and the shipped
templates post them back as a hidden input; neither key is there without
a safe URL. The key is never an argument: a form page's arguments are its
fields and its route, and the confirmation page reads nothing posted.
as_view() refuses a name that is not a non-empty string, one that is
the commit_button, on SpecFormView one the form declares as a field,
and on SpecFormSetView one that is the add_button or sits under the
formset's form- prefix.
refusal_redirect on SpecConfirmView: a refusal sent back to the page
the button was posted from.False by default. Set, an invalid, failed or
needs-input refusal sends each message the page would show in errors
through messages.error, with the refusal's code as extra_tags where it
has one, and redirects to get_refusal_url(refused): the safe URL redirect_field_name reads, else success_url. Under htmx it answers HX-Redirect. A denial is raised as before. Without the messages middleware
Django raises MessageFailure, and the page is rendered as it is without refusal_redirect, so the refusal is never lost; a refusal with no message
to send is the page again too. A refusal sent back counts and presents no
target. as_view() refuses it on a
page with no success_url that does not override get_refusal_url.
The unavailable template filter: why a row's action is unavailable. {% with why=row|unavailable:"withdraw" %}{% if why %}{{ why.reason }}{% endif %}{% endwith %}
returns the row's answer, with the code and reason of the first
condition the row does not meet, when the action is unavailable, and None when it is available. It reads the answers available reads, so it
costs no query, and raises the same TemplateSyntaxError for a name the
spec does not declare or a row the page did not serve. A condition on the
row asked of a row that no longer exists answers with no code and no
reason, so {% if why %} holds and {{ why.reason }} renders empty. The
answer is a fresh dict per read, so json_script takes it, whose clear
and popitem are marked alters_data, so no template can empty it. The
example's table shows the reason where a row has no Withdraw button.
The docs read a negated or combined condition through {% with %},
for both filters, where they said to use available only as a bare {% if %} condition: Django's {% if %} reads an error inside not, and, or or a comparison as the condition being false, so a misspelt
name there draws nothing and raises nothing, and {% with ok=row|available:"withdraw" %}{% if not ok %} resolves the filter
outside {% if %}, where a misspelt name raises.
SpecSelectorView.get_query(request), the query string a page reads.
It answers request.GET unless a subclass answers another QueryDict, and
the page asks it once a request. On a list page the paging keys, the filter
form, the spec's arguments and the previous and next links all read its
answer; an instance page, which is not paged, reads the spec's arguments
from it. The template is handed a request whose GET is that answer, so a
django-tables2 table's header sort links keep it. A list that opens where
the last visit left it answers a query kept in the session on a bare visit;
the selector guide shows one, with a ?reset=1 that forgets a saved query
the spec refuses. Like every request hook it is a plain def, and as_view() refuses an async def one; an answer that is not a QueryDict
raises TypeError naming the hook.
Changed
The htmx handler example answers an anonymous visitor with the login page
whether or not htmx asked, and gains a handler404. Without htmx, a
visitor who is not signed in is redirected to the login page and back to the
page they asked for, where the 403 page used to be shown; a signed-in
visitor still gets Django's 403 page. The new handler404 answers an htmx
request with HX-Refresh, since htmx swaps no 4xx body and a stale row's
action would otherwise do nothing visible, and a browser with Django's 404
page. The pages state that the same handlers answer a list row's and a
confirmation's denial, and that the sync pages serve under ASGI, with the
reason there is no async page.
SpecSelectorView ignores a query key its spec does not declare. unknown_arguments defaults to UnknownArguments.IGNORE on the list and
instance pages, so ?utm_source=x, or a bookmark from before a filter was
renamed, is answered 200 with the rows the rest of the query selects, where
it was a 400 with utm_source: Unknown argument. A declared key's value is
read and refused as before, a route kwarg the spec does not declare is
still the host's misconfiguration, and the JSON views still refuse an
undeclared key. The form, formset and confirmation pages keep REJECT for
what they dispatch, their form's fields and the route. Set unknown_arguments = UnknownArguments.REJECT on a list whose query only
code builds to keep the refusal. A list page and a JSON list now read each
value of one query string the same way, rather than answering it the same.