def test_XML(self): # sanitization process self.assertEqual( XML('<h1>Hello<a data-hello="world">World</a></h1>').xml(), b'<h1>Hello<a data-hello="world">World</a></h1>') # with sanitize, data-attributes are not permitted self.assertEqual( XML('<h1>Hello<a data-hello="world">World</a></h1>', sanitize=True).xml(), b'<h1>HelloWorld</h1>') # stringify by default # FIXME PY3 # seams that __repr__ is no longer enough ##self.assertEqual(XML('1.3'), '1.3') self.assertEqual(XML(u'<div>è</div>').xml(), b'<div>\xc3\xa8</div>') # you can calc len on the class, that equals the xml() and the str() ##self.assertEqual(len(XML('1.3')), len('1.3')) self.assertEqual(len(XML('1.3').xml()), len('1.3')) ##self.assertEqual(len(str(XML('1.3'))), len('1.3')) # you can concatenate them to strings (check for __add__ and __radd__ methods) ##self.assertEqual(XML('a') + 'b', 'ab') ##self.assertEqual(XML('a') + XML('b'), 'ab') ##self.assertEqual('a' + XML('b'), 'ab') # you can compare them ##self.assertEqual(XML('a') == XML('a'), True) # beware that the comparison is made on the XML repr self.assertEqual( XML('<h1>Hello<a data-hello="world">World</a></h1>', sanitize=True), XML('<h1>HelloWorld</h1>')) # bug check for the sanitizer for closing no-close tags self.assertEqual( XML('<p>Test</p><br/><p>Test</p><br/>', sanitize=True), XML('<p>Test</p><br /><p>Test</p><br />')) # basic flatten test self.assertEqual(XML('<p>Test</p>').flatten(), '<p>Test</p>') self.assertEqual( XML('<p>Test</p>').flatten(render=lambda text, tag, attr: text), '<p>Test</p>')
def buttons(executes): ret = '' for execute in executes: if len(execute) == 2: ret += (' ' if ret else '') + \ str(A(current.T(execute[0]),_class='button',_href=URL(execute[1]))) if len(execute) == 3: ret += (' ' if ret else '') + \ str(A(current.T(execute[0]),_class='button', \ _onclick=XML('popupw(\'' +URL(execute[1])+'\',\''+\ execute[2]+'\',\'290\',\'280\',\'650\');'))) if len(execute) == 4: ret += (' ' if ret else '') + \ str(A(current.T(execute[0]),_class='button', \ _onclick=XML('popupw(\'' +URL(execute[1])+'\',\''+\ execute[2]+ '\',\''+execute[3]+\ '\',\'280\',\'650\');'))) if len(execute) == 5: ret += (' ' if ret else '') + \ str(A(current.T(execute[0]),_class='button', \ _onclick=XML('popupw(\'' +URL(execute[1])+'\',\''+\ execute[2]+ '\',\''+execute[3]+'\',\''+execute[4]+\ '\',\'650\');'))) if len(execute) == 6: ret += (' ' if ret else '') + \ str(A(current.T(execute[0]),_class='button', \ _onclick=XML('popupw(\'' +URL(execute[1])+'\',\''+\ execute[2]+'\',\''+execute[3]+'\',\''+execute[4]+\ '\',\''+execute[5]+'\');'))) return ret
def pyfpdf_from_html(html): request = current.request def image_map(path): if path.startswith('/%s/static/' % request.application): return os.path.join(request.folder, path.split('/', 2)[2]) return 'http%s://%s%s' % (request.is_https and 's' or '', request.env.http_host, path) class MyFPDF(FPDF, HTMLMixin): pass pdf = MyFPDF() pdf.add_page() html = sanitize( html, escape=False) # should have better list of allowed tags pdf.write_html(html, image_map=image_map) return XML(pdf.output(dest='S'))
def button(merchant_id="123456789012345", products=[ dict(name="shoes", quantity=1, price=23.5, currency='USD', description="running shoes black") ]): t = '<input name="item_%(key)s_%(k)s" type="hidden" value="%(value)s"/>\n' list_products = '' for k, product in enumerate(products): for key in ('name', 'description', 'quantity', 'price', 'currency'): list_products += t % dict(k=k + 1, key=key, value=product[key]) button = """<form action="https://checkout.google.com/api/checkout/v2/checkoutForm/Merchant/%(merchant_id)s" id="BB_BuyButtonForm" method="post" name="BB_BuyButtonForm" target="_top">\n%(list_products)s<input name="_charset_" type="hidden" value="utf-8"/>\n<input alt="" src="https://checkout.google.com/buttons/buy.gif?merchant_id=%(merchant_id)s&w=117&h=48&style=white&variant=text&loc=en_US" type="image"/>\n</form>""" % dict( merchant_id=merchant_id, list_products=list_products) return XML(button)
def WIKI(text, encoding="utf8", safe_mode='escape', html4tags=False, **attributes): if not text: test = '' if 'extras' in attributes: extras = attributes['extras'] del attributes['extras'] else: extras = None text = text.decode(encoding, 'replace') return XML(markdown(text,extras=extras, safe_mode=safe_mode, html4tags=html4tags)\ .encode(encoding,'xmlcharrefreplace'),**attributes)
def ajax_get_entity_store_location_options(): ''' returns store locations of the ENTITY given in parameters as HTML select options ''' mylogger.debug(message='request.vars:%s' % request.vars) _entity_id = request.vars['entity'] store_location_mapper = STORE_LOCATION_MAPPER() _store_locations = store_location_mapper.find(entity_id=_entity_id) mylogger.debug(message='_store_locations:%s' % _store_locations) # hum... not sure this is a very clean way to unblock the UI and set the style... _result = "<script>$('select#store_location_parent').css('border', '4px solid yellow');</script><option value=''></option>" if _store_locations is not None: for _store_location in _store_locations: # str(_store_location.full_path) if full_path is None (should never happen) to concatenate strings _result += "<option value='" + str( _store_location.id) + "'>" + str( _store_location.full_path) + "</option>" return XML(_result)
def apply_filter(self, message, symbols={}, filter=None, ftag=None): def get_tr(message, prefix, filter): s = self.get_t(message, prefix) return filter(s) if filter else self.filter(s) if filter: prefix = '@' + (ftag or 'userdef') + '\x01' else: prefix = '@' + self.ftag + '\x01' message = get_from_cache(self.cache, prefix + message, lambda: get_tr(message, prefix, filter)) if symbols or symbols == 0 or symbols == "": if isinstance(symbols, dict): symbols.update((key, xmlescape(value).translate(ttab_in)) for key, value in symbols.iteritems() if not isinstance(value, NUMBERS)) else: if not isinstance(symbols, tuple): symbols = (symbols, ) symbols = tuple( value if isinstance(value, NUMBERS) else xmlescape(value). translate(ttab_in) for value in symbols) message = self.params_substitution(message, symbols) return XML(message.translate(ttab_out))
def pyfpdf_from_html(html): request = current.request def image_map(path): if path.startswith('/%s/static/' % request.application): return os.path.join(request.folder, path.split('/', 2)[2]) return 'http%s://%s%s' % (request.is_https and 's' or '', request.env.http_host, path) class MyFPDF(FPDF, HTMLMixin): pass pdf = MyFPDF() pdf.add_page() # pyfpdf needs some attributes to render the table correctly: html = sanitize( html, allowed_attributes={ 'a': ['href', 'title'], 'img': ['src', 'alt'], 'blockquote': ['type'], 'td': ['align', 'bgcolor', 'colspan', 'height', 'width'], 'tr': ['bgcolor', 'height', 'width'], 'table': ['border', 'bgcolor', 'height', 'width'], }, escape=False) pdf.write_html(html, image_map=image_map) return XML(pdf.output(dest='S'))
def g(data): try: output = f(data) return XML(ouput) except (TypeError, ValueError), e: raise HTTP(405, '%s serialization error' % e)
def latex_from_html(html): markmin = TAG(html).element('body').flatten(markmin_serializer) return XML(markmin2latex(markmin))
def exportToReport(): if request.vars.database and request.vars.username: if request.vars.code in ("base64", "base64all"): if request.vars.password: password = base64.b64decode(request.vars.password) else: password = None validator = getLogin(base64.b64decode(request.vars.database), base64.b64decode(request.vars.username), password) else: if request.vars.password: password = request.vars.password else: password = None validator = getLogin(request.vars.database, request.vars.username, password) if validator["valid"] == False: return validator["message"] else: return T('Missing login parameter(s)!') params = {} filters = {} if request.vars.reportcode: if request.vars.code in ("base64", "base64all"): params["reportcode"] = base64.b64decode(request.vars.reportcode) else: params["reportcode"] = request.vars.reportcode elif request.vars.report_id: if request.vars.code in ("base64", "base64all"): params["report_id"] = base64.b64decode(request.vars.report_id) else: params["report_id"] = request.vars.report_id else: return T('Missing reportcode or report_id parameter!') if request.vars.filters: if request.vars.code in ("base64", "base64all"): filters = getParamList(base64.b64decode(request.vars.filters))[0] else: filters = getParamList(request.vars.filters)[0] else: return T('Missing filters parameter!') if request.vars.output: if request.vars.code in ("base64", "base64all"): params["output"] = base64.b64decode(request.vars.output) else: params["output"] = request.vars.output else: params["output"] = "html" if request.vars.orientation: if request.vars.code in ("base64", "base64all"): params["orientation"] = base64.b64decode(request.vars.orientation) else: params["orientation"] = request.vars.orientation else: params["orientation"] = "P" if request.vars.size: if request.vars.code in ("base64", "base64all"): params["size"] = base64.b64decode(request.vars.size) else: params["size"] = request.vars.size else: params["size"] = "A4" if params["output"] == "printer": if not request.vars.printername: return T('Missing printername parameter!') printer_prop = dbout.check_printer(request.vars.printername) if printer_prop["state"] == False: return printer_prop["error_message"] params["output"] = "pdf" if request.vars.copies: try: copies = int(request.vars.copies) except: copies = 1 else: copies = 1 else: printer_prop = None report_tmp = dbout.getReport(params, filters) if type(report_tmp).__name__ == "str": if report_tmp == "NODATA": return HTML( HEAD( TITLE("Nervatura Report"), LINK(_rel="shortcut icon", _href=URL('static', 'favicon.ico'), _type="image/x-icon")), BODY( DIV(CENTER( TABLE(TR( TD(IMG( _src=URL('static', 'images/nodata.png'), _style="border: solid;border-color: #FFFFFF;"), _style= "text-align: center;vertical-align: middle;font-weight: bold;font-family: sans-serif;font-size: 20px;" )), _style= "background-color:#FFFFFF;color:#444444;margin-top:200px;" )), _style="width:100%;height:100%")), _style="background-color:#000000;") else: return report_tmp if printer_prop: print_item = dbout.printReport(printer_prop, report_tmp["template"], "Nervatura Report", copies, params["orientation"], params["size"]) if print_item["state"] == False: return print_item["error_message"] return "OK" elif report_tmp["filetype"] == "ntr": if params["output"] == "xml": response.headers['Content-Type'] = 'text/xml' elif params["output"] == "pdf": response.headers['Content-Type'] = 'application/pdf' if request.vars.code == "base64all": return base64.b64encode(report_tmp["template"]) else: return report_tmp["template"] elif report_tmp["filetype"] == "xls": response.headers['Content-Type'] = "application/vnd.ms-excel" response.headers[ 'Content-Disposition'] = 'attachment;filename="NervaturaReport.xls"' if request.vars.code == "base64all": return base64.b64encode(report_tmp["template"]) else: return report_tmp["template"] elif report_tmp["filetype"] == "html": response.view = "default/report.html" response.title = report_tmp["data"]["title"] response.subtitle = "" import StringIO report_tmp["template"] = response.render( StringIO.StringIO(report_tmp["template"]), report_tmp["data"]) return dict(template=XML(report_tmp["template"])) else: if request.vars.code == "base64all": return base64.b64encode(report_tmp["template"]) else: return report_tmp["template"]
def LOAD(c=None, f='index', args=None, vars=None, extension=None, target=None, ajax=False, ajax_trap=False, url=None, user_signature=False, timeout=None, times=1, content='loading...', post_vars=Storage(), **attr): """ LOADs a component into the action's document Args: c(str): controller f(str): function args(tuple or list): arguments vars(dict): vars extension(str): extension target(str): id of the target ajax(bool): True to enable AJAX bahaviour ajax_trap(bool): True if `ajax` is set to `True`, traps both links and forms "inside" the target url(str): overrides `c`,`f`,`args` and `vars` user_signature(bool): adds hmac signature to all links with a key that is different for every user timeout(int): in milliseconds, specifies the time to wait before starting the request or the frequency if times is greater than 1 or "infinity" times(integer or str): how many times the component will be requested "infinity" or "continuous" are accepted to reload indefinitely the component """ from gluon.html import TAG, DIV, URL, SCRIPT, XML if args is None: args = [] vars = Storage(vars or {}) target = target or 'c' + str(random.random())[2:] attr['_id'] = target request = current.request if '.' in f: f, extension = f.rsplit('.', 1) if url or ajax: url = url or URL(request.application, c, f, r=request, args=args, vars=vars, extension=extension, user_signature=user_signature) # timing options if isinstance(times, basestring): if times.upper() in ("INFINITY", "CONTINUOUS"): times = "Infinity" else: raise TypeError("Unsupported times argument %s" % times) elif isinstance(times, int): if times <= 0: raise ValueError( "Times argument must be greater than zero, 'Infinity' or None" ) else: raise TypeError("Unsupported times argument type %s" % type(times)) if timeout is not None: if not isinstance(timeout, integer_types): raise ValueError("Timeout argument must be an integer or None") elif timeout <= 0: raise ValueError( "Timeout argument must be greater than zero or None") statement = "$.web2py.component('%s','%s', %s, %s);" \ % (url, target, timeout, times) attr['_data-w2p_timeout'] = timeout attr['_data-w2p_times'] = times else: statement = "$.web2py.component('%s','%s');" % (url, target) attr['_data-w2p_remote'] = url if target is not None: return DIV(content, **attr) else: if not isinstance(args, (list, tuple)): args = [args] c = c or request.controller other_request = Storage(request) other_request['env'] = Storage(request.env) other_request.controller = c other_request.function = f other_request.extension = extension or request.extension other_request.args = List(args) other_request.vars = vars other_request.get_vars = vars other_request.post_vars = post_vars other_response = Response() other_request.env.path_info = '/' + \ '/'.join([request.application, c, f] + [str(a) for a in other_request.args]) other_request.env.query_string = \ vars and URL(vars=vars).split('?')[1] or '' other_request.env.http_web2py_component_location = \ request.env.path_info other_request.cid = target other_request.env.http_web2py_component_element = target other_request.restful = types.MethodType(request.restful.__func__, other_request) # A bit nasty but needed to use LOAD on action decorates with @request.restful() other_response.view = '%s/%s.%s' % (c, f, other_request.extension) other_environment = copy.copy(current.globalenv) # NASTY other_response._view_environment = other_environment other_response.generic_patterns = \ copy.copy(current.response.generic_patterns) other_environment['request'] = other_request other_environment['response'] = other_response ## some magic here because current are thread-locals original_request, current.request = current.request, other_request original_response, current.response = current.response, other_response page = run_controller_in(c, f, other_environment) if isinstance(page, dict): other_response._vars = page other_response._view_environment.update(page) page = run_view_in(other_response._view_environment) current.request, current.response = original_request, original_response js = None if ajax_trap: link = URL(request.application, c, f, r=request, args=args, vars=vars, extension=extension, user_signature=user_signature) js = "$.web2py.trap_form('%s','%s');" % (link, target) script = js and SCRIPT(js, _type="text/javascript") or '' return TAG[''](DIV(XML(page), **attr), script)
def Select(db, name=None, table=None, fields=[], prefix=None, \ todos='', lookups={}, masks=[], filtro='', \ distinct=False, orderby='', value=0, width='', \ submit=True): if not db or not name or not table or not fields: return '' if not filtro: rows = db(db[table]).select(orderby=fields[1] \ if not orderby else orderby) else: rows = db(filtro).select(orderby=fields[1] \ if not orderby else orderby) options = [[0, '-- Selecione --']] if todos: options.append([999999, todos]) for row in rows: if masks: if not masks[0]: expr0 = row[fields[0]] else: expr0 = eval("'(%s) %s' % (row['" + masks[0][0] + \ "'], row['" + masks[0][1] + "'])") if not masks[1]: expr1 = row[fields[1]] else: expr1 = eval("'(%s) %s' % (row['" + masks[1][0] + \ "'], row['" + masks[1][1] + "'])") else: expr0 = row[fields[0]] expr1 = row[fields[1]] if lookups: if lookups.has_key(fields[1]): expr1 = db(db[lookups[fields[1]][0]].id==expr1).\ select()[0][lookups[fields[1]][1]] options.append([expr0, expr1]) if submit: ret = "<select name='%s' id='%s_%s' %s onChange=\"%s\">" % \ (name, (prefix if prefix else table), name, 'style=\'width: %s\'' % width if width else '', \ XML("jQuery('#action').attr('value','submit');" + \ "jQuery(document.forms).each(function()" + \ "{this.submit();});")) else: ret = "<select name='%s' id='%s_%s' %s>" % \ (name, (prefix if prefix else table), name, \ 'style=\'width: %s\'' % width if width else '') antx = '' for option in options: if distinct: if option[1] <> antx: antx = option[1] if int(option[0]) == int(value): ret += "<option value='%s' selected='selected'>%s" % \ (option[0], option[1]) ret += "</option>" else: ret += "<option value='%s'>%s</option>" % \ (option[0], option[1]) else: if int(option[0]) == int(value): ret += "<option value='%s' selected='selected'>%s" % \ (option[0], option[1]) ret += "</option>" else: ret += "<option value='%s'>%s</option>" % \ (option[0], option[1]) ret += '</select>' return ret
def __call__(self): output = {} T = current.T request = current.request response = current.response s3 = response.s3 # Check logged in and permissions auth = current.auth settings = current.deployment_settings roles = current.session.s3.roles system_roles = auth.get_system_roles() AUTHENTICATED = system_roles.AUTHENTICATED # Login/Registration forms self_registration = current.deployment_settings.get_security_registration_visible() registered = False login_form = None login_div = None register_form = None register_div = None if AUTHENTICATED not in roles: #login_buttons = DIV(A(T("Login"), # _id = "show-login", # _class = "tiny secondary button", # ), # _id = "login-buttons" # ) script = ''' $('#show-mailform').click(function(e){ e.preventDefault() $('#intro').slideDown(400, function() { $('#login_box').hide() }); }) $('#show-login').click(function(e){ e.preventDefault() $('#login_form').show() $('#register_form').hide() $('#login_box').show() $('#intro').slideUp() })''' s3.jquery_ready.append(script) # This user isn't yet logged-in if "registered" in request.cookies: # This browser has logged-in before registered = True if self_registration is True: # Provide a Registration box on front page #login_buttons.append(A(T("Register"), # _id = "show-register", # _class = "tiny secondary button", # _style = "margin-left:5px", # )) #script = ''' #$('#show-register').click(function(e){ # e.preventDefault() # $('#login_form').hide() # $('#register_form').show() # $('#login_box').show() # $('#intro').slideUp() #})''' #s3.jquery_ready.append(script) register_form = auth.register() register_div = DIV(H3(T("Register")), P(XML(T("If you would like to help, then please <b>sign up now</b>")))) register_script = ''' $('#register-btn').click(function(e){ e.preventDefault() $('#register_form').show() $('#login_form').hide() }) $('#login-btn').click(function(e){ e.preventDefault() $('#register_form').hide() $('#login_form').show() })''' s3.jquery_ready.append(register_script) # Provide a login box on front page auth.messages.submit_button = T("Login") login_form = auth.login(inline=True) login_div = DIV(H3(T("Login")), P(XML(T("Registered users can <b>login</b> to access the system")))) #else: # login_buttons = "" #output["login_buttons"] = login_buttons output["self_registration"] = self_registration output["registered"] = registered output["login_div"] = login_div output["login_form"] = login_form output["register_div"] = register_div output["register_form"] = register_form # Slick slider if s3.debug: s3.scripts.append("/%s/static/scripts/slick.js" % request.application) else: s3.scripts.append("/%s/static/scripts/slick.min.js" % request.application) script = ''' $(document).ready(function(){ $('#title-image').slick({ autoplay:true, autoplaySpeed:5000, speed:1000, fade:true, cssEase:'linear' }); });''' s3.jquery_ready.append(script) s3.stylesheets.append("../themes/%s/homepage.css" % THEME) self._view(THEME, "index.html") return output
def __call__(self, field, value): mylogger.debug(message='current.request.vars:%s' % current.request.vars) mylogger.debug(message='field._tablename:%s' % (str(field._tablename))) mylogger.debug(message='field:%s' % (str(field))) mylogger.debug(message='field.name:%s' % (str(field.name))) mylogger.debug(message='field.type:%s' % (str(field.type))) mylogger.debug(message='field.requires:%s' % (str(field.requires))) mylogger.debug(message='type(value):%s' % (str(type(value)))) mylogger.debug(message='value:%s' % (str(value))) if current.request and current.request['function']: function = current.request['function'] function_configuration = self.configuration[ '*'] if self.configuration.keys().count( '*') > 0 else self.configuration[ function] if function in self.configuration.keys() else '' # query parameter not used yet... if 'query' in function_configuration: query = function_configuration['query'].as_json() else: query = None if 'disable_validate' in function_configuration: disable_validate = function_configuration['disable_validate'] else: disable_validate = False if 'add_in_db' in function_configuration: add_in_db = function_configuration['add_in_db'] else: add_in_db = False if 'multiple' in function_configuration: multiple = function_configuration['multiple'] else: multiple = False if 'submit_on_select' in function_configuration: submit_on_select = function_configuration['submit_on_select'] else: submit_on_select = False max_nb_item = 20 if 'max_nb_item' in function_configuration: max_nb_item = function_configuration['max_nb_item'] func_lambda = '' if 'func_lambda' in function_configuration: func_lambda = function_configuration['func_lambda'] # use this option for no required fields only, to force the user to confirm that the field is empty if 'confirm_empty' in function_configuration: confirm_empty = function_configuration['confirm_empty'] else: confirm_empty = current.request.vars[ 'confirm_empty_%s' % field. name] == 'on' if 'confirm_empty_%s' % field.name in current.request.vars else False is_not_a_reference = (field._tablename == self.ref_field._tablename) disabled = '_disabled' in self.attributes.keys() mylogger.debug(message='add_in_db:%s' % (str(add_in_db))) mylogger.debug(message='multiple:%s' % (str(multiple))) mylogger.debug(message='disabled:%s' % (str(disabled))) mylogger.debug(message='max_nb_item:%s' % (str(max_nb_item))) mylogger.debug(message='is_not_a_reference:%s' % (str(is_not_a_reference))) if (value) and (type(value) is StringType) and (value == '0'): nb_item = 0 elif (value) and (type(value) is StringType) and (value == '|0|'): nb_item = 0 elif (value) and (type(value) is ListType) and (value[0] == 0): nb_item = 0 elif (value) and (type(value) is ListType) and (value[0] == '|0|'): nb_item = 0 elif (value) and (type(value) is ListType): nb_item = len(value) elif value and value != '': nb_item = 1 else: nb_item = 0 if value and not type(value) is ListType and value != '': value = [value] mylogger.debug(message='nb_item:%s' % (str(nb_item))) # # basic widget structure # checkboxes_form = DIV() suggestions_form = DIV( _id='%s_suggestions' % (self.uid), _class='CHIMITHEQUE_MULTIPLE_widget_suggestions') message_form = DIV(_id='%s_message' % (self.uid), _class='CHIMITHEQUE_MULTIPLE_widget_message', _style='display: none;') search_input_form = DIV(INPUT(_name='%s_search' % self.uid, _type='text', _title='%s_search' % self.uid), suggestions_form, _id='%s_search' % (self.uid), _class='search_input_form') # # adding a confirm empty checkbox if needed # if confirm_empty: confirm_empty_form = DIV( INPUT(_name='confirm_empty_%s' % field.name, _id='confirm_empty_%s' % field.name, _type='checkbox', _title=self.text_confirm_empty_form_field, _class='CHIMITHEQUE_MULTIPLE_widget_confirm_empty', _onclick='''$('div[id=%(uid)s]').empty(); if ($('input[type=checkbox][name=confirm_empty_%(field_name)s]').is(':checked')) { $('div[id=%(uid)s]').append('<span id="%(field_name)s_span_no_selected"></span>'); } else { $('div[id=%(uid)s]').append('<span id="%(field_name)s_span_no_selected">%(no_item_selected)s</span>'); } ''' % { 'uid': self.uid, 'field_name': field.name, 'no_item_selected': self.text_no_item_selected })) confirm_empty_form.append( IMG(_src=self.image_disable_url, _alt='disable', _id='%s_disable' % self.uid, _title=self.text_confirm_empty_form_field)) else: confirm_empty_form = DIV() # # building the AJAX query parameters # _ajax_parameters = { 'uid': self.uid, 'multiple': multiple, 'disable_validate': disable_validate, 'add_in_db': add_in_db, 'field_tablename': field._tablename, 'ref_field_tablename': self.ref_field._tablename, 'ref_field_name': self.ref_field.name, 'max_nb_item': max_nb_item, 'max_item_length': self.max_item_length, 'lambda': func_lambda, 'query': query, 'text_close_list': str(self.text_close_list), 'text_submit': str(self.text_submit), 'image_select_url': self.image_select_url, 'submit_on_select': submit_on_select } ajax_parameters = json.dumps(_ajax_parameters) # # adding the "add" image # if not disabled and add_in_db: search_input_form.append( IMG(_src=self.image_insert_url, _alt='submit', _id='%s_add' % self.uid, _title=self.text_submit, _style='visibility: hidden;', _class='CHIMITHEQUE_MULTIPLE_widget_addindb', _onclick=''' // adding the search parameter to the JSON object ajax_parameters = %(ajax_parameters)s; ajax_parameters["search"] = $('input[name=%(uid)s_search]').val(); var ret = $.ajax({ type: "POST", url: "/%(application)s/chimitheque_multiple_widget/item_add", data: JSON.stringify(ajax_parameters), dataType: "json", contentType: "application/json; charset=utf-8", async: false }).done(function(data) { var _action = data['action']; var _id = data['id']; var _val = data['val']; var _encval = data['encval']; var funcCall = "addReplaceCheckBox%(uid)s" + "('" + _action + "','" + _id + "','" + _val + "','" + _encval + "')"; eval(funcCall); $('img#%(uid)s_add').attr('style', 'visibility: hidden;'); }); ''' % { 'uid': self.uid, 'application': current.request.application, 'ajax_parameters': ajax_parameters })) # # adding the selected items DIV # if nb_item == 0: if 'confirm_empty_%s' % field.name in current.request.vars: checkboxes_form.append(SPAN()) else: checkboxes_form.append( SPAN(XML(self.text_no_item_selected), _id='%s_span_no_selected' % field.name)) hidden_box_form = DIV( INPUT(_name='%s' % field.name, _id='%s_hidden' % field.name, _type='checkbox', _value='', _style='visibility: hidden; height: 0px;', _checked='checked', requires=field.requires)) else: hidden_box_form = DIV() # # prepopulating the form # for i in range(0, nb_item): mylogger.debug(message='i:%i' % (i)) prepop_value_id = None prepop_value_label = None if is_not_a_reference: # just populating with the value passed in parameter mylogger.debug(message='case 1') prepop_value_id = value[i] prepop_value_label = value[i] else: # the parameter value is an id in the reference table, then querying the table mylogger.debug(message='case 2') prepop_value = current.db( current.db['%s' % self.ref_field._tablename]['id'] == ( value[i])).select().first() if prepop_value is not None: prepop_value_label = current.db[ '%s' % self.ref_field._tablename]._format(prepop_value) prepop_value_id = value[i] mylogger.debug(message='prepop_value_id:%s' % prepop_value_id) mylogger.debug(message='prepop_value_label:%s' % prepop_value_label) if prepop_value_id: # # adding the checkboxes or radio for the selected items # if multiple: _input = INPUT( _name='%s' % field.name, _id='%s' % field.name, _type='checkbox', _class='CHIMITHEQUE_MULTIPLE_widget_selected', _encvalue=self.uid, _value=prepop_value_id, value=True, requires=field.requires) else: if is_not_a_reference: _input = INPUT( _name='%s' % field.name, _id='%s' % field.name, _type='radio', _class='CHIMITHEQUE_MULTIPLE_widget_selected', _encvalue=self.uid, _value= prepop_value_label, # or prepop_value_id, don't mind... value= prepop_value_label, # or prepop_value_id, don't mind... requires=field.requires) else: _input = INPUT( _name='%s' % field.name, _id='%s' % field.name, _type='radio', _class='CHIMITHEQUE_MULTIPLE_widget_selected', _encvalue=self.uid, _value=prepop_value_id, value=prepop_value_id, requires=field.requires) # # then the delete selected item image # if not disabled and not multiple: img_del = IMG(_src=self.image_delete_url, _alt=self.text_delete, _title=self.text_delete, _onclick='deleteItem%s();' % self.uid, _style='float: left;') else: img_del = SPAN() # # then the label # checkboxes_form.append( DIV(_input, img_del, XML('%s' % prepop_value_label), _class='CHIMITHEQUE_MULTIPLE_widget_selected')) else: # TODO: code identical to line 232... if 'confirm_empty_%s' % field.name in current.request.vars: checkboxes_form.append(SPAN()) else: checkboxes_form.append( SPAN(XML(self.text_no_item_selected), _id='%s_span_no_selected' % field.name)) hidden_box_form = DIV( INPUT(_name='%s' % field.name, _id='%s_hidden' % field.name, _type='checkbox', _value='', _style='visibility: hidden; height: 0px;', _checked='checked', requires=field.requires)) # # building the final form # final_form = DIV( DIV( DIV(checkboxes_form, _id='%s' % self.uid, _class='%s_%s' % (self.ref_field._tablename, self.ref_field.name)), **self.attributes)) if not disabled: final_form.insert(0, confirm_empty_form) final_form.insert(0, search_input_form) # hidden field to export the uid for the pages uid_field = INPUT(_name='uid_%s' % field.name, _type='hidden', value='%s' % self.uid, style='visibility: hidden; height: 0px;') return DIV(final_form, uid_field, hidden_box_form, message_form, SCRIPT( """ function disableAddButton%(uid)s() { $('#%(uid)s_add').attr('style', 'visibility: hidden;'); } function displayMessage%(uid)s(message) { $('#%(uid)s_message span').remove(); $('#%(uid)s_message').append('<span class="error">' + message + '</span>'); } function deleteItem%(uid)s() { $('#%(uid)s').find('div[class=CHIMITHEQUE_MULTIPLE_widget_selected]').remove(); console.log($('input[name=%(field_name)s]').length); /* enabling the hidden field if needed */ if ($('input[name=%(field_name)s]').length <= 1) { console.log("input name '%(field_name)s' was the last element"); $('input[id=%(field_name)s_hidden]').removeAttr('disabled'); $('div[id=%(uid)s]').append('<span id="%(field_name)s_span_no_selected">%(no_item_selected)s</span>'); } else { console.log("input name '%(field_name)s' was not the last element"); } } function addReplaceCheckBox%(uid)s(action, id, val, encval) { console.log(arguments.callee.name); console.log('action:' + action); console.log('id:' + id); console.log('val:' + val); console.log('encval:' + encval); /* base64 decoding the string */ val = Base64.decode(val); /* disabling the hidden field */ $('input[id=%(field_name)s_hidden]').attr('disabled','true'); $('span[id=%(field_name)s_span_no_selected]').remove(); if ($('#%(uid)s').find('input[value="'+id+'"][encvalue='+encval+']').length != 0) { alert('%(text_item_already_selected)s'); } else { var newDiv = $('<div class="CHIMITHEQUE_MULTIPLE_widget_selected"/>'); var newDel = $('<img/>').attr({ 'src': '%(image_delete_url)s', 'alt': '%(image_delete_alt)s', 'title': '%(image_delete_title)s', 'onclick': 'deleteItem%(uid)s();' }); var newElem = $('<input/>').attr({ 'id': '%(field_name)s', 'type': '%(type)s', 'checked': 'checked', 'name': '%(field_name)s', 'value': id, 'class': 'CHIMITHEQUE_MULTIPLE_widget_selected', 'encvalue': encval, }); if (action == 'replace') { newDiv.append(newDel); } newDiv.append(newElem); newDiv.append(val); if (action == 'replace') { $('#%(uid)s div').remove(); } $('#%(uid)s').append(newDiv); } $('input[name=%(uid)s_search]').val(''); $('#' + encval + '_suggestions div').remove(); } function autocomplete%(uid)s() { $elem = $('input[type=text][name=%(uid)s_search]') var inputLength = $elem.val().length; if (inputLength >= %(minchar)s) { // adding the search parameter to the JSON object ajax_parameters = %(ajax_parameters)s; ajax_parameters["search"] = $elem.val(); var ret = $.ajax({ type: "POST", url: "/%(application)s/chimitheque_multiple_widget/item_selector", data: JSON.stringify(ajax_parameters), dataType: "json", contentType: "application/json; charset=utf-8", async: false }).responseText; $('#%(uid)s_suggestions > *').remove(); $('#%(uid)s_message').show(); $('#%(uid)s_message').text(''); if (ret.substr(0, 5) == 'ERROR') { $('#%(uid)s_message').text(ret); $('#%(uid)s_add').attr('style', 'visibility: hidden;'); }else if (ret.substr(0, 4) == 'INDB'){ $('#%(uid)s_add').attr('style', 'visibility: hidden;'); $('#%(uid)s_suggestions').append(ret); }else if (ret.substr(0, 4) == 'NONE'){ $('#%(uid)s_add').attr('style', 'visibility: visible;'); } else { $('#%(uid)s_add').attr('style', 'visibility: visible;'); $('#%(uid)s_suggestions').append(ret); } } } $(document).ready(function() { jQuery('input[type=text][name=%(uid)s_search]').bind('paste', function(e) { setTimeout(function() { autocomplete%(uid)s(); }, 0); }); timer = 0; jQuery('input[type=text][name=%(uid)s_search]').bind('keypress click paste input',function() { if (timer) { clearTimeout(timer); } timer = setTimeout(autocomplete%(uid)s, 400); }); }); """ % { 'disable_validate': disable_validate, 'add_in_db': add_in_db, 'multiple': multiple, 'uid': self.uid, 'field_tablename': field._tablename, 'field_name': field.name, 'field_label': field.label, 'ref_field_tablename': self.ref_field._tablename, 'ref_field_name': self.ref_field.name, 'minchar': self.minchar, 'image_delete_url': self.image_delete_url, 'image_delete_alt': self.text_delete, 'image_delete_title': self.text_delete, 'type': 'checkbox' if multiple else 'radio', 'max_nb_item': max_nb_item, 'max_item_length': self.max_item_length, 'lambda': func_lambda, 'image_delete_small': self.image_delete_url, 'text_item_already_selected': self.text_item_already_selected, 'no_item_selected': self.text_no_item_selected, 'application': current.request.application, 'ajax_parameters': ajax_parameters }), _class='CHIMITHEQUE_MULTIPLE_widget')
def grid( query, fields=None, field_id=None, left=None, join=None, #! orderby=None, groupby=None, groupfields=None, #! having=None, #! headers={}, searchable=False, #True, sortable=True, paginate=20, pagename="page", #! deletable=False, #! True, editable=True, details=False, #! True, selectable=None, create=False, #!True, csv=False, #!True, links=None, links_in_grid=True, upload='<default>', args=[], user_signature=False, #!True, maxtextlengths={}, maxtextlength=20, onvalidation=None, oncreate=None, onupdate=None, ondelete=None, sorter_icons=(XML('↑'), XML('↓')), ui='web2py', showbuttontext=True, _class="web2py_grid", formname='web2py_grid', search_widget='default', ignore_rw=False, formstyle='table3cols', exportclasses=None, formargs={}, createargs={}, editargs={}, viewargs={}, ): # jQuery UI ThemeRoller classes (empty if ui is disabled) if ui == 'jquery-ui': ui = dict( widget='ui-widget', header='ui-widget-header', content='ui-widget-content', default='ui-state-default', cornerall='ui-corner-all', cornertop='ui-corner-top', cornerbottom='ui-corner-bottom', button='ui-button-text-icon-primary', buttontext='ui-button-text', buttonadd='ui-icon ui-icon-plusthick', buttonback='ui-icon ui-icon-arrowreturnthick-1-w', buttonexport='ui-icon ui-icon-transferthick-e-w', buttondelete='ui-icon ui-icon-trash', buttonedit='ui-icon ui-icon-pencil', buttontable='ui-icon ui-icon-triangle-1-e', buttonview='ui-icon ui-icon-zoomin', ) elif ui == 'web2py': ui = dict( widget='', header='', content='', default='', cornerall='', cornertop='', cornerbottom='', button='button btn', buttontext='buttontext button', buttonadd='icon plus icon-plus', buttonback='icon leftarrow icon-arrow-left', buttonexport='icon downarrow icon-download', buttondelete='icon trash icon-trash', buttonedit='icon pen icon-pencil', buttontable='icon rightarrow icon-arrow-right', buttonview='icon magnifier icon-zoom-in', ) elif not isinstance(ui, dict): raise RuntimeError, 'SQLFORM.grid ui argument must be a dictionary' db = query._db T = current.T request = current.request session = current.session response = current.response wenabled = (not user_signature or (session.auth and session.auth.user)) create = wenabled and create editable = wenabled and editable deletable = wenabled and deletable def url(**b): b['args'] = args + b.get('args', []) b['hash_vars'] = False b['user_signature'] = user_signature return URL(**b) def url2(**b): b['args'] = request.args + b.get('args', []) b['hash_vars'] = False b['user_signature'] = user_signature return URL(**b) referrer = session.get('_web2py_grid_referrer_' + formname, url()) # if not user_signature every action is accessible # else forbid access unless # - url is based url # - url has valid signature (vars are not signed, only path_info) # = url does not contain 'create','delete','edit' (readonly) if user_signature: if not ('/'.join(str(a) for a in args) == '/'.join(request.args) # or # URL.verify(request,user_signature=user_signature, # hash_vars=False) or not ('create' in request.args or 'delete' in request.args or 'edit' in request.args)): session.flash = T('not authorized') redirect(referrer) def gridbutton(buttonclass='buttonadd', buttontext='Add', buttonurl=url(args=[]), callback=None, delete=None, trap=True): if showbuttontext: if callback: return A(SPAN(_class=ui.get(buttonclass)), SPAN(T(buttontext), _title=buttontext, _class=ui.get('buttontext')), callback=callback, delete=delete, _class=trap_class(ui.get('button'), trap)) else: return A(SPAN(_class=ui.get(buttonclass)), SPAN(T(buttontext), _title=buttontext, _class=ui.get('buttontext')), _href=buttonurl, _class=trap_class(ui.get('button'), trap)) else: if callback: return A(SPAN(_class=ui.get(buttonclass)), callback=callback, delete=delete, _title=buttontext, _class=trap_class(ui.get('buttontext'), trap)) else: return A(SPAN(_class=ui.get(buttonclass)), _href=buttonurl, _title=buttontext, _class=trap_class(ui.get('buttontext'), trap)) dbset = db(query) tablenames = db._adapter.tables(dbset.query) #if left!=None: tablenames+=db._adapter.tables(left) if left != None: if isinstance(left, list): for _left in left: tablenames = tablenames + db._adapter.tables(_left) else: tablenames = tablenames + db._adapter.tables(left) if join != None: if isinstance(join, list): for _join in join: tablenames = tablenames + db._adapter.tables(_join) else: tablenames = tablenames + db._adapter.tables(join) tables = [db[tablename] for tablename in tablenames] if not fields: fields = reduce(lambda a, b: a + b, [[field for field in table] for table in tables]) if not field_id: field_id = tables[0]._id columns = [str(field) for field in fields \ if field._tablename in tablenames] if not str(field_id) in [str(f) for f in fields]: fields.append(field_id) table = field_id.table tablename = table._tablename if upload == '<default>': upload = lambda filename: url(args=['download', filename]) if len(request.args) > 1 and request.args[-2] == 'download': stream = response.download(request, db) raise HTTP(200, stream, **response.headers) def buttons(edit=False, view=False, record=None): buttons = DIV( gridbutton('buttonback', 'Back', referrer), _class='form_header row_buttons %(header)s %(cornertop)s' % ui) if edit and (not callable(edit) or edit(record)): args = ['edit', table._tablename, request.args[-1]] buttons.append(gridbutton('buttonedit', 'Edit', url(args=args))) if view: args = ['view', table._tablename, request.args[-1]] buttons.append(gridbutton('buttonview', 'View', url(args=args))) if record and links: for link in links: if isinstance(link, dict): buttons.append(link['body'](record)) elif link(record): buttons.append(link(record)) return buttons formfooter = DIV( _class='form_footer row_buttons %(header)s %(cornerbottom)s' % ui) create_form = update_form = view_form = search_form = None sqlformargs = dict(formargs) if create and len(request.args) > 1 and request.args[-2] == 'new': table = db[request.args[-1]] sqlformargs.update(createargs) create_form = SQLFORM(table, ignore_rw=ignore_rw, formstyle=formstyle, _class='web2py_form', **sqlformargs) create_form.process(formname=formname, next=referrer, onvalidation=onvalidation, onsuccess=oncreate) res = DIV(buttons(), create_form, formfooter, _class=_class) res.create_form = create_form res.update_form = update_form res.view_form = view_form res.search_form = search_form return res elif details and len(request.args) > 2 and request.args[-3] == 'view': table = db[request.args[-2]] record = table(request.args[-1]) or redirect(URL('error')) sqlformargs.update(viewargs) view_form = SQLFORM(table, record, upload=upload, ignore_rw=ignore_rw, formstyle=formstyle, readonly=True, _class='web2py_form', **sqlformargs) res = DIV(buttons(edit=editable, record=record), view_form, formfooter, _class=_class) res.create_form = create_form res.update_form = update_form res.view_form = view_form res.search_form = search_form return res # elif editable and len(request.args)>2 and request.args[-3]=='edit': # table = db[request.args[-2]] # record = table(request.args[-1]) or redirect(URL('error')) # sqlformargs.update(editargs) # update_form = SQLFORM(table, record, upload=upload, ignore_rw=ignore_rw, # formstyle=formstyle, deletable=deletable, # _class='web2py_form', # submit_button=T('Submit'), # delete_label=T('Check to delete'), # **sqlformargs) # update_form.process(formname=formname, # onvalidation=onvalidation, # onsuccess=onupdate, # next=referrer) # res = DIV(buttons(view=details, record=record), # update_form, formfooter, _class=_class) # res.create_form = create_form # res.update_form = update_form # res.view_form = view_form # res.search_form = search_form # return res elif deletable and len( request.args) > 2 and request.args[-3] == 'delete': table = db[request.args[-2]] if ondelete: ondelete(table, request.args[-1]) ret = db(table[table._id.name] == request.args[-1]).delete() return ret exportManager = dict( csv_with_hidden_cols=(ExporterCSV,'CSV (hidden cols)'), csv=(ExporterCSV,'CSV'), xml=(ExporterXML, 'XML'), html=(ExporterHTML, 'HTML'), tsv_with_hidden_cols=\ (ExporterTSV,'TSV (Excel compatible, hidden cols)'), tsv=(ExporterTSV, 'TSV (Excel compatible)')) if not exportclasses is None: exportManager.update(exportclasses) export_type = request.vars._export_type if export_type: order = request.vars.order or '' if sortable: if order and not order == 'None': if order[:1] == '~': sign, rorder = '~', order[1:] else: sign, rorder = '', order tablename, fieldname = rorder.split('.', 1) orderby = db[tablename][fieldname] if sign == '~': orderby = ~orderby table_fields = [f for f in fields if f._tablename in tablenames] if export_type in ('csv_with_hidden_cols', 'tsv_with_hidden_cols'): if request.vars.keywords: try: dbset = dbset( SQLFORM.build_query( fields, request.vars.get('keywords', ''))) rows = dbset.select(cacheable=True) except Exception: response.flash = T('Internal Error') rows = [] else: rows = dbset.select(cacheable=True) else: rows = dbset.select(left=left, orderby=orderby, cacheable=True * columns) if export_type in exportManager: value = exportManager[export_type] clazz = value[0] if hasattr(value, '__getitem__') else value oExp = clazz(rows) filename = '.'.join(('rows', oExp.file_ext)) response.headers['Content-Type'] = oExp.content_type response.headers['Content-Disposition'] = \ 'attachment;filename='+filename+';' raise HTTP(200, oExp.export(), **response.headers) elif request.vars.records and not isinstance(request.vars.records, list): request.vars.records = [request.vars.records] elif not request.vars.records: request.vars.records = [] session['_web2py_grid_referrer_' + formname] = url2(vars=request.vars) console = DIV(_class='web2py_console %(header)s %(cornertop)s' % ui) error = None search_actions = DIV(_class='web2py_search_actions') if create: search_actions.append( gridbutton(buttonclass='buttonadd', buttontext=T('Add'), buttonurl=url(args=['new', tablename]))) console.append(search_actions) # if create: # add = gridbutton( # buttonclass='buttonadd', # buttontext='Add', # buttonurl=url(args=['new',tablename])) # if not searchable: # console.append(add) else: add = '' if searchable: sfields = reduce(lambda a, b: a + b, [[f for f in t if f.readable] for t in tables]) if isinstance(search_widget, dict): search_widget = search_widget[tablename] if search_widget == 'default': search_menu = SQLFORM.search_menu(sfields) search_widget = lambda sfield, url: CAT( add, FORM(INPUT( _name='keywords', _value=request.vars.keywords, _id='web2py_keywords', _onfocus= "jQuery('#w2p_query_fields').change();jQuery('#w2p_query_panel').slideDown();" ), INPUT( _type='submit', _value=T('Search'), _class="btn"), INPUT(_type='submit', _value=T('Clear'), _class="btn", _onclick="jQuery('#web2py_keywords').val('');"), _method="GET", _action=url), search_menu) form = search_widget and search_widget(sfields, url()) or '' console.append(form) keywords = request.vars.get('keywords', '') try: if callable(searchable): subquery = searchable(sfields, keywords) else: subquery = SQLFORM.build_query(sfields, keywords) except RuntimeError: subquery = None error = T('Invalid query') else: subquery = None if subquery: dbset = dbset(subquery) try: if groupby: nrows = len( dbset.select(*groupfields, join=join, left=left, groupby=groupby, having=having, cacheable=True)) elif left or join: nrows = dbset.select('count(*)', join=join, left=left, cacheable=True).first()['count(*)'] # if left or groupby: # c = 'count(*)' # nrows = dbset.select(c,left=left,cacheable=True, # groupby=groupby).first()[c] else: nrows = dbset.count() except: nrows = 0 error = T('Unsupported query') order = request.vars.order or '' if sortable: if order and not order == 'None': if groupby: if str(groupby[0]).find(order) > -1: tablename, fieldname = order.split('~')[-1].split( '.', 1) sort_field = db[tablename][fieldname] exception = sort_field.type in ('date', 'datetime', 'time') if exception: orderby = (order[:1] == '~' and sort_field) or ~sort_field else: orderby = (order[:1] == '~' and ~sort_field) or sort_field else: tablename, fieldname = order.split('~')[-1].split( '.', 1) gfields = str(groupfields[0]).split(",") for gfield in gfields: if len(gfield.split(" AS ")) > 1: if gfield.split(" AS ")[1] == fieldname: if str(gfield.split(" AS ")[0]).find( "SUM") > -1: sort_field = db[tablename][ fieldname].sum() elif str(gfield.split(" AS ")[0]).find( "COUNT") > -1: sort_field = db[tablename][ fieldname].count() elif str(gfield.split(" AS ")[0]).find( "MIN") > -1: sort_field = db[tablename][ fieldname].min() elif str(gfield.split(" AS ")[0]).find( "MAX") > -1: sort_field = db[tablename][ fieldname].max() elif str(gfield.split(" AS ")[0]).find( "LENGTH") > -1: sort_field = db[tablename][ fieldname].len() else: break orderby = (order[:1] == '~' and ~sort_field) or sort_field break else: tablename, fieldname = order.split('~')[-1].split('.', 1) sort_field = db[tablename][fieldname] exception = sort_field.type in ('date', 'datetime', 'time') if exception: orderby = (order[:1] == '~' and sort_field) or ~sort_field else: orderby = (order[:1] == '~' and ~sort_field) or sort_field head = TR(_class=ui.get('header')) if selectable: head.append(TH(_class=ui.get('default'))) for field in fields: if columns and not str(field) in columns: continue if not field.readable: continue key = str(field) header = headers.get( str(field), hasattr(field, 'label') and field.label or key) if sortable: if key == order: key, marker = '~' + order, sorter_icons[0] elif key == order[1:]: marker = sorter_icons[1] else: marker = '' header = A( header, marker, _href=url(vars=dict(keywords=request.vars.keywords or '', order=key)), _class=trap_class()) head.append(TH(header, _class=ui.get('default'))) if links and links_in_grid: for link in links: if isinstance(link, dict): head.append(TH(link['header'], _class=ui.get('default'))) # Include extra column for buttons if needed. include_buttons_column = ( details or editable or deletable or (links and links_in_grid and not all([isinstance(link, dict) for link in links]))) if include_buttons_column: head.insert(0, TH(_class=ui.get('default', ''))) # head.append(TH(_class=ui.get('default'))) paginator = UL() if paginate and paginate < nrows: npages, reminder = divmod(nrows, paginate) if reminder: npages += 1 try: page = int(request.vars.page or 1) - 1 except ValueError: page = 0 limitby = (paginate * page, paginate * (page + 1)) def self_link(name, p): d = dict(page=p + 1) if order: d['order'] = order if request.vars.keywords: d['keywords'] = request.vars.keywords return A(name, _href=url(vars=d), _class=trap_class()) NPAGES = 5 # window is 2*NPAGES if page > NPAGES + 1: paginator.append(LI(self_link('<<', 0))) if page > NPAGES: paginator.append(LI(self_link('<', page - 1))) pages = range(max(0, page - NPAGES), min(page + NPAGES, npages)) for p in pages: if p == page: paginator.append( LI(A(p + 1, _onclick='return false'), _class=trap_class('current'))) else: paginator.append(LI(self_link(p + 1, p))) if page < npages - NPAGES: paginator.append(LI(self_link('>', page + 1))) if page < npages - NPAGES - 1: paginator.append(LI(self_link('>>', npages - 1))) else: limitby = None try: table_fields = [f for f in fields if f._tablename in tablenames] if groupby: rows = dbset.select(*groupfields, join=join, left=left, groupby=groupby, having=having, orderby=orderby, limitby=limitby, cacheable=True) else: rows = dbset.select(join=join, left=left, orderby=orderby, limitby=limitby, cacheable=True, *table_fields) # rows = dbset.select(left=left,orderby=orderby, # groupby=groupby,limitby=limitby, # cacheable=True,*table_fields) except SyntaxError: rows = None error = T("Query Not Supported") if nrows: message = error or T('%(nrows)s records found') % dict(nrows=nrows) console.append(DIV(message, _class='web2py_counter')) if rows: htmltable = TABLE(THEAD(head)) tbody = TBODY() numrec = 0 for row in rows: if numrec % 2 == 0: classtr = 'even' else: classtr = 'odd' numrec += 1 id = row[field_id] #@ReservedAssignment if id: rid = id if callable(rid): ### can this ever be callable? rid = rid(row) tr = TR(_id=rid, _class='%s %s' % (classtr, 'with_id')) else: tr = TR(_class=classtr) if selectable: tr.append( INPUT(_type="checkbox", _name="records", _value=id, value=request.vars.records)) for field in fields: if not str(field) in columns: continue if not field.readable: continue if field.type == 'blob': continue value = row[field] maxlength = maxtextlengths.get(str(field), maxtextlength) if field.represent: try: value = field.represent(value, row) except Exception: try: value = field.represent( value, row[field._tablename]) except Exception: pass elif field.type == 'boolean': value = INPUT(_type="checkbox", _checked=value, _disabled=True) elif field.type == 'upload': if value: if callable(upload): value = A(current.T('file'), _href=upload(value)) elif upload: value = A(current.T('file'), _href='%s/%s' % (upload, value)) else: value = '' if isinstance(value, str): value = truncate_string(value, maxlength) elif not isinstance(value, DIV): value = field.formatter(value) if not include_buttons_column: tr.append(TD(value, _style="padding:10px;")) else: tr.append(TD(value)) row_buttons = TD(_class='row_buttons') if links and links_in_grid: for link in links: if isinstance(link, dict): tr.append(TD(link['body'](row))) else: if link(row): row_buttons.append(link(row)) if include_buttons_column: if details and (not callable(details) or details(row)): row_buttons.append( gridbutton('buttonview', 'View', url(args=['view', tablename, id]))) if editable and (not callable(editable) or editable(row)): row_buttons.append( gridbutton('buttonedit', 'Edit', url(args=['edit', tablename, id]))) if deletable and (not callable(deletable) or deletable(row)): row_buttons.append( gridbutton( 'buttondelete', 'Delete', callback=url(args=['delete', tablename, id]), delete='tr')) #tr.append(row_buttons) tr.insert(0, row_buttons) tbody.append(tr) htmltable.append(tbody) htmltable = DIV(htmltable, _style='width:100%;overflow-x:auto') if selectable: htmltable = FORM(htmltable, INPUT(_type="submit")) if htmltable.process(formname=formname).accepted: # htmltable.vars.records = htmltable.vars.records or [] htmltable.vars.records = htmltable.vars.records if type( htmltable.vars.records) == list else [ htmltable.vars.records ] records = [int(r) for r in htmltable.vars.records] selectable(records) redirect(referrer) else: htmltable = DIV(current.T('No records found')) if csv and nrows: export_links = [] for k, v in sorted(exportManager.items()): label = v[1] if hasattr(v, "__getitem__") else k link = url2(vars=dict(order=request.vars.order or '', _export_type=k, keywords=request.vars.keywords or '')) export_links.append(A(T(label), _href=link)) export_menu = \ DIV(T('Export:'),_class="w2p_export_menu",*export_links) else: export_menu = None res = DIV(console, DIV(htmltable, _class="web2py_table"), _class='%s %s' % (_class, ui.get('widget'))) if paginator.components: res.append( DIV(paginator, _class="web2py_paginator %(header)s %(cornerbottom)s" % ui)) if export_menu: res.append(export_menu) res.create_form = create_form res.update_form = update_form res.view_form = view_form res.search_form = search_form return res
def __new__(cls, **kwargs): instance = super(PERSON_FORM, cls).__new__(cls) instance.person = kwargs.get('person') # PERSON type instance.readonly = kwargs.get('readonly') or False instance.readonly_fields = kwargs.get('readonly_fields') or [] my_logger.debug(message='instance.person:%s' % instance.person) my_logger.debug(message='instance.person.creator:%s' % instance.person.creator) if instance.person is not None: current.db.person.first_name.default = instance.person.first_name if 'first_name' in instance.readonly_fields: current.db.person.first_name.writable = False current.db.person.last_name.default = instance.person.last_name if 'last_name' in instance.readonly_fields: current.db.person.last_name.writable = False current.db.person.email.default = instance.person.email if 'email' in instance.readonly_fields: current.db.person.email.writable = False current.db.person.contact.default = instance.person.contact if 'contact' in instance.readonly_fields: current.db.person.contact.writable = False current.db.person.email.requires = [ IS_NOT_EMPTY(), IS_EMAIL(), IS_NOT_IN_DB( current.db(current.db.person.id != instance.person.id), current.db.person.email) ] # creator is a computed field and then not shown by web2py # we need to add it manually instance.form = SQLFORM.factory(Field('creator', 'string', writable=not 'creator' in instance.readonly_fields, label=cc.get_string("PERSON_CREATOR_LABEL"), default=instance.person.creator.email \ if instance.person.creator is not None \ else ''), # creator should exists - backward compatibility current.db.person, Field('is_all_entity', 'boolean', label=cc.get_string("PERSON_IS_ALL_ENTITY_LABEL"), comment=cc.get_string("PERSON_IS_ALL_ENTITY_COMMENT"), represent=lambda r: current.T(str(instance.person.is_all_entity())), # disabled if the user is not admin readable=current.auth.has_membership('all_entity') or \ current.auth.has_membership('admin_entity') or \ current.auth.has_permission('admin'), # admin_ENTITY: backward compatibility writable=(current.auth.has_membership('all_entity') or \ current.auth.has_membership('admin_entity') or \ current.auth.has_permission('admin')) and \ not 'custom_entity' in instance.readonly_fields, # for an update request, pre populating the widget if the user is in all entities default=instance.person.is_all_entity(), ), Field('custom_entity', 'list:reference entity', comment=cc.get_string("PERSON_ENTITY_COMMENT"), label=cc.get_string("PERSON_ENTITY_LABEL"), required=True, notnull=True, writable=not 'custom_entity' in instance.readonly_fields, # for an update request, pre populating the widget given the user entities default=[_entity.id for _entity in instance.person.entities] \ if instance.person.entities is not None \ else [], requires=[IS_IN_DB_AND_USER_ENTITY(current.db(current.db.entity.id > 0), current.db.entity.id, current.db.entity._format, multiple=True), IS_ONE_SELECTED(db=current.db, table=current.db.entity, table_set=~current.db.entity.role.like('user_%'))], represent=lambda r: XML(' <br/>'.join(['%s' % (e.name) \ for e in instance.person.entities])) \ if (not instance.person.is_all_entity() and instance.person.entities is not None) else 'X', widget=lambda field, value: SQLFORM.widgets.multiple.widget(field, value, _class='required')), Field('is_admin', 'boolean', label=cc.get_string("PERSON_IS_ADMIN_LABEL"), comment=cc.get_string("PERSON_IS_ADMIN_COMMENT"), represent=lambda r: current.T(str(instance.person.is_admin())), # disabled if the user is not admin readable=current.auth.has_permission('admin'), writable=current.auth.has_permission('admin') and not 'is_admin' in instance.readonly_fields, # for an update request, pre populating the widget if the user is admin default=instance.person.is_admin(), ), Field('custom_permission', 'string', # this does not matter given that we define our own permission widget label=cc.get_string("PERSON_ENTITY_PERMISSION_LABEL"), required=True, notnull=True, writable=not 'custom_permission' in instance.readonly_fields, # for an update request, pre populating the widget given the user permissions default=[_permission.name for _permission in instance.person.permissions], comment=cc.get_string("PERSON_ENTITY_PERMISSION_COMMENT"), requires=IS_CHIMITHEQUE_PERMISSION(), represent=lambda r: PermissionWidget.represent(r), widget=lambda field, value: PermissionWidget.widget(field, value, _class='required', auth_user_permissions=[_permission.name for _permission in PERSON_MAPPER().find_permissions(current.auth.user.id)] \ if not current.auth.has_permission('admin') \ else None)), readonly=instance.readonly, comments=not instance.readonly, next=URL(current.request.application, 'user', 'list'), submit_button=cc.get_string("SUBMIT") ) else: instance.form = SQLFORM.factory( Field('None', 'string', writable=False, readable=False)) return instance
def snapshot(info=None, context=5, code=None, environment=None): """Return a dict describing a given traceback (based on cgitb.text).""" import time import linecache import inspect import pydoc import cgitb # if no exception info given, get current: etype, evalue, etb = info or sys.exc_info() if isinstance(etype, ClassType): etype = etype.__name__ # create a snapshot dict with some basic information s = {} s['pyver'] = 'Python ' + sys.version.split( )[0] + ': ' + sys.executable + ' (prefix: %s)' % sys.prefix s['date'] = time.ctime(time.time()) # start to process frames records = inspect.getinnerframes(etb, context) del etb # Prevent circular references that would cause memory leaks s['frames'] = [] for frame, file, lnum, func, lines, index in records: file = file and os.path.abspath(file) or '?' args, varargs, varkw, locals = inspect.getargvalues(frame) call = '' if func != '?': call = inspect.formatargvalues( args, varargs, varkw, locals, formatvalue=lambda value: '=' + pydoc.text.repr(value)) # basic frame information f = { 'file': file, 'func': func, 'call': call, 'lines': {}, 'lnum': lnum } highlight = {} def reader(lnum=[lnum]): highlight[lnum[0]] = 1 try: return linecache.getline(file, lnum[0]) finally: lnum[0] += 1 vars = cgitb.scanvars(reader, frame, locals) # if it is a view, replace with generated code if file.endswith('html'): lmin = lnum > context and (lnum - context) or 0 lmax = lnum + context lines = code.split("\n")[lmin:lmax] index = min(context, lnum) - 1 if index is not None: i = lnum - index for line in lines: f['lines'][i] = line.rstrip() i += 1 # dump local variables (referenced in current line only) f['dump'] = {} for name, where, value in vars: if name in f['dump']: continue if value is not cgitb.__UNDEF__: if where == 'global': name = 'global ' + name elif where != 'local': name = where + name.split('.')[-1] f['dump'][name] = pydoc.text.repr(value) else: f['dump'][name] = 'undefined' s['frames'].append(f) # add exception type, value and attributes s['etype'] = str(etype) s['evalue'] = str(evalue) s['exception'] = {} if isinstance(evalue, BaseException): for name in dir(evalue): value = pydoc.text.repr(getattr(evalue, name)) s['exception'][name] = value # add all local values (of last frame) to the snapshot s['locals'] = {} for name, value in locals.items(): s['locals'][name] = pydoc.text.repr(value) # add web2py environment variables for k, v in environment.items(): if k in ('request', 'response', 'session'): s[k] = XML(str(BEAUTIFY(v))) return s
def __call__(self): output = {} T = current.T request = current.request response = current.response s3 = response.s3 # Check logged in and permissions auth = current.auth settings = current.deployment_settings roles = current.session.s3.roles system_roles = auth.get_system_roles() AUTHENTICATED = system_roles.AUTHENTICATED # Login/Registration forms self_registration = current.deployment_settings.get_security_registration_visible( ) registered = False login_form = None login_div = None register_form = None register_div = None # Contact Form request_email = settings.get_frontpage("request_email") if request_email: from s3dal import Field from gluon.validators import IS_NOT_EMPTY from gluon.sqlhtml import SQLFORM fields = [ Field( "name", label="Your name", requires=IS_NOT_EMPTY(), ), Field( "address", label="Your e-mail address", requires=IS_NOT_EMPTY(), ), Field( "subject", label="Subject", requires=IS_NOT_EMPTY(), ), Field( "message", "text", label="Message", requires=IS_NOT_EMPTY(), ), ] from s3 import s3_mark_required labels, required = s3_mark_required(fields) s3.has_required = required response.form_label_separator = "" contact_form = SQLFORM.factory( formstyle=settings.get_ui_formstyle(), submit_button=T("Submit"), labels=labels, separator="", table_name="contact", # Dummy table name _id="mailform", *fields) if contact_form.accepts(request.post_vars, current.session, formname="contact_form", keepvalues=False, hideerror=False): # Processs Contact Form form_vars = contact_form.vars sender = "%s <%s>" % (form_vars.name, form_vars.address) result = current.msg.send_email( to=request_email, sender=sender, subject=form_vars.subject, message=form_vars.message, reply_to=form_vars.address, ) if result: response.confirmation = "Thank you for your message - we'll be in touch shortly" if s3.cdn: if s3.debug: s3.scripts.append( "http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.js" ) else: s3.scripts.append( "http://ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js" ) else: if s3.debug: s3.scripts.append("/%s/static/scripts/jquery.validate.js" % request.application) else: s3.scripts.append( "/%s/static/scripts/jquery.validate.min.js" % request.application) validation_script = ''' $('#mailform').validate({ errorClass:'req', rules:{ name:{ required:true }, address: { required:true, email:true }, subject:{ required:true }, message:{ required:true } }, messages:{ name:"Enter your name", subject:"Enter a subject", message:"Enter a message", address:{ required:"Please enter a valid email address", email:"Please enter a valid email address" } }, errorPlacement:function(error,element){ error.appendTo(element.parents('div.controls')) }, submitHandler:function(form){ form.submit() } })''' s3.jquery_ready.append(validation_script) else: contact_form = "" if AUTHENTICATED not in roles: login_buttons = DIV(A(T("Login"), _id="show-login", _class="tiny secondary button"), _id="login-buttons") script = ''' $('#show-mailform').click(function(e){ e.preventDefault() $('#intro').slideDown(400, function() { $('#login_box').hide() }); }) $('#show-login').click(function(e){ e.preventDefault() $('#login_form').show() $('#register_form').hide() $('#login_box').show() $('#intro').slideUp() })''' s3.jquery_ready.append(script) # This user isn't yet logged-in if "registered" in request.cookies: # This browser has logged-in before registered = True if self_registration is True: # Provide a Registration box on front page login_buttons.append( A(T("Register"), _id="show-register", _class="tiny secondary button", _style="margin-left:5px")) script = ''' $('#show-register').click(function(e){ e.preventDefault() $('#login_form').hide() $('#register_form').show() $('#login_box').show() $('#intro').slideUp() })''' s3.jquery_ready.append(script) register_form = auth.register() register_div = DIV( H3(T("Register")), P( XML( T("If you would like to help, then please <b>sign up now</b>" )))) register_script = ''' $('#register-btn').click(function(e){ e.preventDefault() $('#register_form').show() $('#login_form').hide() }) $('#login-btn').click(function(e){ e.preventDefault() $('#register_form').hide() $('#login_form').show() })''' s3.jquery_ready.append(register_script) # Provide a login box on front page auth.messages.submit_button = T("Login") login_form = auth.login(inline=True) login_div = DIV( H3(T("Login")), P( XML( T("Registered users can <b>login</b> to access the system" )))) else: login_buttons = "" output["login_buttons"] = login_buttons output["self_registration"] = self_registration output["registered"] = registered output["login_div"] = login_div output["login_form"] = login_form output["register_div"] = register_div output["register_form"] = register_form output["contact_form"] = contact_form # Slick slider if s3.debug: s3.scripts.append("/%s/static/scripts/slick.js" % request.application) else: s3.scripts.append("/%s/static/scripts/slick.min.js" % request.application) script = ''' $(document).ready(function(){ $('#title-image').slick({ autoplay:true, autoplaySpeed:5000, speed:1000, fade:true, cssEase:'linear' }); });''' s3.jquery_ready.append(script) s3.stylesheets.append("../themes/%s/homepage.css" % THEME) self._view(THEME, "index.html") return output