bukuserver package
bukuserver.filters module
- class bukuserver.filters.BaseFilter(name: str, options: None | Sequence[tuple[str, str | flask_babel.LazyString]] | Callable[[], Sequence[tuple[str, str | flask_babel.LazyString]]] = None, data_type: Literal['daterangepicker', 'datetimepicker', 'datetimerangepicker', 'datepicker', 'select2-tags', 'timepicker', 'timerangepicker', 'uuid'] | str | None = None, key_name: str | None = None)[source]
Bases:
BaseFilter
- class bukuserver.filters.BookmarkBaseFilter(name, operation_text=None, apply_func=None, filter_type=None, options=None, data_type=None)[source]
Bases:
BaseFilter
- class bukuserver.filters.BookmarkBukuFilter(*args, **kwargs)[source]
Bases:
BaseFilter- KEYS = {'all_keywords': 'match all', 'deep': 'deep', 'markers': 'markers', 'regex': 'regex'}
- class bukuserver.filters.BookmarkField(*values)[source]
Bases:
Enum- DESCRIPTION = 4
- ID = 0
- TAGS = 3
- TITLE = 2
- URL = 1
- class bukuserver.filters.BookmarkOrderFilter(field, *args, **kwargs)[source]
Bases:
BaseFilter- DIR_LIST = [('asc', l'natural'), ('desc', l'reversed')]
- FIELDS = ['index', 'url', 'netloc', 'title', 'description', 'tags', '-#', '#']
- class bukuserver.filters.BookmarkTagNumberEqualFilter(*args, **kwargs)[source]
Bases:
BookmarkBaseFilter
- class bukuserver.filters.BookmarkTagNumberGreaterFilter(*args, **kwargs)[source]
Bases:
BookmarkTagNumberEqualFilter
- class bukuserver.filters.BookmarkTagNumberNotEqualFilter(*args, **kwargs)[source]
Bases:
BookmarkTagNumberEqualFilter
- class bukuserver.filters.BookmarkTagNumberSmallerFilter(*args, **kwargs)[source]
Bases:
BookmarkBaseFilter
- class bukuserver.filters.FilterType(*values)[source]
Bases:
Enum- BOTTOM_X = {'func': <function bottom_x_func>, 'text': l'bottom X'}
- CONTAINS = {'func': <function contains_func>, 'text': l'contains'}
- EQUAL = {'func': <function equal_func>, 'text': l'equals'}
- GREATER = {'func': <function greater_func>, 'text': l'greater than'}
- IN_LIST = {'func': <function in_list_func>, 'text': l'in list'}
- NOT_CONTAINS = {'func': <function not_contains_func>, 'text': l'not contains'}
- NOT_EQUAL = {'func': <function not_equal_func>, 'text': l'not equals'}
- NOT_IN_LIST = {'func': <function not_in_list_func>, 'text': l'not in list'}
- SMALLER = {'func': <function smaller_func>, 'text': l'smaller than'}
- TOP_X = {'func': <function top_x_func>, 'text': l'top X'}
- class bukuserver.filters.TagBaseFilter(name, operation_text=None, apply_func=None, filter_type=None, options=None, data_type=None)[source]
Bases:
BaseFilter
bukuserver.forms module
Forms module.
- class bukuserver.forms.ApiBookmarkCreateForm(*args, **kwargs)[source]
Bases:
ApiTagForm- property data_values
- description = <UnboundField(StringField, (), {})>
- fetch = <UnboundField(BooleanField, (), {'filters': [<function <lambda>>]})>
- property has_data
- tags = <UnboundField(ValueList, (), {'item_validators': [<function is_string>, <wtforms.validators.Regexp object>]})>
- title = <UnboundField(StringField, (), {})>
- url = <UnboundField(StringField, (), {'validators': [<wtforms.validators.DataRequired object>]})>
- class bukuserver.forms.ApiBookmarkEditForm(*args, **kwargs)[source]
Bases:
ApiBookmarkCreateForm- property has_data
- url = <UnboundField(StringField, (), {'validators': [<function optional_none>, <wtforms.validators.Length object>]})>
- class bukuserver.forms.ApiBookmarkRangeEditForm(*args, **kwargs)[source]
Bases:
ApiBookmarkEditForm- property data_values
- del_tags = <UnboundField(BooleanField, ('Delete tags list from existing tags',), {'default': False})>
- property tags_in
- class bukuserver.forms.ApiBookmarkSearchForm(*args, **kwargs)[source]
Bases:
Form- all_keywords = <UnboundField(BooleanField, (), {'filters': [<function <lambda>>]})>
- deep = <UnboundField(BooleanField, (), {'filters': [<function <lambda>>]})>
- keywords = <UnboundField(ValueList, (), {'validators': [<wtforms.validators.DataRequired object>], 'item_validators': [<function is_string>]})>
- markers = <UnboundField(BooleanField, (), {'filters': [<function <lambda>>]})>
- order = <UnboundField(ValueList, (), {'item_validators': [<function is_string>]})>
- regex = <UnboundField(BooleanField, (), {'filters': [<function <lambda>>]})>
- class bukuserver.forms.ApiBookmarksReorderForm(*args, **kwargs)[source]
Bases:
Form- order = <UnboundField(ValueList, (), {'validators': [<wtforms.validators.DataRequired object>], 'item_validators': [<function is_string>]})>
- class bukuserver.forms.ApiFetchDataForm(*args, **kwargs)[source]
Bases:
Form- url = <UnboundField(StringField, (), {'validators': [<wtforms.validators.DataRequired object>]})>
- class bukuserver.forms.ApiTagForm(*args, **kwargs)[source]
Bases:
Form- tags = <UnboundField(ValueList, (), {'validators': [<wtforms.validators.DataRequired object>], 'item_validators': [<function is_string>, <wtforms.validators.Regexp object>]})>
- property tags_str
- class bukuserver.forms.BookmarkForm(*args, **kwargs)[source]
Bases:
FlaskForm- description = <UnboundField(TextAreaField, (l'Description',), {})>
- fetch = <UnboundField(HiddenField, (), {'filters': [<class 'bool'>]})>
- tags = <UnboundField(StringField, (l'Tags',), {})>
- title = <UnboundField(StringField, (l'Title',), {})>
- url = <UnboundField(URLField, (l'URL',), {'validators': [<wtforms.validators.InputRequired object>]})>
- class bukuserver.forms.HomeForm(*args, **kwargs)[source]
Bases:
SearchBookmarksForm- keyword = <UnboundField(StringField, (l'Keyword',), {})>
- class bukuserver.forms.SearchBookmarksForm(*args, **kwargs)[source]
Bases:
FlaskForm- all_keywords = <UnboundField(BooleanField, (l'Match all keywords',), {'default': True, 'description': l'Exclude partial matches (with multiple keywords)'})>
- deep = <UnboundField(BooleanField, (l'Deep search',), {'description': l'When unset, only FULL words will be matched.'})>
- keywords = <UnboundField(FieldList, (<UnboundField(StringField, (l'Keywords',), {})>,), {'min_entries': 1})>
- markers = <UnboundField(BooleanField, (l'With markers',), {'default': True, 'description': l'The search string will be split into multiple keywords, each will be applied to a field based on prefix: - keywords starting with '.', '>' or ':' will be searched for in title, description and URL respectively - '#' will be searched for in tags (comma-separated, partial matches; not affected by Deep Search) - '#,' is the same but will match FULL tags only - '*' will be searched for in all fields (this prefix can be omitted in the 1st keyword) Keywords need to be separated by placing spaces before the prefix.'})>
- regex = <UnboundField(BooleanField, (l'Regex',), {'description': l'The keyword(s) are regular expressions (overrides other options).'})>
- class bukuserver.forms.SwapForm(*args, **kwargs)[source]
Bases:
FlaskForm- id1 = <UnboundField(HiddenField, (), {'filters': [<class 'int'>]})>
- id2 = <UnboundField(HiddenField, (), {'filters': [<class 'int'>]})>
- class bukuserver.forms.ValueList(*args, **kwargs)[source]
Bases:
SelectMultipleFieldA form field model for simple value lists, capable of processing regular array data.
bukuserver.response module
- class bukuserver.response.Response(*values)[source]
Bases:
Enum- BOOKMARK_NOT_FOUND = (HTTPStatus.NOT_FOUND, 'Bookmark not found.')
- FAILURE = (HTTPStatus.CONFLICT, 'Failure.')
- INPUT_NOT_VALID = (HTTPStatus.UNPROCESSABLE_ENTITY, 'Input data not valid.')
- INVALID_REQUEST = (HTTPStatus.BAD_REQUEST, 'Ill-formed request.')
- RANGE_NOT_VALID = (HTTPStatus.NOT_FOUND, 'Range not valid.')
- REMOVED = (HTTPStatus.GONE, 'Functionality no longer available.')
- SUCCESS = (HTTPStatus.OK, 'Success.')
- TAG_NOT_FOUND = (HTTPStatus.NOT_FOUND, 'Tag not found.')
- TAG_NOT_VALID = (HTTPStatus.UNPROCESSABLE_ENTITY, 'Invalid tag.')
- static from_flag(flag: bool, *, data: Dict[str, Any] = None, errors: Dict[str, Any] = None)[source]
- property message: str
- property status: int
- property status_code: int
bukuserver.server module
Server module.
bukuserver.views module
views module.
- class bukuserver.views.BookmarkModelView(bukudb: BukuDb, *args, **kwargs)[source]
Bases:
BaseModelView,ApplyFiltersMixin- action_view() Response | Response
Mass-model action view.
- ajax_lookup() Response | Response
- ajax_update() None | tuple[str, int] | str
Edits a single column of a record in list view. Usually used with column_editable_list that integrates with the x-editable library.
// you can use jQuery to make ajax calls like this: $.ajax({ url: '/admin/<your_model_view_endpoint>/ajax/update/', type: 'POST', data: { "list_form_pk" : "<primary_key_value>", "<column_name>": "<new_value>" }, success: function(response) { // handle success }, error: function(response) { // handle error } });
- can_set_page_size = True
Allows to select page size via dropdown list
- can_view_details = True
Setting this to true will enable the details view. This is recommended when there are too many columns to display in the list_view.
- column_filters = ['buku', 'id', 'url', 'title', 'tags', 'order']
Collection of the column filters.
Can contain either field names or instances of
BaseFilterclasses.Field names may be plain column names or dotted paths that walk across relationships, e.g.
"author.email".For SQLAlchemy views the same dotted-path syntax can be passed as the
columnargument when constructing a filter instance, in which case it is resolved against the view’s model and any joins required to reach the target column are added automatically.Example:
class MyModelView(BaseModelView): column_filters = ( 'user', 'email', 'author.email', # walks a relationship FilterEqual(column='author.email', name='Author Email'), )
- column_formatters = {'entry': <function BookmarkModelView._list_entry>}
Dictionary of list view column formatters.
For example, if you want to show price multiplied by two, you can do something like this:
class MyModelView(BaseModelView): column_formatters = dict(price=lambda v, c, m, p: m.price*2)
or using Jinja2 macro in template:
from flask_admin.model.template import macro class MyModelView(BaseModelView): column_formatters = dict(price=macro('render_price')) # in template {% macro render_price(model, column) %} {{ model.price * 2 }} {% endmacro %}
The Callback function has the prototype:
def formatter(view, context, model, name): # `view` is current administrative view # `context` is instance of jinja2.runtime.Context # `model` is model instance # `name` is property name pass
- column_labels = {'description': l'Description', 'entry': l'Entry', 'id': l'Index', 'tags': l'Tags', 'title': l'Title', 'url': l'URL'}
Dictionary where key is column name and value is string to display.
For example:
class MyModelView(BaseModelView): column_labels = dict(name='Name', last_name='Last Name')
- column_list = ['entry']
Collection of the model field names for the list view. If set to None, will get them from the model.
For example:
class MyModelView(BaseModelView): column_list = ('name', 'last_name', 'email')
(Added in 1.4.0) SQLAlchemy model attributes can be used instead of strings:
class MyModelView(BaseModelView): column_list = ('name', User.last_name)
- When using SQLAlchemy models, you can reference related columns like this::
- class MyModelView(BaseModelView):
column_list = (‘<relationship>.<related column name>’,)
- create_form(obj=None)[source]
Instantiate model creation form and return it.
Override to implement custom behavior.
- create_modal = True
Setting this to true will display the create_view as a modal dialog.
- create_modal_template = 'bukuserver/bookmark_create_modal.html'
Default create modal template
- create_model(form)[source]
Create model from the form.
Returns the model instance if operation succeeded.
Must be implemented in the child class.
- Parameters:
form – Form instance
- create_template = 'bukuserver/bookmark_create.html'
Default create template
- create_view() Response | Response | str
Create model view
- delete_model(model)[source]
Delete model.
Returns True if operation succeeded.
Must be implemented in the child class.
- Parameters:
model – Model instance
- delete_view() Response | Response
Delete model view. Only POST method is allowed.
- details_modal = True
Setting this to true will display the details_view as a modal dialog.
- details_modal_template = 'bukuserver/bookmark_details_modal.html'
Default details modal view template
- details_template = 'bukuserver/bookmark_details.html'
Default details view template
- details_view() Response | Response | str
Details model view
- edit_modal = True
Setting this to true will display the edit_view as a modal dialog.
- edit_modal_template = 'bukuserver/bookmark_edit_modal.html'
Default edit modal template
- edit_template = 'bukuserver/bookmark_edit.html'
Default edit template
- edit_view() Response | Response | str
Edit model view
- export(export_type: str) Response | Response
- extra_css = ['/static/bukuserver/css/bookmark.css', '/static/bukuserver/css/modal.css', '/static/bukuserver/css/list.css']
Extra CSS files to include in the page
- extra_js = ['/static/bukuserver/js/last_page.js', '/static/bukuserver/js/filters_fix.js']
Extra JavaScript files to include in the page
- get_detail_value(context, model, name)[source]
Returns the value to be displayed in the detail view
- Parameters:
context –
jinja2.runtime.Contextmodel – Model instance
name – Field name
- get_list(page, sort_field, sort_desc, _, filters, page_size=None)[source]
Return a tuple of a count of results and a paginated and sorted list of models from the data source.
Must be implemented in the child class.
- Parameters:
page – Page number, 0 based. Can be set to None if it is first page.
sort_field – Sort column name or None.
sort_desc – If set to True, sorting is in descending order.
search – Search query
filters – List of filter tuples. First value in a tuple is a search index, second value is a search value.
page_size – Number of results. Defaults to ModelView’s page_size. Can be overriden to change the page_size limit. Removing the page_size limit requires setting page_size to 0 or False.
- get_one(id)[source]
Return one model by its id.
Must be implemented in the child class.
- Parameters:
id – Model id
- index_view() str
List view
- last_page()
Generic ‘/last_page’ endpoint handler; based on https://github.com/flask-admin/flask-admin/blob/v1.6.0/flask_admin/model/base.py#L1956-L1969
- list_template = 'bukuserver/bookmarks_list.html'
Default list view template
- named_filter_urls = True
Set to True to use human-readable names for filters in URL parameters.
False by default so as to be robust across translations.
Changing this parameter will break any existing URLs that have filters.
- property page_size
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4
- property page_size_options
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable’s items.
If the argument is a tuple, the return value is the same object.
- scaffold_filters(name)[source]
Generate filter object for the given name
- Parameters:
name – Name of the field
- scaffold_form()[source]
Create form.BaseForm inherited class from the model. Must be implemented in the child class.
- scaffold_list_columns()[source]
Return list of the model field names. Must be implemented in the child class.
Expected return format is list of strings of the field names. For example:
['name', 'first_name', 'last_name']
- scaffold_list_form(widget=None, validators=None)[source]
Create form for the index_view using only the columns from self.column_editable_list.
- Parameters:
widget – WTForms widget class. Defaults to XEditableWidget.
validators – form_args dict with only validators {‘name’: {‘validators’: [DataRequired()]}}
Must be implemented in the child class.
- scaffold_sortable_columns()[source]
Returns a dictionary of sortable columns.
from flask-admin docs: If your backend does not support sorting, return None or an empty dictionary.
- update_model(form: BookmarkForm, model: Namespace)[source]
Update model from the form.
Returns True if operation succeeded.
Must be implemented in the child class.
- Parameters:
form – Form instance
model – Model instance
- property url_render_mode
- class bukuserver.views.ColoredData(name, amount, color)
Bases:
tuple- amount
Alias for field number 1
- color
Alias for field number 2
- name
Alias for field number 0
- class bukuserver.views.CustomAdminIndexView(name: str | None = None, category: str | None = None, endpoint: str | None = None, url: str | None = None, template: str = 'admin/index.html', menu_class_name: str | None = None, menu_icon_type: str | None = None, menu_icon_value: str | None = None)[source]
Bases:
AdminIndexView
- class bukuserver.views.StatisticView(bukudb, *args, **kwargs)[source]
Bases:
BaseView- extra_css: list[str] = ['/static/bukuserver/css/modal.css']
Extra CSS files to include in the page
- class bukuserver.views.TagModelView(bukudb, *args, **kwargs)[source]
Bases:
BaseModelView,ApplyFiltersMixin- action_view() Response | Response
Mass-model action view.
- ajax_lookup() Response | Response
- ajax_update() None | tuple[str, int] | str
Edits a single column of a record in list view. Usually used with column_editable_list that integrates with the x-editable library.
// you can use jQuery to make ajax calls like this: $.ajax({ url: '/admin/<your_model_view_endpoint>/ajax/update/', type: 'POST', data: { "list_form_pk" : "<primary_key_value>", "<column_name>": "<new_value>" }, success: function(response) { // handle success }, error: function(response) { // handle error } });
- can_create = False
Is model creation allowed
- can_set_page_size = True
Allows to select page size via dropdown list
- column_filters = ['name', 'usage_count']
Collection of the column filters.
Can contain either field names or instances of
BaseFilterclasses.Field names may be plain column names or dotted paths that walk across relationships, e.g.
"author.email".For SQLAlchemy views the same dotted-path syntax can be passed as the
columnargument when constructing a filter instance, in which case it is resolved against the view’s model and any joins required to reach the target column are added automatically.Example:
class MyModelView(BaseModelView): column_filters = ( 'user', 'email', 'author.email', # walks a relationship FilterEqual(column='author.email', name='Author Email'), )
- column_formatters = {'name': <function TagModelView._name_formatter>}
Dictionary of list view column formatters.
For example, if you want to show price multiplied by two, you can do something like this:
class MyModelView(BaseModelView): column_formatters = dict(price=lambda v, c, m, p: m.price*2)
or using Jinja2 macro in template:
from flask_admin.model.template import macro class MyModelView(BaseModelView): column_formatters = dict(price=macro('render_price')) # in template {% macro render_price(model, column) %} {{ model.price * 2 }} {% endmacro %}
The Callback function has the prototype:
def formatter(view, context, model, name): # `view` is current administrative view # `context` is instance of jinja2.runtime.Context # `model` is model instance # `name` is property name pass
- column_labels = {'name': l'Name', 'usage_count': l'Usage Count'}
Dictionary where key is column name and value is string to display.
For example:
class MyModelView(BaseModelView): column_labels = dict(name='Name', last_name='Last Name')
- create_model(form)[source]
Create model from the form.
Returns the model instance if operation succeeded.
Must be implemented in the child class.
- Parameters:
form – Form instance
- create_view() Response | Response | str
Create model view
- delete_model(model)[source]
Delete model.
Returns True if operation succeeded.
Must be implemented in the child class.
- Parameters:
model – Model instance
- delete_view() Response | Response
Delete model view. Only POST method is allowed.
- details_view() Response | Response | str
Details model view
- edit_template = 'bukuserver/tag_edit.html'
Default edit template
- edit_view() Response | Response | str
Edit model view
- export(export_type: str) Response | Response
- extra_css = ['/static/bukuserver/css/list.css']
Extra CSS files to include in the page
- extra_js = ['/static/bukuserver/js/last_page.js', '/static/bukuserver/js/filters_fix.js']
Extra JavaScript files to include in the page
- get_list(page: int, sort_field: str, sort_desc: bool, search: Any | None, filters: List[Tuple[int, str, str]], page_size: int = None) Tuple[int, List[SimpleNamespace]][source]
Return a tuple of a count of results and a paginated and sorted list of models from the data source.
Must be implemented in the child class.
- Parameters:
page – Page number, 0 based. Can be set to None if it is first page.
sort_field – Sort column name or None.
sort_desc – If set to True, sorting is in descending order.
search – Search query
filters – List of filter tuples. First value in a tuple is a search index, second value is a search value.
page_size – Number of results. Defaults to ModelView’s page_size. Can be overriden to change the page_size limit. Removing the page_size limit requires setting page_size to 0 or False.
- get_one(id)[source]
Return one model by its id.
Must be implemented in the child class.
- Parameters:
id – Model id
- index_view() str
List view
- last_page()
Generic ‘/last_page’ endpoint handler; based on https://github.com/flask-admin/flask-admin/blob/v1.6.0/flask_admin/model/base.py#L1956-L1969
- list_template = 'bukuserver/tags_list.html'
Default list view template
- named_filter_urls = True
Set to True to use human-readable names for filters in URL parameters.
False by default so as to be robust across translations.
Changing this parameter will break any existing URLs that have filters.
- property page_size
int([x]) -> integer int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating-point numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4
- property page_size_options
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable’s items.
If the argument is a tuple, the return value is the same object.
- scaffold_filters(name)[source]
Generate filter object for the given name
- Parameters:
name – Name of the field
- scaffold_form()[source]
Create form.BaseForm inherited class from the model. Must be implemented in the child class.
- scaffold_list_columns()[source]
Return list of the model field names. Must be implemented in the child class.
Expected return format is list of strings of the field names. For example:
['name', 'first_name', 'last_name']
- scaffold_list_form(widget=None, validators=None)[source]
Create form for the index_view using only the columns from self.column_editable_list.
- Parameters:
widget – WTForms widget class. Defaults to XEditableWidget.
validators – form_args dict with only validators {‘name’: {‘validators’: [DataRequired()]}}
Must be implemented in the child class.
- bukuserver.views.last_page(self)[source]
Generic ‘/last_page’ endpoint handler; based on https://github.com/flask-admin/flask-admin/blob/v1.6.0/flask_admin/model/base.py#L1956-L1969