Simple and extensible admin interface framework for Flask
86
Quality
Pending
Does it follow best practices?
Impact
86%
1.30xAverage score across 10 eval scenarios
MongoDB document administration through MongoEngine ORM integration with embedded documents, NoSQL-specific features, and flexible document structures.
Main model view class for MongoEngine documents with CRUD operations, embedded document handling, and MongoDB-specific querying.
from flask_admin.contrib.mongoengine import ModelView
class ModelView(BaseModelView):
def __init__(self, model, name=None, category=None, endpoint=None, url=None, **kwargs):
"""
Initialize MongoEngine model view.
Args:
model: MongoEngine document class
name (str, optional): View name for menu
category (str, optional): Menu category
endpoint (str, optional): Blueprint endpoint
url (str, optional): URL prefix
**kwargs: Additional view configuration
"""
# MongoEngine-specific configuration
subdocuments = {} # Embedded document configuration
embedded_list_columns = [] # Columns for embedded lists
# MongoDB querying
def get_query(self):
"""
Get base QuerySet for list view.
Returns:
QuerySet: MongoEngine QuerySet object
"""
def get_list(self, page, sort_column, sort_desc, search, filters, execute=True, page_size=None):
"""
Get paginated document list with sorting, searching, and filtering.
Args:
page (int): Page number (0-based)
sort_column (str): Field to sort by
sort_desc (bool): Sort in descending order
search (str): Search query string
filters (list): Active filter list
execute (bool): Execute query immediately
page_size (int, optional): Items per page
Returns:
tuple: (total_count, items) if execute=True, queryset if execute=False
"""
def get_one(self, id):
"""
Get single document instance by ObjectId.
Args:
id (str): Document ObjectId as string
Returns:
Document instance or None if not found
"""
# CRUD operations for documents
def create_model(self, form):
"""
Create new document instance from form data.
Args:
form: Validated form instance
Returns:
bool: True if creation successful
"""
def update_model(self, form, model):
"""
Update existing document instance from form data.
Args:
form: Validated form instance
model: Document instance to update
Returns:
bool: True if update successful
"""
def delete_model(self, model):
"""
Delete document instance.
Args:
model: Document instance to delete
Returns:
bool: True if deletion successful
"""
# Form scaffolding for MongoEngine
def scaffold_form(self):
"""
Auto-generate form class from MongoEngine document.
Returns:
Form class with fields for document fields
"""
def scaffold_list_form(self, widget=None, validators=None):
"""
Generate form for inline list editing.
Args:
widget: Custom widget for fields
validators: Custom validators
Returns:
Form class for inline editing
"""
def scaffold_filters(self, name):
"""
Generate filters for document field.
Args:
name (str): Field name
Returns:
list: Available filter types for field
"""
# MongoDB-specific methods
def get_pk_value(self, model):
"""
Get primary key (ObjectId) from document instance.
Args:
model: Document instance
Returns:
str: ObjectId as string
"""
def apply_search(self, query, search):
"""
Apply text search filters to QuerySet.
Args:
query: Base QuerySet
search (str): Search string
Returns:
QuerySet: QuerySet with search filters applied
"""
def apply_filters(self, query, filters):
"""
Apply field filters to QuerySet.
Args:
query: Base QuerySet
filters (list): Active filters
Returns:
QuerySet: QuerySet with filters applied
"""
def apply_sorting(self, query, sort_field, sort_desc):
"""
Apply sorting to QuerySet.
Args:
query: Base QuerySet
sort_field (str): Field to sort by
sort_desc (bool): Sort descending
Returns:
QuerySet: Sorted QuerySet
"""Support for editing embedded documents within parent document forms.
class EmbeddedForm:
def __init__(
self,
form_base_class=None,
form_columns=None,
excluded_form_columns=None,
form_args=None,
form_widget_args=None,
form_overrides=None
):
"""
Initialize embedded document form configuration.
Args:
form_base_class: Base form class for embedded form
form_columns (list, optional): Fields to include in embedded form
excluded_form_columns (list, optional): Fields to exclude
form_args (dict, optional): Form field arguments
form_widget_args (dict, optional): Widget arguments
form_overrides (dict, optional): Field type overrides
"""from flask import Flask
from flask_mongoengine import MongoEngine
from flask_admin import Admin
from flask_admin.contrib.mongoengine import ModelView
from mongoengine import Document, EmbeddedDocument, fields
from datetime import datetime
app = Flask(__name__)
app.config['MONGODB_SETTINGS'] = {
'db': 'blog',
'host': 'localhost',
'port': 27017
}
app.config['SECRET_KEY'] = 'secret-key'
db = MongoEngine(app)
# Define documents
class User(Document):
username = fields.StringField(max_length=80, unique=True, required=True)
email = fields.EmailField(required=True)
created_at = fields.DateTimeField(default=datetime.utcnow)
is_active = fields.BooleanField(default=True)
profile = fields.EmbeddedDocumentField('UserProfile')
class UserProfile(EmbeddedDocument):
first_name = fields.StringField(max_length=50)
last_name = fields.StringField(max_length=50)
bio = fields.StringField(max_length=500)
avatar_url = fields.URLField()
class BlogPost(Document):
title = fields.StringField(max_length=200, required=True)
content = fields.StringField()
author = fields.ReferenceField(User, required=True)
tags = fields.ListField(fields.StringField(max_length=50))
created_at = fields.DateTimeField(default=datetime.utcnow)
published = fields.BooleanField(default=False)
meta = {
'indexes': ['title', 'author', 'created_at'],
'ordering': ['-created_at']
}
# Create admin views
class UserModelView(ModelView):
list_columns = ['username', 'email', 'profile.first_name', 'profile.last_name', 'created_at', 'is_active']
column_searchable_list = ['username', 'email', 'profile.first_name', 'profile.last_name']
column_filters = ['is_active', 'created_at']
form_subdocuments = {
'profile': {
'form_columns': ['first_name', 'last_name', 'bio', 'avatar_url']
}
}
class BlogPostModelView(ModelView):
list_columns = ['title', 'author.username', 'created_at', 'published']
column_searchable_list = ['title', 'content', 'author.username']
column_filters = ['author', 'published', 'created_at', 'tags']
form_columns = ['title', 'content', 'author', 'tags', 'published']
# Initialize admin
admin = Admin(app, name='Blog Admin')
admin.add_view(UserModelView(User, name='Users'))
admin.add_view(BlogPostModelView(BlogPost, name='Blog Posts'))from flask_admin.contrib.mongoengine import EmbeddedForm
class Address(EmbeddedDocument):
street = fields.StringField(max_length=200)
city = fields.StringField(max_length=100)
state = fields.StringField(max_length=50)
zip_code = fields.StringField(max_length=20)
country = fields.StringField(max_length=50, default='USA')
class ContactInfo(EmbeddedDocument):
phone = fields.StringField(max_length=20)
fax = fields.StringField(max_length=20)
website = fields.URLField()
class Company(Document):
name = fields.StringField(max_length=200, required=True)
address = fields.EmbeddedDocumentField(Address)
contact = fields.EmbeddedDocumentField(ContactInfo)
employees = fields.ListField(fields.ReferenceField(User))
founded = fields.DateTimeField()
class CompanyModelView(ModelView):
# Configure embedded document forms
form_subdocuments = {
'address': {
'form_columns': ['street', 'city', 'state', 'zip_code', 'country'],
'form_args': {
'country': {'default': 'USA'}
}
},
'contact': {
'form_columns': ['phone', 'website'], # Exclude fax
'form_widget_args': {
'phone': {'placeholder': '+1-555-123-4567'},
'website': {'placeholder': 'https://example.com'}
}
}
}
# Display embedded fields in list
list_columns = ['name', 'address.city', 'address.state', 'contact.phone', 'founded']
column_labels = {
'address.city': 'City',
'address.state': 'State',
'contact.phone': 'Phone'
}
admin.add_view(CompanyModelView(Company, name='Companies'))from mongoengine import Q
from flask_admin.contrib.mongoengine.filters import FilterEqual, FilterLike, FilterInList
class AdvancedBlogPostView(ModelView):
# Text search across multiple fields
column_searchable_list = ['title', 'content', 'tags']
# MongoDB-specific filters
column_filters = [
'author',
'published',
'created_at',
FilterLike('title', 'Title Contains'),
FilterEqual('author', 'Exact Author'),
FilterInList('tags', 'Has Tags', options=[
('python', 'Python'),
('flask', 'Flask'),
('mongodb', 'MongoDB')
])
]
# Custom query with MongoDB aggregation
def get_query(self):
# Add complex filters using MongoEngine Q objects
return BlogPost.objects.filter(
Q(published=True) | Q(author=current_user.id)
)
# Custom search with regex
def apply_search(self, query, search):
if search:
# MongoDB regex search (case-insensitive)
search_filter = (
Q(title__icontains=search) |
Q(content__icontains=search) |
Q(tags__in=[search])
)
query = query.filter(search_filter)
return query
# Custom column formatter for tags
def _tags_formatter(view, context, model, name):
if model.tags:
return ', '.join(model.tags[:3]) # Show first 3 tags
return ''
column_formatters = {
'tags': _tags_formatter
}class Product(EmbeddedDocument):
name = fields.StringField(required=True)
price = fields.DecimalField(min_value=0)
sku = fields.StringField()
class Order(Document):
order_number = fields.StringField(unique=True, required=True)
customer_email = fields.EmailField(required=True)
products = fields.ListField(fields.EmbeddedDocumentField(Product))
shipping_address = fields.EmbeddedDocumentField(Address)
order_date = fields.DateTimeField(default=datetime.utcnow)
status = fields.StringField(
choices=['pending', 'processing', 'shipped', 'delivered'],
default='pending'
)
class OrderModelView(ModelView):
# Configure embedded list editing
form_subdocuments = {
'products': {
'form_columns': ['name', 'price', 'sku'],
'form_widget_args': {
'price': {'step': '0.01', 'min': '0'}
}
},
'shipping_address': {
'form_columns': ['street', 'city', 'state', 'zip_code']
}
}
list_columns = [
'order_number',
'customer_email',
'products_count',
'order_date',
'status'
]
# Custom formatter for product count
def _products_count_formatter(view, context, model, name):
return len(model.products) if model.products else 0
column_formatters = {
'products_count': _products_count_formatter
}
column_labels = {
'products_count': 'Items'
}
# Custom form processing
def on_model_change(self, form, model, is_created):
# Generate order number for new orders
if is_created and not model.order_number:
import uuid
model.order_number = f'ORD-{uuid.uuid4().hex[:8].upper()}'from mongoengine import FileField
from werkzeug.utils import secure_filename
class Document(Document):
title = fields.StringField(required=True)
description = fields.StringField()
file = FileField()
uploaded_at = fields.DateTimeField(default=datetime.utcnow)
uploaded_by = fields.ReferenceField(User)
class DocumentModelView(ModelView):
form_columns = ['title', 'description', 'file']
list_columns = ['title', 'file.filename', 'uploaded_at', 'uploaded_by.username']
column_labels = {
'file.filename': 'Filename',
'uploaded_by.username': 'Uploaded By'
}
# Custom file formatter
def _file_formatter(view, context, model, name):
if model.file:
return Markup(f'<a href="/download/{model.id}">{model.file.filename}</a>')
return ''
column_formatters = {
'file': _file_formatter
}
def on_model_change(self, form, model, is_created):
# Set uploaded_by to current user
if is_created:
model.uploaded_by = current_user._get_current_object()from flask_admin.actions import action
from flask import flash
class UserModelView(ModelView):
@action('activate', 'Activate Users', 'Activate selected users?')
def action_activate(self, ids):
try:
# Bulk update using MongoEngine
count = User.objects(id__in=ids).update(set__is_active=True)
flash(f'Successfully activated {count} users.', 'success')
except Exception as ex:
flash(f'Failed to activate users: {str(ex)}', 'error')
@action('send_email', 'Send Welcome Email')
def action_send_email(self, ids):
try:
users = User.objects(id__in=ids)
for user in users:
# Send email logic here
send_welcome_email(user.email)
flash(f'Sent emails to {len(users)} users.', 'success')
except Exception as ex:
flash(f'Failed to send emails: {str(ex)}', 'error')Install with Tessl CLI
npx tessl i tessl/pypi-flask-admindocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10