Commit a260ad5f authored by Serge S. Koval's avatar Serge S. Koval

Updated documentation

parent 2845e4b2
......@@ -6,11 +6,11 @@ def action(name, text, confirmation=None):
Use this decorator to expose actions that span more than one
entity (model, file, etc)
`name`
:param name:
Action name
`text`
:param text:
Action text.
`confirmation`
:param confirmation:
Confirmation text. If not provided, action will be executed
unconditionally.
"""
......@@ -64,7 +64,7 @@ class ActionsMixin(object):
"""
Verify if action with `name` is allowed.
`name`
:param name:
Action name
"""
return True
......@@ -93,7 +93,7 @@ class ActionsMixin(object):
"""
Handle action request.
`return_view`
:param return_view:
Name of the view to return to after the request.
If not provided, will return user to the index view.
"""
......
......@@ -10,9 +10,9 @@ def expose(url='/', methods=('GET',)):
"""
Use this decorator to expose views in your view classes.
`url`
:param url:
Relative URL for the view
`methods`
:param methods:
Allowed HTTP methods. By default only GET is allowed.
"""
def wrap(f):
......@@ -84,16 +84,16 @@ class BaseView(object):
"""
Constructor.
`name`
:param name:
Name of this view. If not provided, will be defaulted to the class name.
`category`
:param category:
View category. If not provided, will be shown as a top-level menu item. Otherwise, will
be in a submenu.
`endpoint`
:param endpoint:
Base endpoint name for the view. For example, if there's view method called "index" and
endpoint was set to "myadmin", you can use `url_for('myadmin.index')` to get URL to the
view method. By default, equals to the class name in lower case.
`url`
:param url:
Base URL. If provided, affects how URLs are generated. For example, if url parameter
equals to "test", resulting URL will look like "/admin/test/". If not provided, will
use endpoint as a base url. However, if URL starts with '/', absolute path is assumed
......@@ -161,9 +161,9 @@ class BaseView(object):
"""
Render template
`template`
:param template:
Template path to render
`kwargs`
:param kwargs:
Template arguments
"""
# Store self as admin_view
......@@ -180,7 +180,7 @@ class BaseView(object):
"""
Prettify class name by splitting name by capital characters. So, 'MySuperClass' will look like 'My Super Class'
`name`
:param name:
String to prettify
"""
return sub(r'(?<=.)([A-Z])', r' \1', name)
......@@ -197,6 +197,17 @@ class BaseView(object):
return True
def _handle_view(self, name, **kwargs):
"""
This method will be executed before calling any view method.
By default, it will check if admin class is accessible and if it is not - will
throw HTTP 403 error.
:param name:
View function name
:param kwargs:
View function arguments
"""
if not self.is_accessible():
return abort(403)
......@@ -295,17 +306,17 @@ class Admin(object):
"""
Constructor.
`app`
:param app:
Flask application object
`name`
:param name:
Application name. Will be displayed in main menu and as a page title. If not provided, defaulted to "Admin"
`url`
:param url:
Base URL
`subdomain`
:param subdomain:
Subdomain to use
`index_view`
:param index_view:
Home page view to use. If not provided, will use `AdminIndexView`.
`translations_path`
:param translations_path:
Location of the translation message catalogs. By default will use translations
shipped with the Flask-Admin.
"""
......@@ -345,7 +356,7 @@ class Admin(object):
"""
Add view to the collection.
`view`
:param view:
View to add.
"""
# Add to views
......@@ -391,7 +402,7 @@ class Admin(object):
"""
Add view to the menu tree
`view`
:param view:
View to add
"""
if view.category:
......@@ -410,7 +421,7 @@ class Admin(object):
"""
Register all views with Flask application.
`app`
:param app:
Flask application instance
"""
if self.app is not None:
......
......@@ -61,9 +61,9 @@ class FileAdmin(BaseView, ActionsMixin):
Requires two parameters:
`path`
:param path:
Path to the directory which will be managed
`url`
:param url:
Base URL for the directory. Will be used to generate
static links to the files.
......@@ -137,19 +137,19 @@ class FileAdmin(BaseView, ActionsMixin):
"""
Constructor.
`base_path`
:param base_path:
Base file storage location
`base_url`
:param base_url:
Base URL for the files
`name`
:param name:
Name of this view. If not provided, will be defaulted to the class name.
`category`
:param category:
View category
`endpoint`
:param endpoint:
Endpoint name for the view
`url`
:param url:
URL for view
`verify_path`
:param verify_path:
Verify if path exists. If set to `True` and path does not exist
will throw exception.
"""
......@@ -177,7 +177,7 @@ class FileAdmin(BaseView, ActionsMixin):
Override to customize behavior.
`path`
:param path:
Relative path to the root
"""
return True
......@@ -202,7 +202,7 @@ class FileAdmin(BaseView, ActionsMixin):
Override to customize behavior.
`filename`
:param filename:
Source file name
"""
ext = op.splitext(filename)[1].lower()
......@@ -218,6 +218,11 @@ class FileAdmin(BaseView, ActionsMixin):
def is_in_folder(self, base_path, directory):
"""
Verify if `directory` is in `base_path` folder
:param base_path:
Base directory path
:param directory:
Directory path to check
"""
return op.normpath(directory).startswith(base_path)
......@@ -225,9 +230,9 @@ class FileAdmin(BaseView, ActionsMixin):
"""
Save uploaded file to the disk
`path`
:param path:
Path to save to
`file_data`
:param file_data:
Werkzeug `FileStorage` object
"""
file_data.save(path)
......@@ -236,11 +241,11 @@ class FileAdmin(BaseView, ActionsMixin):
"""
Return prettified URL
`endpoint`
:param endpoint:
Endpoint name
`path`
:param path:
Directory path
`kwargs`
:param kwargs:
Additional arguments
"""
if not path:
......@@ -257,7 +262,7 @@ class FileAdmin(BaseView, ActionsMixin):
"""
Return static file url
`path`
:param path:
Static file path
"""
base_url = self.get_base_url()
......@@ -300,7 +305,7 @@ class FileAdmin(BaseView, ActionsMixin):
"""
Index view method
`path`
:param path:
Optional directory path. If not provided, will use base directory
"""
# Get path and verify if it is valid
......@@ -350,7 +355,7 @@ class FileAdmin(BaseView, ActionsMixin):
"""
Upload view method
`path`
:param path:
Optional directory path. If not provided, will use base directory
"""
# Get path and verify if it is valid
......@@ -383,7 +388,7 @@ class FileAdmin(BaseView, ActionsMixin):
"""
Directory creation view method
`path`
:param path:
Optional directory path. If not provided, will use base directory
"""
# Get path and verify if it is valid
......
......@@ -11,13 +11,13 @@ class BasePeeweeFilter(filters.BaseFilter):
"""
Constructor.
`column`
:param column:
Model field
`name`
:param name:
Display name
`options`
:param options:
Fixed set of options
`data_type`
:param data_type:
Client data type
"""
super(BasePeeweeFilter, self).__init__(name, options, data_type)
......
......@@ -20,7 +20,6 @@ class InlineModelFormList(fields.FieldList):
self.model = model
self.prop = prop
# TODO: Fix me
self._pk = get_primary_key(model)
super(InlineModelFormList, self).__init__(InlineModelFormField(form, self._pk), **kwargs)
......
......@@ -181,9 +181,26 @@ class QuerySelectMultipleField(QuerySelectField):
class InlineModelFormList(FieldList):
"""
Customizied ``wtforms.fields.FieldList`` class which will work with SQLAlchemy
model instances.
"""
widget = InlineFormListWidget()
def __init__(self, form, session, model, prop, **kwargs):
"""
Default constructor.
:param form:
Form for the related model
:param session:
SQLAlchemy session
:param model:
Related model
:param prop:
Related property name
"""
self.form = form
self.session = session
self.model = model
......
......@@ -12,13 +12,13 @@ class BaseSQLAFilter(filters.BaseFilter):
"""
Constructor.
`column`
:param column:
Model field
`name`
:param name:
Display name
`options`
:param options:
Fixed set of options
`data_type`
:param data_type:
Client data type
"""
super(BaseSQLAFilter, self).__init__(name, options, data_type)
......
......@@ -239,6 +239,24 @@ def get_form(model, converter,
only=None, exclude=None,
field_args=None,
hidden_pk=False):
"""
Generate form from the model.
:param model:
Model to generate form from
:param converter:
Converter class to use
:param base_class:
Base form class
:param only:
Include fields
:param exclude:
Exclude fields
:param field_args:
Dictionary with additional field arguments
:param hidden_pk:
Generate hidden field with model primary key or not
"""
# TODO: Support new 0.8 API
if not hasattr(model, '_sa_class_manager'):
......@@ -263,6 +281,28 @@ def get_form(model, converter,
def contribute_inline(session, model, form_class, inline_models):
"""
Generate form fields for inline forms and contribute them to
the `form_class`
:param session:
SQLAlchemy session
:param model:
Model class
:param form_class:
Form to add properties to
:param inline_models:
List of inline model definitions. Can be one of:
- ``tuple``, first value is related model instance,
second is dictionary with options
- ``InlineFormAdmin`` instance
- Model class
:return:
Form class
"""
# Get mapper
mapper = model._sa_class_manager.mapper
......
......@@ -12,6 +12,9 @@ def parse_like_term(term):
def get_primary_key(model):
"""
Return primary key name from a model
:param model:
Model class
"""
props = model._sa_class_manager.mapper.iterate_properties
......
......@@ -137,17 +137,17 @@ class ModelView(BaseModelView):
"""
Constructor.
`model`
:param model:
Model class
`session`
:param session:
SQLALchemy session
`name`
:param name:
View name. If not set, will default to model name
`category`
:param category:
Category name
`endpoint`
:param endpoint:
Endpoint name. If not set, will default to model name
`url`
:param url:
Base URL. If not set, will default to '/admin/' + endpoint
"""
self.session = session
......@@ -295,12 +295,16 @@ class ModelView(BaseModelView):
"""
Verify if column type is text-based.
Returns `True` for `String`, `Unicode`, `Text`, `UnicodeText`
:returns:
``True`` for ``String``, ``Unicode``, ``Text``, ``UnicodeText``
"""
return (name == 'String' or name == 'Unicode' or
name == 'Text' or name == 'UnicodeText')
def scaffold_filters(self, name):
"""
Return list of enabled filters
"""
if isinstance(name, basestring):
attr = getattr(self.model, name, None)
else:
......@@ -363,7 +367,7 @@ class ModelView(BaseModelView):
Verify that provided filter object is derived from the
SQLAlchemy-compatible filter class.
`filter`
:param filter:
Filter object to verify.
"""
return isinstance(filter, filters.BaseSQLAFilter)
......@@ -409,17 +413,17 @@ class ModelView(BaseModelView):
"""
Return models from the database.
`page`
:param page:
Page number
`sort_column`
:param sort_column:
Sort column name
`sort_desc`
:param sort_desc:
Descending or ascending sort
`search`
:param search:
Search query
`execute`
:param execute:
Execute query immediately? Default is `True`
`filters`
:param filters:
List of filter tuples
"""
......@@ -515,8 +519,8 @@ class ModelView(BaseModelView):
"""
Return one model by its id.
`id`
Model
:param id:
Model id
"""
return self.session.query(self.model).get(id)
......@@ -525,7 +529,7 @@ class ModelView(BaseModelView):
"""
Create model from form.
`form`
:param form:
Form instance
"""
try:
......@@ -542,8 +546,10 @@ class ModelView(BaseModelView):
"""
Update model from form.
`form`
:param form:
Form instance
:param model:
Model instance
"""
try:
form.populate_obj(model)
......@@ -557,7 +563,7 @@ class ModelView(BaseModelView):
"""
Delete model.
`model`
:param model:
Model to delete
"""
try:
......
......@@ -45,13 +45,13 @@ class TimeField(fields.Field):
"""
Constructor
`label`
:param label:
Label
`validators`
:param validators:
Field validators
`formats`
:param formats:
Supported time formats, as a enumerable.
`kwargs`
:param kwargs:
Any additional parameters
"""
super(TimeField, self).__init__(label, validators, **kwargs)
......@@ -130,7 +130,16 @@ class DateTimePickerWidget(widgets.TextInput):
class RenderTemplateWidget(object):
"""
WTForms widget that renders Jinja2 template
"""
def __init__(self, template):
"""
Constructor
:param template:
Template path
"""
self.template = template
def __call__(self, field, **kwargs):
......
......@@ -222,17 +222,17 @@ class BaseModelView(BaseView, ActionsMixin):
"""
Constructor.
`model`
:param model:
Model class
`name`
:param name:
View name. If not provided, will use model class name
`category`
:param category:
View category
`endpoint`
:param endpoint:
Base endpoint. If not provided, will use model name + 'view'.
For example if model name was 'User', endpoint will be
'userview'
`url`
:param url:
Base URL. If not provided, will use endpoint as a URL.
"""
......@@ -318,7 +318,7 @@ class BaseModelView(BaseView, ActionsMixin):
"""
Return human-readable column name.
`field`
:param field:
Model field name.
"""
if self.rename_columns and field in self.rename_columns:
......@@ -381,7 +381,7 @@ class BaseModelView(BaseView, ActionsMixin):
"""
Generate filter object for the given name
`name`
:param name:
Name of the field
"""
return None
......@@ -393,7 +393,7 @@ class BaseModelView(BaseView, ActionsMixin):
Override in model backend implementation to verify if
provided filter type is allowed.
`filter`
:param filter:
Filter object to verify.
"""
return isinstance(filter, filters.BaseFilter)
......@@ -480,7 +480,7 @@ class BaseModelView(BaseView, ActionsMixin):
"""
Verify if column is sortable.
`name`
:param name:
Column name.
"""
return name in self._sortable_columns
......@@ -502,15 +502,15 @@ class BaseModelView(BaseView, ActionsMixin):
Must be implemented in child class.
`page`
:param page:
Page number, 0 based. Can be set to None if it is first page.
`sort_field`
:param sort_field:
Sort column name or None.
`sort_desc`
:param sort_desc:
If set to True, sorting is in descending order.
`search`
:param search:
Search query
`filters`
:param filters:
List of filter tuples. First value in a tuple is a search
index, second value is a search value.
"""
......@@ -522,7 +522,7 @@ class BaseModelView(BaseView, ActionsMixin):
Must be implemented in the child class.
`id`
:param id:
Model id
"""
raise NotImplemented('Please implement get_one method')
......@@ -536,7 +536,7 @@ class BaseModelView(BaseView, ActionsMixin):
Must be implemented in the child class.
`form`
:param form:
Form instance
"""
raise NotImplemented()
......@@ -549,9 +549,9 @@ class BaseModelView(BaseView, ActionsMixin):
Must be implemented in the child class.
`form`
:param form:
Form instance
`model`
:param model:
Model instance
"""
raise NotImplemented()
......@@ -564,7 +564,7 @@ class BaseModelView(BaseView, ActionsMixin):
Must be implemented in the child class.
`model`
:param model:
Model instance
"""
raise NotImplemented()
......@@ -576,7 +576,7 @@ class BaseModelView(BaseView, ActionsMixin):
For example, 'hello_world' will be converted to 'Hello World'
`name`
:param name:
Name to prettify
"""
return name.replace('_', ' ').title()
......@@ -627,17 +627,17 @@ class BaseModelView(BaseView, ActionsMixin):
Generate page URL with current page, sort column and
other parameters.
`view`
:param view:
View name
`page`
:param page:
Page number
`sort`
:param sort:
Sort column index
`sort_desc`
:param sort_desc:
Use descending sorting order
`search`
:param search:
Search query
`filters`
:param filters:
List of active filters
"""
if not search:
......@@ -669,10 +669,10 @@ class BaseModelView(BaseView, ActionsMixin):
"""
Returns value to be displayed in list view
`model`
Model instance
`name`
Field name
:param model:
Model instance
:param name:
Field name
"""
if name in self.list_formatters:
return self.list_formatters[name](model, name)
......
......@@ -2,6 +2,12 @@ from wtforms.fields import FormField
class InlineModelFormField(FormField):
"""
Customized ``FormField``.
Excludes model primary key from the `populate_obj` and
handles `should_delete` flag.
"""
def __init__(self, form, pk, **kwargs):
super(InlineModelFormField, self).__init__(form, **kwargs)
......
......@@ -9,11 +9,11 @@ class BaseFilter(object):
"""
Constructor.
`name`
:param name:
Displayed name
`options`
:param options:
List of fixed options. If provided, will use drop down instead of textbox.
`data_type`
:param data_type:
Client-side widget type to use.
"""
self.name = name
......@@ -26,7 +26,7 @@ class BaseFilter(object):
Override to customize behavior.
`view`
:param view:
Associated administrative view class.
"""
return self.options
......@@ -37,7 +37,7 @@ class BaseFilter(object):
If value is valid, returns `True` and `False` otherwise.
`value`
:param value:
Value to validate
"""
return True
......@@ -46,7 +46,7 @@ class BaseFilter(object):
"""
Parse value into python format.
`value`
:param value:
Value to parse
"""
return value
......@@ -55,7 +55,7 @@ class BaseFilter(object):
"""
Apply search criteria to the query and return new query.
`query`
:param query:
Query
"""
raise NotImplemented()
......
......@@ -6,9 +6,9 @@ def import_module(name, required=True):
"""
Import module by name
`name`
:param name:
Module name
`required`
:param required:
If set to `True` and module was not found - will throw exception.
If set to `False` and module was not found - will return None.
Default is `True`.
......@@ -26,7 +26,7 @@ def import_attribute(name):
"""
Import attribute using string reference.
`name`
:param name:
String reference.
Throws ImportError or AttributeError if module or attribute do not exist.
......@@ -47,7 +47,7 @@ def module_not_found(additional_depth=0):
Checks if ImportError was raised because module does not exist or
something inside it raised ImportError
`additional_depth`
:param additional_depth:
supply int of depth of your call if you're not doing
import on the same level of code - f.e., if you call function, which is
doing import, you should pass 1 for single additional level of depth
......@@ -62,9 +62,9 @@ def rec_getattr(obj, attr, default=None):
"""
Recursive getattr.
`attr`
:param attr:
Dot delimited attribute name
`default`
:param default:
Default value
Example::
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment