or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

appengine-integration.mdcore-admin.mdfile-admin.mdforms.mdgeoalchemy-integration.mdhelpers-utilities.mdindex.mdmodel-views.mdmongoengine-integration.mdredis-integration.mdsqlalchemy-integration.md

model-views.mddocs/

0

# Model Views and CRUD Operations

1

2

Base model view functionality for creating database-driven administrative interfaces with comprehensive CRUD operations, filtering, searching, and batch actions.

3

4

## Capabilities

5

6

### Base Model View

7

8

Foundation class for model-based admin views providing list, create, edit, and delete operations with extensive customization options.

9

10

```python { .api }

11

class BaseModelView(BaseView, ActionsMixin):

12

"""

13

Base class for model-based admin views.

14

"""

15

16

# List view configuration

17

list_columns = None # Columns to display in list view

18

column_exclude_list = None # Columns to exclude from list

19

column_auto_select_related = True # Auto-select related models

20

column_select_related_list = None # Explicitly select related models

21

column_display_pk = False # Display primary key column

22

column_hide_backrefs = True # Hide back-references

23

24

# Column formatting and display

25

column_formatters = {} # Custom column formatters

26

column_formatters_export = {} # Export-specific formatters

27

column_type_formatters = {} # Type-based formatters

28

column_labels = {} # Custom column labels

29

column_descriptions = {} # Column descriptions/tooltips

30

column_sortable_list = None # Sortable columns

31

column_default_sort = None # Default sort column and direction

32

33

# Filtering and searching

34

column_filters = None # Available filters

35

named_filter_urls = False # Use named filter URLs

36

column_searchable_list = None # Searchable columns

37

38

# List view behavior

39

page_size = 20 # Items per page

40

can_set_page_size = False # Allow user to change page size

41

42

# CRUD permissions

43

can_create = True # Allow creating new records

44

can_edit = True # Allow editing records

45

can_delete = True # Allow deleting records

46

can_view_details = False # Allow viewing record details

47

48

# Export functionality

49

can_export = False # Allow data export

50

export_max_rows = 0 # Maximum export rows (0 = unlimited)

51

export_types = ['csv'] # Supported export formats

52

53

# Form configuration

54

form_columns = None # Columns in create/edit forms

55

form_excluded_columns = None # Columns excluded from forms

56

form_include_pk = False # Include primary key in forms

57

form_overrides = {} # Custom field overrides

58

form_widget_args = {} # Widget arguments

59

form_extra_fields = {} # Additional form fields

60

61

# Form validation and processing

62

form_edit_rules = None # Edit form rules

63

form_create_rules = None # Create form rules

64

form_args = {} # Form field arguments

65

66

# Details view

67

details_modal = False # Show details in modal

68

details_modal_template = None # Details modal template

69

70

# Templates

71

list_template = 'admin/model/list.html'

72

edit_template = 'admin/model/edit.html'

73

create_template = 'admin/model/create.html'

74

details_template = 'admin/model/details.html'

75

76

def __init__(

77

self,

78

model=None,

79

name=None,

80

category=None,

81

endpoint=None,

82

url=None,

83

static_folder=None,

84

menu_class_name=None,

85

menu_icon_type=None,

86

menu_icon_value=None

87

):

88

"""

89

Initialize base model view.

90

91

Args:

92

model: Model class

93

name (str, optional): View name for menu

94

category (str, optional): Menu category

95

endpoint (str, optional): Blueprint endpoint

96

url (str, optional): URL prefix

97

static_folder (str, optional): Static files folder

98

menu_class_name (str, optional): Menu CSS class

99

menu_icon_type (str, optional): Icon type

100

menu_icon_value (str, optional): Icon identifier

101

"""

102

103

# Model operations (abstract methods to be implemented by ORM-specific views)

104

def get_pk_value(self, model):

105

"""

106

Get primary key value from model instance.

107

108

Args:

109

model: Model instance

110

111

Returns:

112

Primary key value

113

"""

114

115

def get_list(self, page, sort_column, sort_desc, search, filters, execute=True, page_size=None):

116

"""

117

Get model list with pagination, sorting, and filtering.

118

119

Args:

120

page (int): Page number (0-based)

121

sort_column (str): Sort column name

122

sort_desc (bool): Sort descending

123

search (str): Search query

124

filters (list): Active filters

125

execute (bool): Execute query immediately

126

page_size (int, optional): Items per page

127

128

Returns:

129

tuple: (count, data) or query object if execute=False

130

"""

131

132

def get_one(self, id):

133

"""

134

Get single model instance by ID.

135

136

Args:

137

id: Primary key value

138

139

Returns:

140

Model instance or None

141

"""

142

143

def create_model(self, form):

144

"""

145

Create new model instance from form data.

146

147

Args:

148

form: Form instance with data

149

150

Returns:

151

bool: True if successful

152

"""

153

154

def update_model(self, form, model):

155

"""

156

Update model instance from form data.

157

158

Args:

159

form: Form instance with data

160

model: Model instance to update

161

162

Returns:

163

bool: True if successful

164

"""

165

166

def delete_model(self, model):

167

"""

168

Delete model instance.

169

170

Args:

171

model: Model instance to delete

172

173

Returns:

174

bool: True if successful

175

"""

176

177

# Form methods

178

def scaffold_form(self):

179

"""

180

Create form class from model.

181

182

Returns:

183

Form class

184

"""

185

186

def scaffold_list_form(self, widget=None, validators=None):

187

"""

188

Create list form for inline editing.

189

190

Args:

191

widget: Form widget

192

validators: Field validators

193

194

Returns:

195

Form class

196

"""

197

198

def scaffold_filters(self, name):

199

"""

200

Create filters for column.

201

202

Args:

203

name (str): Column name

204

205

Returns:

206

list: Filter instances

207

"""

208

209

# View methods (exposed via @expose decorator)

210

def index_view(self):

211

"""

212

List view displaying paginated model data.

213

214

Returns:

215

str: Rendered template

216

"""

217

218

def create_view(self):

219

"""

220

Create new model instance view.

221

222

Returns:

223

str: Rendered template or redirect

224

"""

225

226

def edit_view(self):

227

"""

228

Edit existing model instance view.

229

230

Returns:

231

str: Rendered template or redirect

232

"""

233

234

def delete_view(self):

235

"""

236

Delete model instance view.

237

238

Returns:

239

Redirect response

240

"""

241

242

def details_view(self):

243

"""

244

View model instance details.

245

246

Returns:

247

str: Rendered template

248

"""

249

250

def export(self, export_type):

251

"""

252

Export model data.

253

254

Args:

255

export_type (str): Export format ('csv', etc.)

256

257

Returns:

258

Export response

259

"""

260

```

261

262

### View Arguments and Configuration

263

264

Configuration classes for managing list view state and filter groups.

265

266

```python { .api }

267

class ViewArgs:

268

def __init__(

269

self,

270

page=None,

271

page_size=None,

272

sort=None,

273

sort_desc=None,

274

search=None,

275

filters=None,

276

extra_args=None

277

):

278

"""

279

Initialize list view arguments.

280

281

Args:

282

page (int, optional): Page number

283

page_size (int, optional): Items per page

284

sort (str, optional): Sort column

285

sort_desc (bool, optional): Sort descending

286

search (str, optional): Search query

287

filters (list, optional): Active filters

288

extra_args (dict, optional): Additional arguments

289

"""

290

291

def clone(self, **kwargs):

292

"""

293

Clone arguments with modifications.

294

295

Args:

296

**kwargs: Arguments to override

297

298

Returns:

299

ViewArgs: Cloned instance

300

"""

301

302

class FilterGroup:

303

def __init__(self, label):

304

"""

305

Initialize filter group.

306

307

Args:

308

label (str): Group label

309

"""

310

311

def append(self, filter):

312

"""

313

Add filter to group.

314

315

Args:

316

filter: Filter instance

317

"""

318

319

def non_lazy(self):

320

"""

321

Get non-lazy filter representation.

322

323

Returns:

324

FilterGroup: Non-lazy group

325

"""

326

```

327

328

### Actions and Batch Operations

329

330

Batch action system for performing operations on multiple selected items.

331

332

```python { .api }

333

def action(name, text, confirmation=None):

334

"""

335

Decorator to expose batch actions on selected items.

336

337

Args:

338

name (str): Action identifier

339

text (str): Action display text

340

confirmation (str, optional): Confirmation message

341

342

Returns:

343

function: Decorated method

344

"""

345

346

class ActionsMixin:

347

"""

348

Mixin providing batch action functionality to views.

349

"""

350

351

def __init__(self):

352

"""

353

Initialize actions mixin.

354

"""

355

356

def init_actions(self):

357

"""

358

Scan and initialize action methods.

359

"""

360

361

def is_action_allowed(self, name):

362

"""

363

Check if action is permitted for current user.

364

365

Args:

366

name (str): Action name

367

368

Returns:

369

bool: True if allowed

370

"""

371

372

def get_actions_list(self):

373

"""

374

Get list of allowed actions for current user.

375

376

Returns:

377

list: Available actions

378

"""

379

380

def handle_action(self, return_view=None):

381

"""

382

Process action requests from list view.

383

384

Args:

385

return_view (str, optional): View to return to after action

386

387

Returns:

388

Response: Flask response

389

"""

390

```

391

392

## Usage Examples

393

394

### Custom Model View

395

396

```python

397

from flask_admin.contrib.sqla import ModelView

398

from flask_admin.actions import action

399

from flask import flash, redirect, url_for

400

401

class UserModelView(ModelView):

402

# List view configuration

403

list_columns = ['id', 'name', 'email', 'created_at', 'is_active']

404

column_searchable_list = ['name', 'email']

405

column_filters = ['is_active', 'created_at']

406

column_labels = {'is_active': 'Active Status'}

407

408

# Form configuration

409

form_columns = ['name', 'email', 'is_active', 'role']

410

form_widget_args = {

411

'email': {'placeholder': 'user@example.com'}

412

}

413

414

# Permissions

415

can_create = True

416

can_edit = True

417

can_delete = False

418

can_export = True

419

420

# Custom action

421

@action('activate', 'Activate Users', 'Are you sure you want to activate selected users?')

422

def action_activate(self, ids):

423

try:

424

query = User.query.filter(User.id.in_(ids))

425

count = query.update({User.is_active: True}, synchronize_session=False)

426

db.session.commit()

427

flash(f'Successfully activated {count} users.', 'success')

428

except Exception as ex:

429

flash(f'Failed to activate users: {str(ex)}', 'error')

430

431

# Override permissions

432

def is_accessible(self):

433

return current_user.is_authenticated and current_user.is_admin

434

435

def inaccessible_callback(self, name, **kwargs):

436

return redirect(url_for('security.login', next=request.url))

437

438

# Register with admin

439

admin.add_view(UserModelView(User, db.session, name='Users', category='Management'))

440

```

441

442

### Custom Column Formatters

443

444

```python

445

from markupsafe import Markup

446

447

class ProductModelView(ModelView):

448

column_formatters = {

449

'price': lambda v, c, m, p: f'${m.price:.2f}',

450

'image': lambda v, c, m, p: Markup(f'<img src="{m.image_url}" width="50">') if m.image_url else '',

451

'status': lambda v, c, m, p: Markup(f'<span class="label label-{m.status_color}">{m.status}</span>')

452

}

453

454

column_formatters_export = {

455

'price': lambda v, c, m, p: m.price, # Export raw price value

456

'image': lambda v, c, m, p: m.image_url or '' # Export URL only

457

}

458

```