Skip to content

Commit a835f5e

Browse files
authored
serialize as str when field is UUID type (#11)
* serialize as str when field is UUID type * ci: update workflow github * add cuser middleware
1 parent 6395159 commit a835f5e

File tree

5 files changed

+76
-51
lines changed

5 files changed

+76
-51
lines changed

.github/workflows/python-app.yml

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,45 @@ jobs:
1515
runs-on: ubuntu-latest
1616
strategy:
1717
matrix:
18-
django_version: [ '3.2', '4.0', '4.1', '4.2' ]
19-
python_version: [ '3.7', '3.8', '3.9', '3.10', '3.11' ]
18+
django_version: [ '4.2', '5.2', '6.0']
19+
python_version: [ '3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14' ]
2020
exclude:
21-
- django_version: '3.2'
22-
python_version: '3.11'
21+
- django_version: '4.2'
22+
python_version: '3.13'
2323

24-
- django_version: '4.0'
25-
python_version: '3.11'
24+
- django_version: '4.2'
25+
python_version: '3.14'
2626

27-
- django_version: '4.1'
28-
python_version: '3.11'
27+
- django_version: '5.2'
28+
python_version: '3.8'
2929

30-
- django_version: '4.0'
31-
python_version: '3.7'
30+
- django_version: '5.2'
31+
python_version: '3.9'
3232

33-
- django_version: '4.1'
34-
python_version: '3.7'
33+
- django_version: '6.0'
34+
python_version: '3.8'
35+
36+
- django_version: '6.0'
37+
python_version: '3.9'
38+
39+
- django_version: '6.0'
40+
python_version: '3.10'
41+
42+
- django_version: '6.0'
43+
python_version: '3.11'
3544

36-
- django_version: '4.2'
37-
python_version: '3.7'
3845
env:
3946
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4047
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
4148

4249
steps:
43-
- uses: actions/checkout@v2
50+
- uses: actions/checkout@v6
4451
- name: Set up Python ${{ matrix.python_version }}
45-
uses: actions/setup-python@v2
52+
uses: actions/setup-python@v5
4653
with:
4754
python-version: ${{ matrix.python_version }}
4855
- name: Cache pip
49-
uses: actions/cache@v2
56+
uses: actions/cache@v4
5057
with:
5158
# This path is specific to Ubuntu
5259
path: ~/.cache/pip
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from __future__ import unicode_literals
2+
import threading
3+
from django.contrib.auth import get_user_model
4+
5+
6+
class CuserMiddleware:
7+
_thread_local = threading.local()
8+
9+
def __init__(self, get_response):
10+
self.get_response = get_response
11+
12+
def __call__(self, request):
13+
try:
14+
self.__class__.set_user(request.user)
15+
response = self.get_response(request)
16+
return response
17+
finally:
18+
self.__class__.del_user()
19+
20+
@classmethod
21+
def get_user(cls, default=None):
22+
"""
23+
Retrieve user info
24+
"""
25+
return getattr(cls._thread_local, 'user', default)
26+
27+
@classmethod
28+
def set_user(cls, user):
29+
"""
30+
Store user info
31+
"""
32+
if isinstance(user, str):
33+
user_model = get_user_model()
34+
user = user_model.objects.get(username=user)
35+
cls._thread_local.user = user
36+
37+
@classmethod
38+
def del_user(cls):
39+
"""
40+
Delete user info
41+
"""
42+
if hasattr(cls._thread_local, 'user'):
43+
del cls._thread_local.user

tracking_fields/tests/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"django.middleware.common.CommonMiddleware",
4747
"django.middleware.csrf.CsrfViewMiddleware",
4848
"django.contrib.auth.middleware.AuthenticationMiddleware",
49+
"tracking_fields.middleware.cuser.CuserMiddleware",
4950
"django.contrib.messages.middleware.MessageMiddleware",
5051
"django.middleware.clickjacking.XFrameOptionsMiddleware",
5152
)

tracking_fields/tests/tests.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import datetime
55
import json
66

7-
from cuser.middleware import CuserMiddleware
7+
from tracking_fields.middleware.cuser import CuserMiddleware
88
from django.contrib.auth.models import User
99
from django.contrib.contenttypes.models import ContentType
1010
from django.core.files import File
@@ -55,26 +55,6 @@ def test_create(self):
5555
assert human_event.user == self.user
5656
assert human_event.user_repr == self.user_repr
5757

58-
def test_update_without_cuser(self):
59-
"""
60-
Test the CREATE event without the cuser module
61-
"""
62-
from tracking_fields import tracking
63-
64-
tracking.CUSER = False
65-
self.human.age = 43
66-
self.human.save()
67-
events = TrackingEvent.objects.order_by("date").all()
68-
assert events.count() == 3
69-
human_event = events.last()
70-
assert human_event.date is not None
71-
assert human_event.action == UPDATE
72-
assert human_event.object == self.human
73-
assert human_event.object_repr == self.human_repr
74-
assert human_event.user is None
75-
assert human_event.user_repr == "None"
76-
tracking.CUSER = True
77-
7858
def test_update(self):
7959
"""
8060
Test the UPDATE event

tracking_fields/tracking.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import datetime
44
import json
55
import logging
6+
import uuid
67

8+
from tracking_fields.middleware.cuser import CuserMiddleware
79
from django.contrib.contenttypes.models import ContentType
810
from django.core.exceptions import ObjectDoesNotExist
911
from django.db.models import ManyToManyField, Model
@@ -15,13 +17,6 @@
1517
except ImportError:
1618
StateWrapper = type("StateWrapper", (object,), dict())
1719

18-
try:
19-
from cuser.middleware import CuserMiddleware
20-
21-
CUSER = True
22-
except ImportError:
23-
CUSER = False
24-
2520
from tracking_fields.models import (
2621
CREATE,
2722
DELETE,
@@ -116,13 +111,10 @@ def _create_event(instance, action):
116111
"""
117112
Create a new event, getting the use if django-cuser is available.
118113
"""
119-
user = None
114+
user = CuserMiddleware.get_user()
120115
user_repr = repr(user)
121-
if CUSER:
122-
user = CuserMiddleware.get_user()
123-
user_repr = repr(user)
124-
if user is not None and user.is_anonymous:
125-
user = None
116+
if user is not None and user.is_anonymous:
117+
user = None
126118
return TrackingEvent.objects.create(
127119
action=action,
128120
object_content_type=ContentType.objects.get_for_model(instance),
@@ -144,6 +136,8 @@ def _serialize_field(field):
144136
except ValueError:
145137
# No file
146138
return json.dumps(None, ensure_ascii=False)
139+
if isinstance(field, uuid.UUID):
140+
return json.dumps(str(field), ensure_ascii=False)
147141
if isinstance(field, Model):
148142
return json.dumps(str(field), ensure_ascii=False)
149143
if isinstance(field, StateWrapper):

0 commit comments

Comments
 (0)