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

template-integration.mddocs/

0

# Template Integration

1

2

Django template tags for displaying notification counts, status indicators, and live-updating notification interfaces with JavaScript integration for real-time updates.

3

4

## Capabilities

5

6

### Template Tags

7

8

Django template tags for displaying notification information and generating JavaScript for live updates.

9

10

```python { .api }

11

@register.simple_tag(takes_context=True)

12

def notifications_unread(context):

13

"""

14

Get unread notification count for current user (cached).

15

16

Args:

17

context: Django template context containing request and user

18

19

Returns:

20

int: Number of unread notifications for authenticated user, 0 for anonymous

21

22

Template usage:

23

{% notifications_unread %}

24

{% notifications_unread as count %}

25

"""

26

27

@register.filter

28

def has_notification(user):

29

"""

30

Check if user has any unread notifications.

31

32

Args:

33

user: Django User object

34

35

Returns:

36

bool: True if user has unread notifications, False otherwise

37

38

Template usage:

39

{{ user|has_notification }}

40

{% if user|has_notification %}...{% endif %}

41

"""

42

43

@register.simple_tag

44

def register_notify_callbacks(

45

badge_class='live_notify_badge',

46

menu_class='live_notify_list',

47

refresh_period=15,

48

callbacks='',

49

api_name='list',

50

fetch=5,

51

nonce=None,

52

mark_as_read=False

53

):

54

"""

55

Generate JavaScript code for live notification functionality.

56

57

Args:

58

badge_class (str): CSS class for notification badge elements

59

menu_class (str): CSS class for notification list elements

60

refresh_period (int): Update interval in seconds

61

callbacks (str): Comma-separated callback function names

62

api_name (str): API endpoint type ('list' or 'count')

63

fetch (int): Number of notifications to fetch

64

nonce (str, optional): CSP nonce for script tag

65

mark_as_read (bool): Auto-mark notifications as read when fetched

66

67

Returns:

68

str: HTML script tag with JavaScript configuration

69

70

Template usage:

71

{% register_notify_callbacks %}

72

{% register_notify_callbacks refresh_period=30 fetch=10 %}

73

"""

74

75

@register.simple_tag(takes_context=True)

76

def live_notify_badge(context, badge_class='live_notify_badge'):

77

"""

78

Render live notification count badge.

79

80

Args:

81

context: Django template context

82

badge_class (str): CSS class for badge element

83

84

Returns:

85

str: HTML span element with current unread count

86

87

Template usage:

88

{% live_notify_badge %}

89

{% live_notify_badge "my-badge-class" %}

90

"""

91

92

@register.simple_tag

93

def live_notify_list(list_class='live_notify_list'):

94

"""

95

Render empty notification list container for JavaScript population.

96

97

Args:

98

list_class (str): CSS class for list container

99

100

Returns:

101

str: Empty HTML ul element for notifications

102

103

Template usage:

104

{% live_notify_list %}

105

{% live_notify_list "my-list-class" %}

106

"""

107

```

108

109

### Caching Function

110

111

```python { .api }

112

def get_cached_notification_unread_count(user):

113

"""

114

Get cached unread notification count for user.

115

116

Args:

117

user: Django User object

118

119

Returns:

120

int: Cached unread notification count

121

122

Note:

123

Uses Django cache with CACHE_TIMEOUT setting for cache duration

124

"""

125

```

126

127

### Usage Examples

128

129

#### Basic Template Integration

130

131

```html

132

<!-- Load the template tags -->

133

{% load notifications_tags %}

134

135

<!-- Simple unread count display -->

136

<div class="notifications">

137

Notifications ({% notifications_unread %})

138

</div>

139

140

<!-- Store count in variable -->

141

{% notifications_unread as unread_count %}

142

{% if unread_count > 0 %}

143

<div class="notification-alert">

144

You have {{ unread_count }} unread notification{{ unread_count|pluralize }}

145

</div>

146

{% endif %}

147

148

<!-- Check if user has notifications -->

149

{% if user|has_notification %}

150

<span class="notification-indicator">●</span>

151

{% endif %}

152

```

153

154

#### Navigation Bar Integration

155

156

```html

157

{% load notifications_tags %}

158

159

<nav class="navbar">

160

<ul class="nav-items">

161

<li class="nav-item">

162

<a href="{% url 'notifications:unread' %}" class="nav-link">

163

<i class="icon-bell"></i>

164

Notifications

165

{% notifications_unread as count %}

166

{% if count > 0 %}

167

<span class="badge badge-danger">{{ count }}</span>

168

{% endif %}

169

</a>

170

</li>

171

</ul>

172

</nav>

173

174

<!-- Dropdown notification menu -->

175

<div class="notification-dropdown">

176

<button class="dropdown-toggle" data-toggle="dropdown">

177

<i class="icon-bell"></i>

178

{% if user|has_notification %}

179

<span class="notification-dot"></span>

180

{% endif %}

181

</button>

182

<div class="dropdown-menu">

183

<div class="dropdown-header">

184

Notifications

185

<span class="count">{% notifications_unread %}</span>

186

</div>

187

<div class="notification-list" id="notification-dropdown-list">

188

<!-- Will be populated by JavaScript -->

189

</div>

190

<div class="dropdown-footer">

191

<a href="{% url 'notifications:all' %}">View All</a>

192

<a href="{% url 'notifications:mark_all_as_read' %}">Mark All as Read</a>

193

</div>

194

</div>

195

</div>

196

```

197

198

#### Live Notification Setup

199

200

```html

201

{% load notifications_tags %}

202

203

<!DOCTYPE html>

204

<html>

205

<head>

206

<title>My App</title>

207

<style>

208

.live_notify_badge {

209

background: red;

210

color: white;

211

border-radius: 50%;

212

padding: 2px 6px;

213

font-size: 12px;

214

position: absolute;

215

top: -8px;

216

right: -8px;

217

}

218

219

.live_notify_list {

220

max-height: 300px;

221

overflow-y: auto;

222

border: 1px solid #ddd;

223

border-radius: 4px;

224

}

225

226

.notification-item {

227

padding: 10px;

228

border-bottom: 1px solid #eee;

229

cursor: pointer;

230

}

231

232

.notification-item:hover {

233

background-color: #f5f5f5;

234

}

235

</style>

236

</head>

237

<body>

238

<div class="header">

239

<div class="notification-container" style="position: relative;">

240

<i class="icon-bell"></i>

241

<!-- Live badge that updates automatically -->

242

{% live_notify_badge %}

243

</div>

244

</div>

245

246

<div class="notification-panel">

247

<h3>Recent Notifications</h3>

248

<!-- Live list that updates automatically -->

249

{% live_notify_list %}

250

</div>

251

252

<!-- Register JavaScript for live updates -->

253

{% register_notify_callbacks refresh_period=20 fetch=8 %}

254

255

<!-- Custom callback functions -->

256

<script>

257

function onNotificationUpdate(data) {

258

console.log('Notifications updated:', data);

259

// Custom handling when notifications are updated

260

if (data.unread_count > 0) {

261

document.title = `(${data.unread_count}) My App`;

262

} else {

263

document.title = 'My App';

264

}

265

}

266

267

function onNotificationClick(notification) {

268

console.log('Notification clicked:', notification);

269

// Handle notification click

270

window.location.href = '/notification/' + notification.id;

271

}

272

</script>

273

274

<!-- Register callbacks -->

275

{% register_notify_callbacks callbacks="onNotificationUpdate,onNotificationClick" %}

276

</body>

277

</html>

278

```

279

280

#### Advanced Configuration

281

282

```html

283

{% load notifications_tags %}

284

285

<!-- Custom CSS classes and configuration -->

286

{% register_notify_callbacks

287

badge_class="my-notification-badge"

288

menu_class="my-notification-menu"

289

refresh_period=30

290

api_name="list"

291

fetch=15

292

mark_as_read=True

293

%}

294

295

<!-- Multiple notification areas -->

296

<div class="sidebar">

297

<h4>Quick Notifications</h4>

298

{% live_notify_list "sidebar-notifications" %}

299

</div>

300

301

<div class="main-content">

302

<div class="toolbar">

303

<span class="notification-icon">

304

πŸ””

305

{% live_notify_badge "toolbar-badge" %}

306

</span>

307

</div>

308

</div>

309

310

<!-- Configure different areas with different settings -->

311

<script>

312

// Custom configuration for sidebar

313

{% register_notify_callbacks

314

menu_class="sidebar-notifications"

315

fetch=5

316

refresh_period=60

317

%}

318

319

// Custom configuration for toolbar

320

{% register_notify_callbacks

321

badge_class="toolbar-badge"

322

api_name="count"

323

refresh_period=15

324

%}

325

</script>

326

```

327

328

#### CSP (Content Security Policy) Support

329

330

```html

331

{% load notifications_tags %}

332

333

<!-- Generate nonce for CSP -->

334

{% csrf_token %}

335

<script nonce="{{ csp_nonce }}">

336

const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;

337

</script>

338

339

<!-- Pass nonce to template tag -->

340

{% register_notify_callbacks nonce=csp_nonce %}

341

```

342

343

#### Conditional Loading

344

345

```html

346

{% load notifications_tags %}

347

348

<!-- Only load live notifications for authenticated users -->

349

{% if user.is_authenticated %}

350

<div class="user-notifications">

351

{% if user|has_notification %}

352

<div class="notification-alert">

353

You have new notifications!

354

{% live_notify_badge %}

355

</div>

356

{% endif %}

357

358

{% live_notify_list %}

359

{% register_notify_callbacks %}

360

</div>

361

{% else %}

362

<div class="guest-message">

363

<a href="{% url 'login' %}">Login</a> to see notifications

364

</div>

365

{% endif %}

366

```

367

368

#### Integration with Bootstrap

369

370

```html

371

{% load notifications_tags %}

372

373

<!-- Bootstrap navbar with notification dropdown -->

374

<nav class="navbar navbar-expand-lg navbar-dark bg-dark">

375

<div class="navbar-nav ms-auto">

376

<div class="nav-item dropdown">

377

<a class="nav-link dropdown-toggle position-relative" href="#" data-bs-toggle="dropdown">

378

<i class="fas fa-bell"></i>

379

{% live_notify_badge "position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger" %}

380

</a>

381

<div class="dropdown-menu dropdown-menu-end" style="width: 300px;">

382

<h6 class="dropdown-header">

383

Notifications

384

<span class="badge bg-primary ms-2">{% notifications_unread %}</span>

385

</h6>

386

<div class="dropdown-divider"></div>

387

<div class="notification-container" style="max-height: 400px; overflow-y: auto;">

388

{% live_notify_list "list-unstyled" %}

389

</div>

390

<div class="dropdown-divider"></div>

391

<div class="dropdown-item-text text-center">

392

<a href="{% url 'notifications:all' %}" class="btn btn-sm btn-outline-primary me-2">

393

View All

394

</a>

395

<a href="{% url 'notifications:mark_all_as_read' %}" class="btn btn-sm btn-outline-secondary">

396

Mark All Read

397

</a>

398

</div>

399

</div>

400

</div>

401

</div>

402

</nav>

403

404

<!-- Bootstrap styling for notifications -->

405

<style>

406

.list-unstyled .notification-item {

407

padding: 0.5rem 1rem;

408

border-bottom: 1px solid #dee2e6;

409

text-decoration: none;

410

color: inherit;

411

display: block;

412

}

413

414

.list-unstyled .notification-item:hover {

415

background-color: #f8f9fa;

416

}

417

418

.list-unstyled .notification-item:last-child {

419

border-bottom: none;

420

}

421

</style>

422

423

{% register_notify_callbacks

424

menu_class="list-unstyled"

425

badge_class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger"

426

refresh_period=25

427

fetch=10

428

%}

429

```

430

431

#### Custom Notification Rendering

432

433

```html

434

{% load notifications_tags %}

435

436

<!-- Override default notification rendering -->

437

<script>

438

function customNotificationRenderer(notifications) {

439

const container = document.querySelector('.live_notify_list');

440

container.innerHTML = '';

441

442

notifications.forEach(notification => {

443

const item = document.createElement('div');

444

item.className = 'notification-item';

445

item.innerHTML = `

446

<div class="notification-avatar">

447

<img src="/static/img/avatar-placeholder.png" alt="Avatar">

448

</div>

449

<div class="notification-content">

450

<div class="notification-text">

451

<strong>${notification.actor}</strong> ${notification.verb}

452

${notification.target ? notification.target : ''}

453

</div>

454

<div class="notification-time">

455

${formatTimeAgo(notification.timestamp)}

456

</div>

457

</div>

458

<div class="notification-actions">

459

<button onclick="markAsRead(${notification.slug})" class="btn-sm">βœ“</button>

460

<button onclick="deleteNotification(${notification.slug})" class="btn-sm">βœ—</button>

461

</div>

462

`;

463

container.appendChild(item);

464

});

465

}

466

467

// Override the default render function

468

window.renderNotifications = customNotificationRenderer;

469

</script>

470

471

{% live_notify_list %}

472

{% register_notify_callbacks callbacks="customNotificationRenderer" %}

473

```

474

475

### Helper Functions

476

477

Internal helper functions used by template tags for user context handling and caching.

478

479

```python { .api }

480

def get_cached_notification_unread_count(user):

481

"""

482

Get cached unread notification count for user with configurable timeout.

483

484

Args:

485

user: Django User object

486

487

Returns:

488

int: Number of unread notifications (cached result)

489

490

Cache key: 'cache_notification_unread_count'

491

Cache timeout: Configured via CACHE_TIMEOUT setting

492

"""

493

494

def user_context(context):

495

"""

496

Extract authenticated user from template context.

497

498

Args:

499

context: Django template context dict

500

501

Returns:

502

User: Authenticated user object or None for anonymous/missing users

503

504

Handles:

505

- Missing user in context

506

- Anonymous users (both Django < 1.11 and >= 1.11 syntax)

507

- Authenticated users

508

"""

509

```