agora inbox for pgsql-www@postgresql.org  
help / color / mirror / Atom feed
From: Jonathan Gonzalez V. <jonathan@abdiel.eu>
Subject: [PATCH 1/1] Turn the logout link into a POST method following Django 5.2 rules.
Date: Mon, 10 Aug 2026 11:30:40 +0200

---
 media/css/main.css       | 12 ++++++++++++
 pgweb/account/tests.py   | 26 ++++++++++++++++++++++++++
 pgweb/util/contexts.py   |  2 +-
 templates/base/page.html |  9 ++++++++-
 4 files changed, 47 insertions(+), 2 deletions(-)
 create mode 100644 pgweb/account/tests.py

diff --git a/media/css/main.css b/media/css/main.css
index 7e9ebf18..4861a348 100644
--- a/media/css/main.css
+++ b/media/css/main.css
@@ -847,6 +847,18 @@ input#navbar-toggler {
   color: var(--pg-sidenav-a-fg-color);
   font-weight: normal;
 }
+#pgSideNav .pg-sidenav-link {
+  background: none;
+  border: 0;
+  color: var(--pg-sidenav-a-fg-color);
+  cursor: pointer;
+  font: inherit;
+  padding: 0;
+}
+
+#pgSideNav .pg-sidenav-link:hover {
+  text-decoration: underline;
+}
 
 #pgSideNav ul {
   list-style-type: circle;
diff --git a/pgweb/account/tests.py b/pgweb/account/tests.py
new file mode 100644
index 00000000..3cbc59d7
--- /dev/null
+++ b/pgweb/account/tests.py
@@ -0,0 +1,26 @@
+from django.contrib.auth import SESSION_KEY, get_user_model
+from django.test import TestCase, override_settings
+
+
+@override_settings(DO_ESI=True)
+class LogoutTests(TestCase):
+    def setUp(self):
+        self.user = get_user_model().objects.create_user(
+            username='logout-test',
+            email='logout-test@example.com',
+        )
+        self.client.force_login(self.user)
+
+    def test_account_navigation_submits_logout_with_post(self):
+        response = self.client.get('/account/')
+
+        self.assertContains(
+            response,
+            '<form action="/account/logout/" method="post">',
+        )
+
+    def test_logout_post_clears_session(self):
+        response = self.client.post('/account/logout/')
+
+        self.assertRedirects(response, '/', fetch_redirect_response=False)
+        self.assertNotIn(SESSION_KEY, self.client.session)
diff --git a/pgweb/util/contexts.py b/pgweb/util/contexts.py
index ca493714..95750c39 100644
--- a/pgweb/util/contexts.py
+++ b/pgweb/util/contexts.py
@@ -89,7 +89,7 @@ sitenav = {
             {'title': 'Organisations', 'link': '/account/edit/organisations/'},
         ]},
         {'title': 'Change password', 'link': '/account/changepwd/'},
-        {'title': 'Logout', 'link': '/account/logout/'},
+        {'title': 'Logout', 'link': '/account/logout/', 'method': 'post'},
     ],
 }
 
diff --git a/templates/base/page.html b/templates/base/page.html
index 523b53d8..7dc9e5f8 100644
--- a/templates/base/page.html
+++ b/templates/base/page.html
@@ -11,7 +11,14 @@
          <ul>
            {%for m in navmenu%}
            {%if not forloop.first %}</li>{%endif%}
-           <li{%if forloop.last%} class="last-child"{%endif%}><a href="{{m.link}}">{{m.title}}</a>
+           <li{%if forloop.last%} class="last-child"{%endif%}>
+            {%if m.link == '/account/logout/'%}
+             <form action="{{m.link}}" method="post">{%csrf_token%}
+              <button class="pg-sidenav-link" type="submit">{{m.title}}</button>
+             </form>
+            {%else%}
+             <a href="{{m.link}}">{{m.title}}</a>
+            {%endif%}
             {%if m.submenu %}
              <ul>
              {%for sm in m.submenu %}
-- 
2.53.0


--=-=-=--






view thread (1467+ messages)  latest in thread

Message-ID: <no-message-id-34655@localhost>
Permalink:  ../no-message-id-34655@localhost/
Also on:    postgresql.org/message-id/no-message-id-34655@localhost

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-www@postgresql.org
  Cc: jonathan@abdiel.eu
  Subject: Re: [PATCH 1/1] Turn the logout link into a POST method following Django 5.2 rules.
  In-Reply-To: <no-message-id-34655@localhost>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox