def __init__(self, listing, tablename=None): self.listing = listing self.config = get_table_config(self.listing.clazz, tablename) self.template = template_lookup.get_template("internal/dtlist.mako") # Template for JS datatable configuration self.js_template = template_lookup.get_template("internal/dtlist.js.mako")
def __init__(self, listing, tablename=None): self.listing = listing self.config = get_table_config(self.listing.clazz, tablename) self.template = template_lookup.get_template("internal/dtlist.mako") # Template for JS datatable configuration self.js_template = template_lookup.get_template( "internal/dtlist.js.mako")
def render(self): """Initialize renderer""" html = [] active = 'active' if self._active else 'inactive' config = self._field._config.renderer has_errors = len(self._field.get_errors()) has_warnings = len(self._field.get_warnings()) class_options = "form-group %s %s %s" % ((has_errors and 'has-error'), (has_warnings and 'has-warning'), (active)) html.append(HTML.tag("div", _closed=False, rules=u"{}".format(";".join(rules_to_string(self._field))), formgroup="{}".format(self._field.name), desired="{}".format(self._field.desired), required="{}".format(self._field.required), class_=class_options)) html.append(self._render_label()) # All items which can potentially be linked. However this list # of items may be already filtered be defining a default filter # in the overview configuration which is used for this renderer. items = self.itemlist.items selected_items = self._get_selected_items(items) if self._field.readonly or self.onlylinked == "true": items = selected_items # Filter options based on the configured filter expression of # the renderer. Please note the this method return a list of # tuples. item_tuples = self._field.filter_options(items) # Get filtered options and only use the items which are # in the origin items list and has passed filtering. item_tuples = self._field.filter_options(items) # Filter the items again based on the permissions. This means # resetting the third value in the tuple. if self.showall != "true" and not self._field.readonly: item_tuples = filter_options_on_permissions(self._field._form._request, item_tuples) values = {'items': item_tuples, 'selected_item_ids': [i.id for i in selected_items], 'field': self._field, 'clazz': self.get_class(), 'pclazz': self._field._form._item.__class__, 'request': self._field._form._request, '_': self._field._form._translate, 's': security, 'h': helpers, 'url_getter': get_link_url, 'tableconfig': get_table_config(self.itemlist.clazz, config.table)} html.append(literal(self.template.render(**values))) html.append(self._render_errors()) html.append(self._render_help()) html.append(HTML.tag("/div", _closed=False)) return literal("").join(html)
def handle_sorting(clazz, request): """Return a tuple of *fieldname* and *sortorder* (asc, desc). The sorting is determined in the follwoing order: First try to get the sorting from the current request (GET-Param). If there are no sorting params try to get the params saved in the session or if requested from a saved search. As last fallback use the default sorting for the table. """ name = clazz.__tablename__ # Default sorting options default_field = get_table_config(clazz).get_default_sort_column() default_order = get_table_config(clazz).get_default_sort_order() # Get sorting from the session. If there is no saved sorting use the # default value. field = request.session.get('%s.list.sort_field' % name, default_field) order = request.session.get('%s.list.sort_order' % name, default_order) # Get saved sorting from the the saved search. saved_search_id = request.params.get('saved') if saved_search_id: searches_dic = request.user.settings.get('searches', {}) if searches_dic: search = searches_dic.get(name) if search: field, order = search.get(saved_search_id, [[], [], None])[1] # Get sorting from the request. If there is no sorting option in # the request then use the saved sorting options. field = request.GET.get('sort_field', field) order = request.GET.get('sort_order', order) # Save current sorting in the session if 'reset' in request.params: request.session['%s.list.sort_field' % name] = default_field request.session['%s.list.sort_order' % name] = default_order else: request.session['%s.list.sort_field' % name] = field request.session['%s.list.sort_order' % name] = order request.session.save() return field, order
def get_list_renderer(listing, request): """Returns the renderer for an listing. Allow to use DTListRenderer if the renderer configuration is set.""" tableconfig = get_table_config(listing.clazz) settings = request.registry.settings default = settings.get("layout.advanced_overviews") == "true" if tableconfig.is_advancedsearch(default): return ListRenderer(listing) else: return DTListRenderer(listing)
def get_list_renderer(listing, request, table=None): """Returns the renderer for an listing. Allow to use DTListRenderer if the renderer configuration is set.""" tableconfig = get_table_config(listing.clazz, table) settings = request.registry.settings default = settings.get("layout.advanced_overviews") == "true" if tableconfig.is_advancedsearch(default): return ListRenderer(listing, table) else: return DTListRenderer(listing, table)
def itemlist(self): clazz = self.get_class() itemlist = get_item_list(self._field._form._request, clazz) config = get_table_config(itemlist.clazz, self._field._config.renderer.table) sort_field = config.get_default_sort_column() sort_order = config.get_default_sort_order() itemlist.sort(sort_field, sort_order) # Warning filtering items here can cause loosing relations to # the filtered items. This is esspecially true if the item which # was related to the item before now gets filtered because of a # changes value in an attribute e.g. In this case the filtered # item is not in the list at all and will not be sent on a POST # request. This will result in removing the relation! search = config.get_default_search() itemlist.filter(search) return itemlist
def render(self): """Initialize renderer""" html = [] active = 'active' if self._active else 'inactive' config = self._field._config.renderer has_errors = len(self._field.get_errors()) has_warnings = len(self._field.get_warnings()) class_options = "form-group %s %s %s" % ((has_errors and 'has-error'), (has_warnings and 'has-warning'),(active)) html.append(HTML.tag("div", _closed=False, rules=u"{}".format(";".join(self._field.rules_to_string)), formgroup="{}".format(self._field.name), desired="{}".format(self._field.desired), required="{}".format(self._field.required), class_=class_options)) html.append(self._render_label()) if self._field.is_readonly() or self.onlylinked == "true": items = self._get_selected_items(self.itemlist.items) else: items = self.itemlist.items # Get filtered options and only use the items which are # in the origin items list and has passed filtering. items = self._field.filter_options(items) # Now filter the items based on the user permissions if self.showall != "true": items = filter_options_on_permissions(self._field._form._request, items) values = {'items': items, 'field': self._field, 'clazz': self.get_class(), 'pclazz': self._field._form._item.__class__, 'request': self._field._form._request, '_': self._field._form._translate, 's': security, 'h': helpers, 'tableconfig': get_table_config(self.itemlist.clazz, config.table)} html.append(literal(self.template.render(**values))) html.append(self._render_errors()) html.append(self._render_help()) html.append(HTML.tag("/div", _closed=False)) return literal("").join(html)
def handle_paginating(clazz, request): """Returns a tupe of current page and pagesize. The default page and size is page on and all items on one page. This is also the default if pagination is not enabled for the table.""" name = clazz.__tablename__ # Default pagination options table_config = get_table_config(clazz) settings = request.registry.settings default = settings.get("layout.advanced_overviews") == "true" # Only set paginated if the table is the advancedsearch as the # simple search provides its own client sided pagination. if table_config.is_paginated() and table_config.is_advancedsearch(default): default_page = 0 # First page default_size = 50 else: return (0, None) # Get pagination from session page = request.session.get('%s.list.pagination_page' % name, default_page) size = request.session.get('%s.list.pagination_size' % name, default_size) # Overwrite options with options from get request page = int(request.GET.get('pagination_page', page)) size = request.GET.get('pagination_size', size) if size: size = int(size) else: size = None if 'reset' in request.params: request.session['%s.list.pagination_page' % name] = default_page request.session['%s.list.pagination_size' % name] = default_size else: request.session['%s.list.pagination_page' % name] = page request.session['%s.list.pagination_size' % name] = size request.session.save() return (page, size)
def itemlist(self): clazz = self.get_class() if self.showall == 'true': itemlist = get_item_list(self._field._form._request, clazz) else: itemlist = get_item_list(self._field._form._request, clazz, user=self._field._form._request.user) config = get_table_config(itemlist.clazz, self._field._config.renderer.table) sort_field = config.get_default_sort_column() sort_order = config.get_default_sort_order() itemlist.sort(sort_field, sort_order) # Warning filtering items here can cause loosing relations to # the filtered items. This is esspecially true if the item which # was related to the item before now gets filtered because of a # changes value in an attribute e.g. In this case the filtered # item is not in the list at all and will not be sent on a POST # request. This will result in removing the relation! search = config.get_default_search() itemlist.filter(search) return itemlist
def __init__(self, listing, tablename=None): self.listing = listing self.config = get_table_config(self.listing.clazz, tablename) self.template = template_lookup.get_template("internal/staticlist.mako")
def get_search(clazz, request): """Returns a list of tuples with the search word and the fieldname. The function will first look if there is already a saved search in the session for the overview of the given clazz. If there is no previous search the start with an empty search stack. The following behavior differs depending if it is a POST or GET request: 1. GET Return either an empty search stack or return the saved stack in the session. 2. POST Get the new submitted search. If the search is not already on the stack, then push it. If the search word is empty, then pop the last search from the stack. Finally return the modified stack. Please note the this function will not save the modified search stack in the session! This should be done elsewhere. E.g Depending if the search was successfull. """ name = clazz.__tablename__ # Default search fielter default_search = get_table_config(clazz).get_default_search() # Check if there is already a saved search in the session, If not # use the default search. saved_search = (request.session.get('%s.list.search' % name, []) or default_search) regexpr = request.session.get('%s.list.search.regexpr' % name, False) if "enableregexpr" in request.params: request.session['%s.list.search.regexpr' % name] = True return saved_search elif "disableregexpr" in request.params: request.session['%s.list.search.regexpr' % name] = False return saved_search if 'reset' in request.params: return default_search # If the request is not a equest from the search form then # abort here and return the saved search params if there are any. form_name = request.params.get('form') if form_name != "search": return saved_search saved_search_id = request.params.get('saved') if saved_search_id: searches_dic = request.user.settings.get('searches', {}) if searches_dic: searches_dic_search = searches_dic.get(name) if searches_dic_search: return searches_dic_search.get(saved_search_id, [[], [], None])[0] elif "save" in request.params: return saved_search elif "delete" in request.params: return saved_search else: search = request.params.get('search') search_field = request.params.get('field') # If search is empty try to pop the last filter in the saved search if search == "" and len(saved_search) > 0: popped = saved_search.pop() log.debug('Popping %s from search stack' % repr(popped)) # Iterate over the saved search. If the search is not already in the # stack push it. if search != "": found = False for x in saved_search: if search == x[0] and search_field == x[1]: found = True break if not found: log.debug('Adding search for "%s" in field "%s"' % (search, search_field)) saved_search.append((search, search_field, regexpr)) return saved_search
def filter(self, filter_stack): """This function will filter the items by only leaving those items in the list which match all search criteria in the filter stack. The number of items will get reduced with every iteration on the filter stack. The search is case sensitive. The filter stack is a list of tuples which describe the filter expression. Each tuple consists of three values: 1. The search expression 2. Optionally the name of the column on which the search will be applied. 3. Boolean flag to indicate that the given search expression should be handled as a regular expression. The search support three modes. On default the search will look for the presence of the given search string within the values of the item. It will also match on parts of the string. So searching for 'Foo' will also match 'Foobar'. Another mode is using the search expression as a regular expression. The last mode makes use of special operators. The search supports the following operators: "<", "<=", "!=", ">" ">=" and "~" The operator can be provided with the search string. It mus be the first word of the search expression. If a operator is present it will be used. The "~" operator will trigger a fuzzy search using the Double Metaphone algorithm for determining equal phonetics. If the phonetics do not match the Levenshtein distance will be calculated. The search will iterate over all items in the list. For each item the function will try to match the value of either all, or from the configured search field with the regular expression or configured operator. If the value matches, then the item is kept in the list. :filter_stack: Filter stack :returns: Filtered list of items """ self.search_filter = filter_stack log.debug('Length filterstack: %s' % len(filter_stack)) table_config = get_table_config(self.clazz) table_columns = {} # Save cols in the tableconfig for later access while getting values. for col in table_config.get_columns(): table_columns[col.get('name')] = col for search, search_field, regexpr in filter_stack: search_op = None # Get soperator x = search.split(" ") if x[0] in opmapping: search_op = x[0] search = " ".join(x[1:]) # Build a regular expression if regexpr: re_expr = re.compile(search, re.IGNORECASE) else: re_expr = re.compile(re.escape(search), re.IGNORECASE) filtered_items = [] log.debug('Filtering "%s" in "%s" with operator "%s" on %s items' % (search, search_field, search_op, len(self.items))) if search_field != "": fields = [search_field] else: fields = table_columns.keys() for item in self.items: for field in fields: expand = table_columns[field].get('expand') value = item.get_value(field, expand=expand) if isinstance(value, list): value = ", ".join([unicode(x) for x in value]) else: value = unicode(value) if search_op: if opmapping[search_op](value, search): filtered_items.append(item) break else: if re_expr.search(value): filtered_items.append(item) break self.items = filtered_items
def filter(self, filter_stack, request=None, table="overview"): """This function will filter the items by only leaving those items in the list which match all search criteria in the filter stack. The number of items will get reduced with every iteration on the filter stack. The search is case sensitive. The filter stack is a list of tuples which describe the filter expression. Each tuple consists of three values: 1. The search expression 2. Optionally the name of the column on which the search will be applied. 3. Boolean flag to indicate that the given search expression should be handled as a regular expression. The search support three modes. On default the search will look for the presence of the given search string within the values of the item. It will also match on parts of the string. So searching for 'Foo' will also match 'Foobar'. Another mode is using the search expression as a regular expression. The last mode makes use of special operators. The search supports the following operators: "<", "<=", "!=", ">" ">=" and "~" The operator can be provided with the search string. It mus be the first word of the search expression. If a operator is present it will be used. The "~" operator will trigger a fuzzy search using the Double Metaphone algorithm for determining equal phonetics. If the phonetics do not match the Levenshtein distance will be calculated. The search will iterate over all items in the list. For each item the function will try to match the value of either all, or from the configured search field with the regular expression or configured operator. If the value matches, then the item is kept in the list. :filter_stack: Filter stack :request: Current request. :table: Name of the table config which is used for the search defaults to "overview". :returns: Filtered list of items """ self.search_filter = filter_stack log.debug('Length filterstack: %s' % len(filter_stack)) table_config = get_table_config(self.clazz, table) table_columns = {} # Save cols in the tableconfig for later access while getting values. for col in [ col for col in table_config.get_columns() if col.get("searchable", True) ]: table_columns[col.get('name')] = col for search, search_field, regexpr in filter_stack: search_op = None # Get soperator x = search.split(" ") if x[0] in opmapping: search_op = x[0] search = " ".join(x[1:]) # Build a regular expression if regexpr: re_expr = re.compile(search, re.IGNORECASE) else: re_expr = re.compile(re.escape(search), re.IGNORECASE) filtered_items = [] log.debug('Filtering "%s" in "%s" with operator "%s" on %s items' % (search, search_field, search_op, len(self.items))) if search_field != "": fields = [search_field] else: fields = table_columns.keys() for item in self.items: for field in fields: expand = table_columns[field].get('expand') renderer = table_config.get_renderer(table_columns[field]) if renderer: value = renderer(request, item, field, table_config) else: value = item.get_value(field, expand=expand) if hasattr(value, 'render'): pretty_value = value.render(request) elif isinstance(value, list): if request and expand: value = ", ".join( [request.translate(unicode(v)) for v in value]) else: value = ", ".join([unicode(v) for v in value]) pretty_value = value else: pretty_value = unicode(prettify(request, value)) if request and expand: pretty_value = request.translate(pretty_value) if search_op: if request: value = request.translate(unicode(value)) else: value = unicode(value) if opmapping[search_op](value, search): filtered_items.append(item) break else: if re_expr.search(pretty_value): filtered_items.append(item) break self.items = filtered_items
def __init__(self, listing, tablename=None): """@todo: to be defined """ self.listing = listing self.config = get_table_config(self.listing.clazz, tablename) self.template = template_lookup.get_template("internal/list.mako")
def __init__(self, listing, tablename=None): self.listing = listing self.config = get_table_config(self.listing.clazz, tablename) self.template = template_lookup.get_template( "internal/staticlist.mako")
def __init__(self, listing): """@todo: to be defined """ self.listing = listing self.config = get_table_config(self.listing.clazz) self.template = template_lookup.get_template("internal/list.mako")
def get_search(clazz, request): """Returns a list of tuples with the search word and the fieldname. The function will first look if there is already a saved search in the session for the overview of the given clazz. If there is no previous search the start with an empty search stack. The following behavior differs depending if it is a POST or GET request: 1. GET Return either an empty search stack or return the saved stack in the session. 2. POST Get the new submitted search. If the search is not already on the stack, then push it. If the search word is empty, then pop the last search from the stack. Finally return the modified stack. Please note the this function will not save the modified search stack in the session! This should be done elsewhere. E.g Depending if the search was successfull. """ name = clazz.__tablename__ # Default search fielter default_search = get_table_config(clazz).get_default_search() # Check if there is already a saved search in the session, If not # use the default search. saved_search = (request.session.get('%s.list.search' % name, []) or default_search) regexpr = request.session.get('%s.list.search.regexpr' % name, False) if "enableregexpr" in request.params: request.session['%s.list.search.regexpr' % name] = True return saved_search elif "disableregexpr" in request.params: request.session['%s.list.search.regexpr' % name] = False return saved_search if 'reset' in request.params: saved_search = [] # If the request is not a equest from the search form then # abort here and return the saved search params if there are any. form_name = request.params.get('form') if form_name != "search": return saved_search saved_search_id = request.params.get('saved') if saved_search_id: searches_dic = request.user.settings.get('searches', {}) if searches_dic: searches_dic_search = searches_dic.get(name) if searches_dic_search: return searches_dic_search.get(saved_search_id, [[], [], None])[0] elif "save" in request.params: return saved_search elif "delete" in request.params: return saved_search else: search = request.params.get('search') search_field = request.params.get('field') # If search is empty try to pop the last filter in the saved search if search == "" and len(saved_search) > 0: popped = saved_search.pop() log.debug('Popping %s from search stack' % repr(popped)) # Iterate over the saved search. If the search is not already in the # stack push it. if search != "": found = False for x in saved_search: if search == x[0] and search_field == x[1]: found = True break if not found: log.debug('Adding search for "%s" in field "%s"' % (search, search_field)) if search: saved_search.append((search, search_field, regexpr)) return saved_search