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
```