or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

admin-integration.mdapi-endpoints.mdconfiguration.mdcore-system.mdindex.mdsignals.mdtemplate-integration.mdutilities.mdweb-interface.md

utilities.mddocs/

0

# Utilities

1

2

Helper functions for formatting notifications, converting IDs to URL-safe slugs, and retrieving notification data for API responses with configurable limits and pagination.

3

4

## Capabilities

5

6

### Notification Helper Functions

7

8

Functions for processing and formatting notification data for API responses and template display.

9

10

```python { .api }

11

def get_notification_list(request, method_name='all'):

12

"""

13

Get formatted notification list for API responses.

14

15

Args:

16

request: Django HTTP request object

17

method_name (str): QuerySet method name ('all', 'unread', 'read', etc.)

18

19

Query Parameters (from request.GET):

20

max (int): Maximum notifications to return (1-100)

21

mark_as_read (str): Mark notifications as read if parameter exists

22

23

Returns:

24

list: List of notification dictionaries with formatted data

25

26

Dictionary structure:

27

{

28

'id': int,

29

'slug': int,

30

'actor': str,

31

'verb': str,

32

'target': str or None,

33

'action_object': str or None,

34

'description': str,

35

'timestamp': datetime,

36

'unread': bool,

37

'level': str,

38

'public': bool,

39

'deleted': bool,

40

'emailed': bool,

41

'data': dict

42

}

43

"""

44

45

def get_num_to_fetch(request):

46

"""

47

Extract and validate number of notifications to fetch from request.

48

49

Args:

50

request: Django HTTP request object

51

52

Query Parameters (from request.GET):

53

max (int, optional): Number of notifications requested

54

55

Returns:

56

int: Validated number between 1-100, defaults to NUM_TO_FETCH setting

57

58

Validation:

59

- Must be integer

60

- Must be between 1 and 100 inclusive

61

- Falls back to default if invalid

62

"""

63

```

64

65

### ID and Slug Conversion

66

67

Utility functions for converting between notification IDs and URL-safe slugs for secure URL patterns.

68

69

```python { .api }

70

def slug2id(slug):

71

"""

72

Convert notification slug back to database ID.

73

74

Args:

75

slug (int or str): URL slug representing notification

76

77

Returns:

78

int: Database ID for notification lookup

79

80

Formula: ID = slug - 110909

81

"""

82

83

def id2slug(notification_id):

84

"""

85

Convert notification database ID to URL-safe slug.

86

87

Args:

88

notification_id (int): Database ID of notification

89

90

Returns:

91

int: URL-safe slug for use in URLs and templates

92

93

Formula: slug = ID + 110909

94

"""

95

```

96

97

### Usage Examples

98

99

#### API Response Formatting

100

101

```python

102

from notifications.helpers import get_notification_list, get_num_to_fetch

103

from django.http import JsonResponse

104

105

def custom_notification_api(request):

106

"""Custom API endpoint using helper functions."""

107

108

# Get validated number to fetch

109

num_to_fetch = get_num_to_fetch(request)

110

print(f"Fetching {num_to_fetch} notifications")

111

112

# Get formatted notification list

113

unread_notifications = get_notification_list(request, 'unread')

114

all_notifications = get_notification_list(request, 'all')

115

116

return JsonResponse({

117

'unread': unread_notifications,

118

'all': all_notifications,

119

'meta': {

120

'requested_count': num_to_fetch,

121

'unread_count': len(unread_notifications),

122

'all_count': len(all_notifications)

123

}

124

})

125

126

# Example request: /api/notifications/?max=25&mark_as_read=true

127

# Returns formatted notification data with auto-read functionality

128

```

129

130

#### Custom View with Helpers

131

132

```python

133

from django.shortcuts import render

134

from django.contrib.auth.decorators import login_required

135

from notifications.helpers import get_notification_list

136

137

@login_required

138

def dashboard_notifications(request):

139

"""Dashboard view showing formatted notifications."""

140

141

# Get recent notifications for display

142

recent_notifications = get_notification_list(request, 'all')[:5]

143

unread_notifications = get_notification_list(request, 'unread')

144

145

# Process notifications for template

146

processed_notifications = []

147

for notification in recent_notifications:

148

processed_notifications.append({

149

'id': notification['id'],

150

'display_text': f"{notification['actor']} {notification['verb']}",

151

'target_text': notification.get('target', ''),

152

'time_ago': notification['timestamp'],

153

'is_unread': notification['unread'],

154

'edit_url': f"/admin/notifications/notification/{notification['id']}/change/",

155

'mark_read_url': f"/notifications/mark-as-read/{notification['slug']}/"

156

})

157

158

return render(request, 'dashboard/notifications.html', {

159

'notifications': processed_notifications,

160

'unread_count': len(unread_notifications)

161

})

162

```

163

164

#### Slug Conversion Examples

165

166

```python

167

from notifications.utils import id2slug, slug2id

168

from notifications.models import Notification

169

170

# Convert ID to slug for URL

171

notification = Notification.objects.get(id=123)

172

url_slug = id2slug(notification.id)

173

print(f"URL slug: {url_slug}") # Output: 111032

174

175

# Use in URL pattern

176

notification_url = f"/notifications/mark-as-read/{url_slug}/"

177

178

# Convert slug back to ID for database lookup

179

def mark_notification_read(request, slug):

180

notification_id = slug2id(slug)

181

notification = Notification.objects.get(

182

id=notification_id,

183

recipient=request.user

184

)

185

notification.mark_as_read()

186

return redirect('notifications:all')

187

188

# Bulk slug operations

189

notification_ids = [100, 101, 102, 103]

190

slugs = [id2slug(nid) for nid in notification_ids]

191

print(f"Slugs: {slugs}") # [111009, 111010, 111011, 111012]

192

193

# Convert back

194

original_ids = [slug2id(slug) for slug in slugs]

195

print(f"Original IDs: {original_ids}") # [100, 101, 102, 103]

196

```

197

198

#### Request Parameter Processing

199

200

```python

201

from notifications.helpers import get_num_to_fetch

202

203

def process_notification_request(request):

204

"""Demonstrate request parameter processing."""

205

206

# Various request scenarios

207

test_requests = [

208

{'GET': {}}, # Default: 10

209

{'GET': {'max': '25'}}, # Valid: 25

210

{'GET': {'max': '150'}}, # Too large: 10 (default)

211

{'GET': {'max': '0'}}, # Too small: 10 (default)

212

{'GET': {'max': 'invalid'}}, # Invalid: 10 (default)

213

{'GET': {'max': '50'}}, # Valid: 50

214

]

215

216

results = []

217

for req_data in test_requests:

218

# Mock request object

219

class MockRequest:

220

def __init__(self, get_data):

221

self.GET = get_data

222

223

mock_request = MockRequest(req_data['GET'])

224

num_to_fetch = get_num_to_fetch(mock_request)

225

results.append({

226

'input': req_data['GET'].get('max', 'not provided'),

227

'output': num_to_fetch

228

})

229

230

return results

231

232

# Example output:

233

# [

234

# {'input': 'not provided', 'output': 10},

235

# {'input': '25', 'output': 25},

236

# {'input': '150', 'output': 10},

237

# {'input': '0', 'output': 10},

238

# {'input': 'invalid', 'output': 10},

239

# {'input': '50', 'output': 50}

240

# ]

241

```

242

243

#### Custom Notification Formatter

244

245

```python

246

from notifications.helpers import get_notification_list

247

from django.contrib.humanize.templatetags.humanize import naturaltime

248

249

def format_notifications_for_email(user, max_notifications=20):

250

"""Format notifications for email digest."""

251

252

# Create mock request for helper function

253

class MockRequest:

254

def __init__(self, user, max_count):

255

self.user = user

256

self.GET = {'max': str(max_count)}

257

258

mock_request = MockRequest(user, max_notifications)

259

notifications = get_notification_list(mock_request, 'unread')

260

261

formatted_notifications = []

262

for notification in notifications:

263

formatted_notifications.append({

264

'subject': f"New notification: {notification['verb']}",

265

'message': notification.get('description',

266

f"{notification['actor']} {notification['verb']}"),

267

'time': naturaltime(notification['timestamp']),

268

'actor': notification['actor'],

269

'action': notification['verb'],

270

'target': notification.get('target'),

271

'url': f"https://example.com/notifications/mark-as-read/{notification['slug']}/"

272

})

273

274

return formatted_notifications

275

276

# Usage

277

user_notifications = format_notifications_for_email(user, 10)

278

for notif in user_notifications:

279

print(f"Email: {notif['subject']}")

280

print(f"Content: {notif['message']}")

281

print(f"Time: {notif['time']}")

282

print("---")

283

```

284

285

#### Pagination Helper

286

287

```python

288

from notifications.helpers import get_num_to_fetch

289

from django.core.paginator import Paginator

290

291

def paginated_notifications(request, method_name='all'):

292

"""Get paginated notifications using helper functions."""

293

294

# Get number to fetch per page

295

per_page = get_num_to_fetch(request)

296

297

# Get user's notifications

298

if method_name == 'unread':

299

notifications = request.user.notifications.unread()

300

elif method_name == 'read':

301

notifications = request.user.notifications.read()

302

else:

303

notifications = request.user.notifications.all()

304

305

# Create paginator

306

paginator = Paginator(notifications, per_page)

307

page_number = request.GET.get('page', 1)

308

page_obj = paginator.get_page(page_number)

309

310

# Format notifications for response

311

formatted_notifications = []

312

for notification in page_obj:

313

formatted_notifications.append({

314

'id': notification.id,

315

'slug': notification.slug,

316

'actor': str(notification.actor),

317

'verb': notification.verb,

318

'target': str(notification.target) if notification.target else None,

319

'description': notification.description,

320

'timestamp': notification.timestamp,

321

'unread': notification.unread,

322

'level': notification.level

323

})

324

325

return {

326

'notifications': formatted_notifications,

327

'pagination': {

328

'has_previous': page_obj.has_previous(),

329

'has_next': page_obj.has_next(),

330

'previous_page_number': page_obj.previous_page_number() if page_obj.has_previous() else None,

331

'next_page_number': page_obj.next_page_number() if page_obj.has_next() else None,

332

'current_page': page_obj.number,

333

'total_pages': page_obj.paginator.num_pages,

334

'total_count': page_obj.paginator.count,

335

'per_page': per_page

336

}

337

}

338

339

# Usage in view

340

def notification_list_api(request):

341

result = paginated_notifications(request, 'unread')

342

return JsonResponse(result)

343

```

344

345

#### Bulk Operations with Utilities

346

347

```python

348

from notifications.utils import slug2id

349

from notifications.models import Notification

350

351

def bulk_mark_notifications_read(request):

352

"""Mark multiple notifications as read using slugs."""

353

354

# Get slugs from request (e.g., form data or JSON)

355

slugs = request.POST.getlist('notification_slugs')

356

# or from JSON: slugs = json.loads(request.body).get('slugs', [])

357

358

# Convert slugs to IDs

359

notification_ids = [slug2id(slug) for slug in slugs]

360

361

# Bulk update notifications

362

updated_count = Notification.objects.filter(

363

id__in=notification_ids,

364

recipient=request.user,

365

unread=True

366

).update(unread=False)

367

368

return JsonResponse({

369

'success': True,

370

'updated_count': updated_count,

371

'processed_ids': notification_ids

372

})

373

374

def generate_notification_urls(notifications):

375

"""Generate URLs for a list of notifications."""

376

377

urls = {}

378

for notification in notifications:

379

slug = notification.slug # Uses property from model

380

urls[notification.id] = {

381

'mark_read': f"/notifications/mark-as-read/{slug}/",

382

'mark_unread': f"/notifications/mark-as-unread/{slug}/",

383

'delete': f"/notifications/delete/{slug}/",

384

'detail': f"/notifications/{slug}/"

385

}

386

387

return urls

388

389

# Example usage

390

user_notifications = user.notifications.unread()[:10]

391

notification_urls = generate_notification_urls(user_notifications)

392

393

for notification in user_notifications:

394

urls = notification_urls[notification.id]

395

print(f"Notification {notification.id}:")

396

print(f" Mark Read: {urls['mark_read']}")

397

print(f" Delete: {urls['delete']}")

398

```