or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

extension-setup.mdform-rendering.mdindex.mdnavigation.mdpagination.mdpython-utilities.mdtable-rendering.mdutilities.md

pagination.mddocs/

0

# Pagination

1

2

Pagination component rendering for Flask-SQLAlchemy pagination objects with customizable navigation controls, alignment options, URL fragment support, and responsive design considerations.

3

4

## Capabilities

5

6

### Full Pagination

7

8

Render complete pagination with numbered pages and navigation controls.

9

10

```python { .api }

11

def render_pagination(pagination, endpoint=None, prev='«', next='»',

12

size=None, ellipses='…', args={}, fragment='', align=''):

13

"""

14

Render full pagination with numbered pages.

15

16

Args:

17

pagination: Flask-SQLAlchemy Pagination object

18

endpoint (str): Flask endpoint for pagination links (defaults to current endpoint)

19

prev (str): Previous button text/HTML (default: '«')

20

next (str): Next button text/HTML (default: '»')

21

size (str): Pagination size - 'sm' or 'lg' for small/large

22

ellipses (str): Text for ellipsis indicator (default: '…')

23

args (dict): Additional URL parameters to preserve

24

fragment (str): URL fragment (#section) to append to links

25

align (str): Alignment - 'center' or 'right' (default: left)

26

27

Returns:

28

Rendered HTML pagination with Bootstrap styling

29

30

Pagination Object Properties Used:

31

- page: Current page number

32

- pages: Total number of pages

33

- per_page: Items per page

34

- total: Total number of items

35

- has_prev: Boolean for previous page availability

36

- has_next: Boolean for next page availability

37

- prev_num: Previous page number

38

- next_num: Next page number

39

- iter_pages(): Iterator for page numbers with gaps

40

"""

41

```

42

43

### Simple Pager

44

45

Render simplified pagination with only Previous/Next buttons.

46

47

```python { .api }

48

def render_pager(pagination, fragment='',

49

prev='<span aria-hidden="true">&larr;</span> Previous',

50

next='Next <span aria-hidden="true">&rarr;</span>', align=''):

51

"""

52

Render simple pagination pager (Previous/Next only).

53

54

Args:

55

pagination: Flask-SQLAlchemy Pagination object

56

fragment (str): URL fragment to append to links

57

prev (str): Previous button text/HTML

58

next (str): Next button text/HTML

59

align (str): Alignment - 'center' or 'right'

60

61

Returns:

62

Rendered HTML pager with Bootstrap styling

63

64

Usage:

65

- Simpler alternative to full pagination

66

- Better for mobile interfaces

67

- Suitable when page numbers aren't necessary

68

"""

69

```

70

71

### Current Page Display

72

73

Internal helper for rendering the current active page indicator.

74

75

```python { .api }

76

def get_current_page(page):

77

"""

78

Render the current active page in pagination.

79

80

Args:

81

page (int): Current page number

82

83

Returns:

84

Rendered HTML for current page indicator

85

86

Note: Internal helper used by pagination macros

87

"""

88

```

89

90

## Pagination Features

91

92

### Flask-SQLAlchemy Integration

93

94

Bootstrap-Flask pagination works seamlessly with Flask-SQLAlchemy's pagination system:

95

96

```python

97

# View function with pagination

98

@app.route('/posts')

99

def posts():

100

page = request.args.get('page', 1, type=int)

101

posts = Post.query.paginate(

102

page=page,

103

per_page=5,

104

error_out=False

105

)

106

return render_template('posts.html', posts=posts)

107

```

108

109

### URL Parameter Preservation

110

111

Pagination automatically preserves existing URL parameters:

112

113

```python

114

# URL: /search?q=python&category=tutorial&page=2

115

args = {'q': 'python', 'category': 'tutorial'}

116

```

117

118

### Responsive Design

119

120

Pagination components adapt to different screen sizes:

121

122

- **Large screens**: Full pagination with all page numbers

123

- **Medium screens**: Pagination with ellipses for space

124

- **Small screens**: Consider using simple pager instead

125

126

## Usage Examples

127

128

### Basic Pagination

129

130

```python

131

# View function

132

@app.route('/users')

133

def users():

134

page = request.args.get('page', 1, type=int)

135

users = User.query.paginate(

136

page=page,

137

per_page=10,

138

error_out=False

139

)

140

return render_template('users.html', users=users)

141

```

142

143

```html

144

<!-- Template -->

145

{% from 'base/pagination.html' import render_pagination %}

146

147

<div class="container">

148

<!-- Display items -->

149

{% for user in users.items %}

150

<div class="card mb-2">

151

<div class="card-body">

152

<h5>{{ user.name }}</h5>

153

<p>{{ user.email }}</p>

154

</div>

155

</div>

156

{% endfor %}

157

158

<!-- Pagination -->

159

{{ render_pagination(users) }}

160

</div>

161

```

162

163

### Centered Pagination

164

165

```html

166

{{ render_pagination(posts, align='center') }}

167

```

168

169

### Right-Aligned Pagination

170

171

```html

172

{{ render_pagination(products, align='right') }}

173

```

174

175

### Large Pagination

176

177

```html

178

{{ render_pagination(posts, size='lg') }}

179

```

180

181

### Small Pagination

182

183

```html

184

{{ render_pagination(comments, size='sm') }}

185

```

186

187

### Custom Navigation Text

188

189

```html

190

{{ render_pagination(posts,

191

prev='← Previous Posts',

192

next='Next Posts →'

193

) }}

194

```

195

196

### Pagination with URL Parameters

197

198

```python

199

# View preserving search parameters

200

@app.route('/search')

201

def search():

202

query = request.args.get('q', '')

203

category = request.args.get('category', '')

204

page = request.args.get('page', 1, type=int)

205

206

results = Post.query.filter(

207

Post.title.contains(query)

208

).paginate(page=page, per_page=10)

209

210

return render_template('search.html',

211

results=results,

212

search_args={'q': query, 'category': category})

213

```

214

215

```html

216

{{ render_pagination(results, args=search_args) }}

217

```

218

219

### Pagination with URL Fragments

220

221

```html

222

<!-- Jump to results section after page change -->

223

{{ render_pagination(results, fragment='results') }}

224

225

<!-- Results section -->

226

<div id="results">

227

<!-- Search results here -->

228

</div>

229

```

230

231

### Simple Pager Alternative

232

233

```html

234

{% from 'base/pagination.html' import render_pager %}

235

236

<!-- Simple Previous/Next pager -->

237

{{ render_pager(posts) }}

238

239

<!-- Centered pager -->

240

{{ render_pager(posts, align='center') }}

241

242

<!-- Custom pager text -->

243

{{ render_pager(posts,

244

prev='← Older Posts',

245

next='Newer Posts →'

246

) }}

247

```

248

249

### Pagination with Item Count

250

251

```html

252

<div class="d-flex justify-content-between align-items-center mb-3">

253

<small class="text-muted">

254

Showing {{ posts.per_page * (posts.page - 1) + 1 }} to

255

{{ posts.per_page * posts.page if posts.page < posts.pages else posts.total }}

256

of {{ posts.total }} posts

257

</small>

258

259

{{ render_pagination(posts, align='right') }}

260

</div>

261

```

262

263

### AJAX Pagination

264

265

```html

266

<!-- Pagination with data attributes for AJAX -->

267

<div id="pagination-container">

268

{{ render_pagination(posts, endpoint='api.posts') }}

269

</div>

270

271

<script>

272

// Handle pagination clicks with AJAX

273

$('#pagination-container').on('click', '.page-link', function(e) {

274

e.preventDefault();

275

const url = $(this).attr('href');

276

277

$.get(url, function(data) {

278

$('#content').html(data.content);

279

$('#pagination-container').html(data.pagination);

280

});

281

});

282

</script>

283

```

284

285

### Conditional Pagination Display

286

287

```html

288

{% if posts.pages > 1 %}

289

<nav aria-label="Posts pagination">

290

{{ render_pagination(posts) }}

291

</nav>

292

{% endif %}

293

```

294

295

### Bootstrap 4 vs Bootstrap 5 Differences

296

297

The pagination macros work identically across Bootstrap versions, but the underlying CSS classes differ:

298

299

#### Bootstrap 4

300

- Uses `page-item` and `page-link` classes

301

- Active state with `active` class

302

- Disabled state with `disabled` class

303

304

#### Bootstrap 5

305

- Same class structure as Bootstrap 4

306

- Enhanced accessibility attributes

307

- Improved focus states and keyboard navigation

308

309

### Advanced Pagination Configuration

310

311

```html

312

{{ render_pagination(posts,

313

endpoint='blog.posts', # Custom endpoint

314

prev='‹ Previous', # Custom previous text

315

next='Next ›', # Custom next text

316

size='lg', # Large pagination

317

ellipses='...', # Custom ellipsis

318

align='center', # Center alignment

319

args={'category': category}, # Preserve URL params

320

fragment='posts' # Jump to section

321

) }}

322

```

323

324

### Pagination Info Display

325

326

```html

327

<div class="row align-items-center">

328

<div class="col-md-6">

329

<small class="text-muted">

330

Page {{ posts.page }} of {{ posts.pages }}

331

({{ posts.total }} total {{ 'post' if posts.total == 1 else 'posts' }})

332

</small>

333

</div>

334

<div class="col-md-6">

335

{{ render_pagination(posts, align='right') }}

336

</div>

337

</div>

338

```

339

340

### Per-Page Selection

341

342

```html

343

<div class="d-flex justify-content-between align-items-center mb-3">

344

<div>

345

<label class="form-label">Items per page:</label>

346

<select class="form-select d-inline w-auto" onchange="changePerPage(this.value)">

347

<option value="10" {{ 'selected' if posts.per_page == 10 }}>10</option>

348

<option value="25" {{ 'selected' if posts.per_page == 25 }}>25</option>

349

<option value="50" {{ 'selected' if posts.per_page == 50 }}>50</option>

350

</select>

351

</div>

352

353

{{ render_pagination(posts) }}

354

</div>

355

```

356

357

### Empty State Handling

358

359

```html

360

{% if posts.items %}

361

<!-- Display items -->

362

{% for post in posts.items %}

363

<!-- Post content -->

364

{% endfor %}

365

366

<!-- Show pagination only if there are multiple pages -->

367

{% if posts.pages > 1 %}

368

{{ render_pagination(posts) }}

369

{% endif %}

370

{% else %}

371

<div class="text-center py-5">

372

<h4>No posts found</h4>

373

<p class="text-muted">Try adjusting your search criteria.</p>

374

</div>

375

{% endif %}

376

```

377

378

## Configuration

379

380

Pagination respects Flask-SQLAlchemy pagination configuration:

381

382

```python

383

# Flask-SQLAlchemy configuration

384

app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

385

386

# Pagination defaults

387

DEFAULT_PER_PAGE = 20

388

MAX_PER_PAGE = 100

389

390

# In view functions

391

per_page = min(request.args.get('per_page', DEFAULT_PER_PAGE, type=int), MAX_PER_PAGE)

392

```