Skip to content

Commit f6278d9

Browse files
committed
Fix some request.user and request.session docs mentions
1 parent 2663c49 commit f6278d9

File tree

10 files changed

+101
-56
lines changed

10 files changed

+101
-56
lines changed

plain-api/plain/api/README.md

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Because [Views](/plain/plain/views/README.md) can convert built-in types to resp
2020
```python
2121
# app/api/views.py
2222
from plain.api.views import APIKeyView, APIView
23+
from plain.auth import get_request_user, set_request_user
2324
from plain.http import JsonResponse
2425
from plain.views.exeptions import ResponseException
2526

@@ -33,7 +34,7 @@ class BaseAPIView(APIView, APIKeyView):
3334
super().use_api_key()
3435

3536
if user := self.api_key.users.first():
36-
self.request.user = user
37+
set_request_user(self.request, user)
3738
else:
3839
raise ResponseException(
3940
JsonResponse(
@@ -46,10 +47,11 @@ class BaseAPIView(APIView, APIKeyView):
4647
# An endpoint that returns the current user
4748
class UserView(BaseAPIView):
4849
def get(self):
50+
user = get_request_user(self.request)
4951
return {
50-
"uuid": self.request.user.uuid,
51-
"username": self.request.user.username,
52-
"time_zone": str(self.request.user.time_zone),
52+
"uuid": user.uuid,
53+
"username": user.username,
54+
"time_zone": str(user.time_zone),
5355
}
5456

5557

@@ -59,7 +61,7 @@ class PullRequestView(BaseAPIView):
5961
try:
6062
pull = (
6163
PullRequest.query.all()
62-
.visible_to_user(self.request.user)
64+
.visible_to_user(get_request_user(self.request))
6365
.get(uuid=self.url_kwargs["uuid"])
6466
)
6567
except PullRequest.DoesNotExist:
@@ -104,10 +106,12 @@ Handling authentication in the API is pretty straightforward. If you use [API ke
104106
```python
105107
class BaseAPIView(APIView, APIKeyView):
106108
def use_api_key(self):
109+
from plain.auth import set_request_user
110+
107111
super().use_api_key()
108112

109113
if user := self.api_key.users.first():
110-
self.request.user = user
114+
set_request_user(self.request, user)
111115
else:
112116
raise ResponseException(
113117
JsonResponse(
@@ -122,10 +126,12 @@ When it comes to authorizing actions, typically you will factor this in to the q
122126
```python
123127
class PullRequestView(BaseAPIView):
124128
def get(self):
129+
from plain.auth import get_request_user
130+
125131
try:
126132
pull = (
127133
PullRequest.query.all()
128-
.visible_to_user(self.request.user)
134+
.visible_to_user(get_request_user(self.request))
129135
.get(uuid=self.url_kwargs["uuid"])
130136
)
131137
except PullRequest.DoesNotExist:
@@ -149,9 +155,11 @@ class UserForm(ModelForm):
149155

150156
class UserView(BaseAPIView):
151157
def patch(self):
158+
from plain.auth import get_request_user
159+
152160
form = UserForm(
153161
request=self.request,
154-
instance=self.request.user,
162+
instance=get_request_user(self.request),
155163
)
156164

157165
if form.is_valid():
@@ -174,10 +182,12 @@ Deletes can be handled in the `delete` method of the view. Most of the time this
174182
```python
175183
class PullRequestView(BaseAPIView):
176184
def delete(self):
185+
from plain.auth import get_request_user
186+
177187
try:
178188
pull = (
179189
PullRequest.query.all()
180-
.visible_to_user(self.request.user)
190+
.visible_to_user(get_request_user(self.request))
181191
.get(uuid=self.url_kwargs["uuid"])
182192
)
183193
except PullRequest.DoesNotExist:
@@ -229,19 +239,20 @@ user.api_key = APIKey.query.create()
229239
user.save()
230240
```
231241

232-
To use API keys in your views, you can inherit from `APIKeyView` and customize the [`use_api_key`](./views.py#use_api_key) method to set the `request.user` attribute (or any other attribute) to the object associated with the API key.
242+
To use API keys in your views, you can inherit from `APIKeyView` and customize the [`use_api_key`](./views.py#use_api_key) method to associate the request with a user (or any other object) using `set_request_user()`.
233243

234244
```python
235245
# app/api/views.py
236246
from plain.api.views import APIKeyView, APIView
247+
from plain.auth import set_request_user
237248

238249

239250
class BaseAPIView(APIView, APIKeyView):
240251
def use_api_key(self):
241252
super().use_api_key()
242253

243254
if user := self.api_key.users.first():
244-
self.request.user = user
255+
set_request_user(self.request, user)
245256
else:
246257
raise ResponseException(
247258
JsonResponse(
@@ -292,9 +303,10 @@ class CurrentUserAPIView(BaseAPIView):
292303
"summary": "Get current user",
293304
})
294305
def get(self):
295-
if self.request.user:
296-
user = self.request.user
297-
else:
306+
from plain.auth import get_request_user
307+
308+
user = get_request_user(self.request)
309+
if not user:
298310
raise Http404
299311

300312
return schemas.UserSchema.from_user(user, self.request)
@@ -325,9 +337,10 @@ class TeamAccountAPIView(BaseAPIView):
325337
team__organization=self.organization, uuid=self.url_kwargs["uuid"]
326338
)
327339

328-
if self.request.user:
340+
user = get_request_user(self.request)
341+
if user:
329342
return TeamAccount.query.get(
330-
team__organization__in=self.request.user.organizations.all(),
343+
team__organization__in=user.organizations.all(),
331344
uuid=self.url_kwargs["uuid"],
332345
)
333346
except TeamAccount.DoesNotExist:

plain-auth/plain/auth/README.md

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ The `plain.auth` package provides user authentication and authorization for Plai
1717

1818
```python
1919
# In a view
20-
if request.user:
21-
print(f"Hello, {request.user.email}!")
20+
from plain.auth import get_request_user
21+
22+
user = get_request_user(request)
23+
if user:
24+
print(f"Hello, {user.email}!")
2225
else:
2326
print("You are not logged in.")
2427
```
@@ -33,7 +36,7 @@ class ProfileView(AuthViewMixin, View):
3336
login_required = True
3437

3538
def get(self):
36-
return f"Welcome, {self.request.user.email}!"
39+
return f"Welcome, {self.user.email}!"
3740
```
3841

3942
## Authentication setup
@@ -108,23 +111,24 @@ urlpatterns = [
108111

109112
## Checking if a user is logged in
110113

111-
A `request.user` will either be `None` or point to an instance of your `AUTH_USER_MODEL`.
112-
113-
In templates:
114+
In templates, use the `get_current_user()` function:
114115

115116
```html
116-
{% if request.user %}
117-
<p>Hello, {{ request.user.email }}!</p>
117+
{% if get_current_user() %}
118+
<p>Hello, {{ get_current_user().email }}!</p>
118119
{% else %}
119120
<p>You are not logged in.</p>
120121
{% endif %}
121122
```
122123

123-
In Python code:
124+
In Python code, use `get_request_user()`:
124125

125126
```python
126-
if request.user:
127-
print(f"Hello, {request.user.email}!")
127+
from plain.auth import get_request_user
128+
129+
user = get_request_user(request)
130+
if user:
131+
print(f"Hello, {user.email}!")
128132
else:
129133
print("You are not logged in.")
130134
```
@@ -151,7 +155,7 @@ class AdminOnlyView(AuthViewMixin, View):
151155
class CustomPermissionView(AuthViewMixin, View):
152156
def check_auth(self):
153157
super().check_auth()
154-
if not self.request.user.is_special:
158+
if not self.user.is_special:
155159
raise PermissionDenied("You're not special!")
156160
```
157161

plain-flags/plain/flags/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class FooEnabled(Flag):
3737
Use flags in HTML templates:
3838

3939
```html
40-
{% if flags.FooEnabled(request.user) %}
40+
{% if flags.FooEnabled(get_current_user()) %}
4141
<p>Foo is enabled for you!</p>
4242
{% else %}
4343
<p>Foo is disabled for you.</p>

plain-htmx/plain/htmx/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ Then in the view class, we can define methods for each HTTP method + `plain-hx-a
202202
class PullRequestDetailView(HTMXViewMixin, DetailView):
203203
def get_queryset(self):
204204
# The queryset will apply to all actions on the view, so "permission" logic can be shared
205-
return super().get_queryset().filter(users=self.request.user)
205+
return super().get_queryset().filter(users=self.user)
206206

207207
# Action handling methods follow this format:
208208
# htmx_{method}_{action}
@@ -251,7 +251,7 @@ this can basically all be done through standard request and response headers:
251251
class PullRequestDetailView(HTMXViewMixin, DetailView):
252252
def get_queryset(self):
253253
# The queryset will apply to all actions on the view, so "permission" logic can be shared
254-
return super().get_queryset().filter(users=self.request.user)
254+
return super().get_queryset().filter(users=self.user)
255255

256256
# You can also leave off the "plain-hx-action" attribute and just handle the HTTP method
257257
def htmx_delete(self):

plain-models/plain/models/fields/related_descriptors.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,9 @@ def __set__(self, instance, value):
199199
- ``instance`` is the ``child`` instance
200200
- ``value`` is the ``parent`` instance on the right of the equal sign
201201
"""
202-
# If value is a LazyObject (like SimpleLazyObject used for request.user),
203-
# force its evaluation. For ForeignKey fields, the value should only be
204-
# None or a model instance, never a boolean or other type.
202+
# If value is a LazyObject, force its evaluation. For ForeignKey fields,
203+
# the value should only be None or a model instance, never a boolean or
204+
# other type.
205205
if isinstance(value, LazyObject):
206206
# This forces evaluation: if it's None, value becomes None;
207207
# if it's a User instance, value becomes that instance.

plain-oauth/plain/oauth/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,11 @@ Here's an very basic example:
182182
{% extends "base.html" %}
183183

184184
{% block content %}
185-
Hello {{ request.user }}!
185+
Hello {{ get_current_user() }}!
186186

187187
<h2>Existing connections</h2>
188188
<ul>
189-
{% for connection in request.user.oauth_connections.all %}
189+
{% for connection in get_current_user().oauth_connections.all %}
190190
<li>
191191
{{ connection.provider_key }} [ID: {{ connection.provider_user_id }}]
192192
<form action="{% url 'oauth:disconnect' connection.provider_key %}" method="post">

plain-pages/plain/pages/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ title: Features
5656
---
5757

5858
<h1>{{ page.title }}</h1>
59-
<p>Current user: {{ request.user }}</p>
59+
<p>Current user: {{ get_current_user() }}</p>
6060
```
6161

6262
### Markdown pages

plain-sessions/plain/sessions/README.md

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,38 @@ Sessions are implemented as a dictionary-like object that automatically handles
2020

2121
## Basic usage
2222

23-
Sessions are automatically available on request objects when the middleware is installed. You can use `request.session` like a standard Python dictionary:
23+
In views that inherit from `SessionViewMixin`, you can use `self.session` like a standard Python dictionary:
2424

2525
```python
26+
from plain.sessions.views import SessionViewMixin
2627
from plain.views import View
2728

28-
class MyView(View):
29+
class MyView(SessionViewMixin, View):
2930
def get(self):
3031
# Store values in the session
31-
self.request.session['username'] = 'jane'
32-
self.request.session['cart_items'] = [1, 2, 3]
32+
self.session['username'] = 'jane'
33+
self.session['cart_items'] = [1, 2, 3]
3334

3435
# Retrieve values from the session
35-
username = self.request.session.get('username')
36-
cart_items = self.request.session.get('cart_items', [])
36+
username = self.session.get('username')
37+
cart_items = self.session.get('cart_items', [])
3738

3839
# Check if a key exists
39-
if 'username' in self.request.session:
40+
if 'username' in self.session:
4041
# User has a session
4142
pass
4243

4344
# Delete values from the session
44-
del self.request.session['cart_items']
45+
del self.session['cart_items']
46+
```
47+
48+
Outside of views, you can use `get_request_session()`:
49+
50+
```python
51+
from plain.sessions import get_request_session
52+
53+
session = get_request_session(request)
54+
session['key'] = 'value'
4555
```
4656

4757
The session data is automatically saved when you set or delete values. Sessions are stored in the database using the [`Session`](./models.py#Session) model.
@@ -89,23 +99,41 @@ The [`SessionStore`](./core.py#SessionStore) class provides additional methods f
8999
To completely remove the current session data and regenerate the session key:
90100

91101
```python
92-
# Delete all session data and get a new session key
93-
request.session.flush()
102+
# In a view with SessionViewMixin
103+
self.session.flush()
104+
105+
# Outside a view
106+
from plain.sessions import get_request_session
107+
session = get_request_session(request)
108+
session.flush()
94109
```
95110

96111
### Cycling session keys
97112

98113
To create a new session key while retaining the current session data (useful for security purposes):
99114

100115
```python
101-
# Keep the data but change the session key
102-
request.session.cycle_key()
116+
# In a view with SessionViewMixin
117+
self.session.cycle_key()
118+
119+
# Outside a view
120+
from plain.sessions import get_request_session
121+
session = get_request_session(request)
122+
session.cycle_key()
103123
```
104124

105125
### Checking if session is empty
106126

107127
```python
108-
if request.session.is_empty():
128+
# In a view with SessionViewMixin
129+
if self.session.is_empty():
130+
# No session data exists
131+
pass
132+
133+
# Outside a view
134+
from plain.sessions import get_request_session
135+
session = get_request_session(request)
136+
if session.is_empty():
109137
# No session data exists
110138
pass
111139
```

plain-toolbar/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ Add the toolbar to your base template:
3131
</html>
3232
```
3333

34-
The toolbar will appear when `settings.DEBUG` is True or when `request.user.is_admin` is True.
34+
The toolbar will appear when `settings.DEBUG` is True or when the authenticated user has `is_admin` set to True.

0 commit comments

Comments
 (0)