fixes issue 1980
pyflaked the module, at least a bit. Sometimes I feel developers are in a contest where less characters and lines win. Concise implementation wins over verbose one, but less SLOC DON'T mean somewhat better code. Just reading through this module makes my brain hurt a bit
This commit is contained in:
+99
-67
@@ -14,13 +14,18 @@ Holds:
|
||||
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import urllib
|
||||
import re
|
||||
import cStringIO
|
||||
|
||||
import os
|
||||
from gluon.http import HTTP
|
||||
from gluon.html import XmlComponent
|
||||
from gluon.html import XML, SPAN, TAG, A, DIV, CAT, UL, LI, TEXTAREA, BR, IMG, SCRIPT, P
|
||||
from gluon.http import HTTP, redirect
|
||||
from gluon.html import XmlComponent, truncate_string
|
||||
from gluon.html import XML, SPAN, TAG, A, DIV, CAT, UL, LI, TEXTAREA, BR, IMG
|
||||
from gluon.html import FORM, INPUT, LABEL, OPTION, SELECT, COL, COLGROUP
|
||||
from gluon.html import TABLE, THEAD, TBODY, TR, TD, TH, STYLE, DEFAULT_PASSWORD_DISPLAY
|
||||
from gluon.html import URL, truncate_string, FIELDSET
|
||||
from gluon.html import TABLE, THEAD, TBODY, TR, TD, TH, STYLE, SCRIPT
|
||||
from gluon.html import URL, FIELDSET, P, DEFAULT_PASSWORD_DISPLAY
|
||||
from gluon.dal import DAL, Field
|
||||
from gluon.dal.base import DEFAULT
|
||||
from gluon.dal.objects import Table, Row, Expression
|
||||
@@ -29,16 +34,12 @@ from gluon.dal.helpers.methods import smart_query, bar_encode, sqlhtml_validator
|
||||
from gluon.dal.helpers.classes import Reference, SQLCustomType
|
||||
from gluon.storage import Storage
|
||||
from gluon.utils import md5_hash
|
||||
from gluon.validators import IS_EMPTY_OR, IS_NOT_EMPTY, IS_LIST_OF, IS_DATE, \
|
||||
IS_DATETIME, IS_INT_IN_RANGE, IS_FLOAT_IN_RANGE, IS_STRONG
|
||||
from gluon.validators import IS_EMPTY_OR, IS_NOT_EMPTY, IS_LIST_OF, IS_DATE
|
||||
from gluon.validators import IS_DATETIME, IS_INT_IN_RANGE, IS_FLOAT_IN_RANGE
|
||||
from gluon.validators import IS_STRONG
|
||||
|
||||
import gluon.serializers as serializers
|
||||
import datetime
|
||||
import urllib
|
||||
import re
|
||||
import cStringIO
|
||||
from gluon.globals import current
|
||||
from gluon.http import redirect
|
||||
|
||||
try:
|
||||
import gluon.settings as settings
|
||||
@@ -49,7 +50,7 @@ widget_class = re.compile('^\w*')
|
||||
|
||||
|
||||
def add_class(a, b):
|
||||
return a+' '+b if a else b
|
||||
return a + ' ' + b if a else b
|
||||
|
||||
|
||||
def represent(field, value, record):
|
||||
@@ -85,11 +86,11 @@ def show_if(cond):
|
||||
if not cond:
|
||||
return None
|
||||
base = "%s_%s" % (cond.first.tablename, cond.first.name)
|
||||
if ((cond.op.__name__ == 'EQ' and cond.second == True) or
|
||||
(cond.op.__name__ == 'NE' and cond.second == False)):
|
||||
if ((cond.op.__name__ == 'EQ' and cond.second is True) or
|
||||
(cond.op.__name__ == 'NE' and cond.second is False)):
|
||||
return base, ":checked"
|
||||
if ((cond.op.__name__ == 'EQ' and cond.second == False) or
|
||||
(cond.op.__name__ == 'NE' and cond.second == True)):
|
||||
if ((cond.op.__name__ == 'EQ' and cond.second is False) or
|
||||
(cond.op.__name__ == 'NE' and cond.second is True)):
|
||||
return base, ":not(:checked)"
|
||||
if cond.op.__name__ == 'EQ':
|
||||
return base, "[value='%s']" % cond.second
|
||||
@@ -305,7 +306,8 @@ class ListWidget(StringWidget):
|
||||
_class = 'string'
|
||||
requires = field.requires if isinstance(
|
||||
field.requires, (IS_NOT_EMPTY, IS_LIST_OF)) else None
|
||||
if isinstance(value, str): value = [value]
|
||||
if isinstance(value, str):
|
||||
value = [value]
|
||||
nvalue = value or ['']
|
||||
items = [LI(INPUT(_id=_id, _class=_class, _name=_name,
|
||||
value=v, hideerror=k < len(nvalue) - 1,
|
||||
@@ -351,7 +353,6 @@ class RadioWidget(OptionsWidget):
|
||||
else:
|
||||
value = str(value)
|
||||
|
||||
|
||||
attr = cls._attributes(field, {}, **attributes)
|
||||
attr['_class'] = add_class(attr.get('_class'), 'web2py_radiowidget')
|
||||
|
||||
@@ -626,7 +627,7 @@ class AutocompleteWidget(object):
|
||||
self.help_fields = help_fields or []
|
||||
self.help_string = help_string
|
||||
if self.help_fields and not self.help_string:
|
||||
self.help_string = ' '.join('%%(%s)s'%f.name
|
||||
self.help_string = ' '.join('%%(%s)s' % f.name
|
||||
for f in self.help_fields)
|
||||
|
||||
self.request = request
|
||||
@@ -900,7 +901,7 @@ def formstyle_bootstrap3_inline_factory(col_label_size=3):
|
||||
label['_for'] = None
|
||||
label.insert(0, controls)
|
||||
_controls = DIV(DIV(label, _help, _class="checkbox"),
|
||||
_class="%s %s" % (offset_class, col_class))
|
||||
_class="%s %s" % (offset_class, col_class))
|
||||
label = ''
|
||||
elif isinstance(controls, SELECT):
|
||||
controls.add_class('form-control')
|
||||
@@ -1132,7 +1133,7 @@ class SQLFORM(FORM):
|
||||
if fieldname.find('.') >= 0:
|
||||
continue
|
||||
|
||||
field = (self.table[fieldname] if fieldname in self.table.fields
|
||||
field = (self.table[fieldname] if fieldname in self.table.fields
|
||||
else self.extra_fields[fieldname])
|
||||
comment = None
|
||||
|
||||
@@ -1184,7 +1185,7 @@ class SQLFORM(FORM):
|
||||
cond = readonly or \
|
||||
(not ignore_rw and not field.writable and field.readable)
|
||||
|
||||
if default is not None and not cond:
|
||||
if default is not None and not cond:
|
||||
default = field.formatter(default)
|
||||
|
||||
dspval = default
|
||||
@@ -1192,10 +1193,6 @@ class SQLFORM(FORM):
|
||||
|
||||
if cond:
|
||||
|
||||
# ## if field.re field.requires = sqlhtml_validators(field) field.requires = sqlhtml_validators(field)present is available else
|
||||
# ## ignore blob and preview uploaded images
|
||||
# ## format everything else
|
||||
|
||||
if field.represent:
|
||||
inp = represent(field, default, record)
|
||||
elif field.type in ['blob']:
|
||||
@@ -1272,7 +1269,7 @@ class SQLFORM(FORM):
|
||||
(olname.replace('.', '__') + SQLFORM.ID_ROW_SUFFIX,
|
||||
'', widget, col3.get(olname, '')))
|
||||
self.custom.linkto[olname.replace('.', '__')] = widget
|
||||
# </block>
|
||||
# </block>
|
||||
|
||||
# when deletable, add delete? checkbox
|
||||
self.custom.delete = self.custom.deletable = ''
|
||||
@@ -1291,16 +1288,15 @@ class SQLFORM(FORM):
|
||||
)
|
||||
xfields.append(
|
||||
(self.FIELDKEY_DELETE_RECORD + SQLFORM.ID_ROW_SUFFIX,
|
||||
LABEL(
|
||||
LABEL(
|
||||
T(delete_label), sep,
|
||||
_for=self.FIELDKEY_DELETE_RECORD,
|
||||
_id=self.FIELDKEY_DELETE_RECORD + \
|
||||
SQLFORM.ID_LABEL_SUFFIX),
|
||||
_id=self.FIELDKEY_DELETE_RECORD +
|
||||
SQLFORM.ID_LABEL_SUFFIX),
|
||||
widget,
|
||||
col3.get(self.FIELDKEY_DELETE_RECORD, '')))
|
||||
self.custom.delete = self.custom.deletable = widget
|
||||
|
||||
|
||||
# when writable, add submit button
|
||||
self.custom.submit = ''
|
||||
if not readonly:
|
||||
@@ -1480,7 +1476,7 @@ class SQLFORM(FORM):
|
||||
# that does not pass validation, yet it should be deleted
|
||||
for fieldname in self.fields:
|
||||
|
||||
field = (self.table[fieldname]
|
||||
field = (self.table[fieldname]
|
||||
if fieldname in self.table.fields
|
||||
else self.extra_fields[fieldname])
|
||||
### this is a workaround! widgets should always have default not None!
|
||||
@@ -1995,6 +1991,18 @@ class SQLFORM(FORM):
|
||||
details = details and not groupby
|
||||
rows = None
|
||||
|
||||
# see issue 1980. Basically we can have keywords in get_vars
|
||||
# (i.e. when the search term is propagated through page=2&keywords=abc)
|
||||
# but if there is keywords in post_vars (i.e. POSTing a search request)
|
||||
# the one in get_vars should be replaced by the new one
|
||||
keywords = ''
|
||||
if 'keywords' in request.post_vars:
|
||||
keywords = request.post_vars.keywords
|
||||
elif 'keywords' in request.get_vars:
|
||||
keywords = request.get_vars.keywords
|
||||
|
||||
print 'keyworkds are', keywords
|
||||
|
||||
def fetch_count(dbset):
|
||||
##FIXME for google:datastore cache_count is ignored
|
||||
## if it's not an integer
|
||||
@@ -2051,7 +2059,7 @@ class SQLFORM(FORM):
|
||||
'/'.join(str(a) for a in args) == '/'.join(request.args) or
|
||||
URL.verify(request, user_signature=user_signature,
|
||||
hash_vars=False) or
|
||||
(request.args(len(args))=='view' and not logged)):
|
||||
(request.args(len(args))=='view' and not logged)):
|
||||
session.flash = T('not authorized')
|
||||
redirect(referrer)
|
||||
|
||||
@@ -2096,8 +2104,8 @@ class SQLFORM(FORM):
|
||||
else:
|
||||
fields = []
|
||||
columns = []
|
||||
filter1 = lambda f:isinstance(f, Field)
|
||||
filter2 = lambda f:isinstance(f, Field) and f.readable
|
||||
filter1 = lambda f: isinstance(f, Field)
|
||||
filter2 = lambda f: isinstance(f, Field) and f.readable
|
||||
for table in tables:
|
||||
fields += filter(filter1, table)
|
||||
columns += filter(filter2, table)
|
||||
@@ -2111,15 +2119,18 @@ class SQLFORM(FORM):
|
||||
if groupby is None:
|
||||
field_id = tables[0]._id
|
||||
elif groupby and isinstance(groupby, Field):
|
||||
field_id = groupby #take the field passed as groupby
|
||||
#take the field passed as groupby
|
||||
field_id = groupby
|
||||
elif groupby and isinstance(groupby, Expression):
|
||||
field_id = groupby.first #take the first groupby field
|
||||
while not(isinstance(field_id, Field)): # Navigate to the first Field of the expression
|
||||
#take the first groupby field
|
||||
field_id = groupby.first
|
||||
while not(isinstance(field_id, Field)):
|
||||
# Navigate to the first Field of the expression
|
||||
field_id = field_id.first
|
||||
table = field_id.table
|
||||
tablename = table._tablename
|
||||
if not any(str(f) == str(field_id) for f in fields):
|
||||
fields = [f for f in fields]+[field_id]
|
||||
fields = [f for f in fields] + [field_id]
|
||||
if upload == '<default>':
|
||||
upload = lambda filename: url(args=['download', filename])
|
||||
if request.args(-2) == 'download':
|
||||
@@ -2283,8 +2294,10 @@ class SQLFORM(FORM):
|
||||
expcolumns = [str(f) for f in columns]
|
||||
selectable_columns = [str(f) for f in columns if not isinstance(f, Field.Virtual)]
|
||||
if export_type.endswith('with_hidden_cols'):
|
||||
#expcolumns = [] start with the visible columns, which includes visible virtual fields
|
||||
selectable_columns = [] #like expcolumns but excluding virtual
|
||||
# expcolumns = [] start with the visible columns, which
|
||||
# includes visible virtual fields
|
||||
selectable_columns = []
|
||||
#like expcolumns but excluding virtual
|
||||
for table in tables:
|
||||
for field in table:
|
||||
if field.readable and field.tablename in tablenames:
|
||||
@@ -2292,19 +2305,21 @@ class SQLFORM(FORM):
|
||||
expcolumns.append(str(field))
|
||||
if not(isinstance(field, Field.Virtual)):
|
||||
selectable_columns.append(str(field))
|
||||
#look for virtual fields not displayed (and virtual method fields to be added here?)
|
||||
#look for virtual fields not displayed (and virtual method
|
||||
#fields to be added here?)
|
||||
for (field_name, field) in table.iteritems():
|
||||
if isinstance(field, Field.Virtual) and not str(field) in expcolumns:
|
||||
expcolumns.append(str(field))
|
||||
|
||||
if export_type in exportManager and exportManager[export_type]:
|
||||
if request.vars.keywords:
|
||||
if keywords:
|
||||
try:
|
||||
#the query should be constructed using searchable fields but not virtual fields
|
||||
#the query should be constructed using searchable
|
||||
#fields but not virtual fields
|
||||
sfields = reduce(lambda a, b: a + b,
|
||||
[[f for f in t if f.readable and not isinstance(f, Field.Virtual)] for t in tables])
|
||||
dbset = dbset(SQLFORM.build_query(
|
||||
sfields, request.vars.get('keywords', '')))
|
||||
sfields, keywords))
|
||||
rows = dbset.select(left=left, orderby=orderby,
|
||||
cacheable=True, *selectable_columns)
|
||||
except Exception, e:
|
||||
@@ -2316,7 +2331,8 @@ class SQLFORM(FORM):
|
||||
|
||||
value = exportManager[export_type]
|
||||
clazz = value[0] if hasattr(value, '__getitem__') else value
|
||||
rows.colnames = expcolumns # expcolumns is all cols to be exported including virtual fields
|
||||
# expcolumns is all cols to be exported including virtual fields
|
||||
rows.colnames = expcolumns
|
||||
oExp = clazz(rows)
|
||||
filename = '.'.join(('rows', oExp.file_ext))
|
||||
response.headers['Content-Type'] = oExp.content_type
|
||||
@@ -2330,8 +2346,7 @@ class SQLFORM(FORM):
|
||||
elif not request.vars.records:
|
||||
request.vars.records = []
|
||||
|
||||
session['_web2py_grid_referrer_' + formname] = \
|
||||
url2(vars=request.get_vars)
|
||||
session['_web2py_grid_referrer_' + formname] = url2(vars=request.get_vars)
|
||||
console = DIV(_class='web2py_console %(header)s %(cornertop)s' % ui)
|
||||
error = None
|
||||
if create:
|
||||
@@ -2357,7 +2372,7 @@ class SQLFORM(FORM):
|
||||
sfields_id = '%s_query_panel' % prefix
|
||||
skeywords_id = '%s_keywords' % prefix
|
||||
search_widget = lambda sfield, url: CAT(FORM(
|
||||
INPUT(_name='keywords', _value=request.vars.keywords,
|
||||
INPUT(_name='keywords', _value=keywords,
|
||||
_id=skeywords_id,_class='form-control',
|
||||
_onfocus="jQuery('#%s').change();jQuery('#%s').slideDown();" % (spanel_id, sfields_id) if advanced_search else ''
|
||||
),
|
||||
@@ -2368,7 +2383,6 @@ class SQLFORM(FORM):
|
||||
form = search_widget and search_widget(sfields, url()) or ''
|
||||
console.append(add)
|
||||
console.append(form)
|
||||
keywords = request.vars.get('keywords', '')
|
||||
try:
|
||||
if callable(searchable):
|
||||
subquery = searchable(sfields, keywords)
|
||||
@@ -2428,7 +2442,7 @@ class SQLFORM(FORM):
|
||||
elif key == ordermatch[1:]:
|
||||
marker = sorter_icons[1]
|
||||
header = A(header, marker, _href=url(vars=dict(
|
||||
keywords=request.vars.keywords or '',
|
||||
keywords=keywords,
|
||||
order=key)), cid=request.cid)
|
||||
headcols.append(TH(header, _class=ui.get('default')))
|
||||
|
||||
@@ -2466,17 +2480,22 @@ class SQLFORM(FORM):
|
||||
if paginate and dbset._db._adapter.dbengine == 'google:datastore':
|
||||
cursor = request.vars.cursor or True
|
||||
limitby = (0, paginate)
|
||||
try: page = int(request.vars.page or 1)-1
|
||||
except ValueError: page = 0
|
||||
elif paginate and paginate<nrows:
|
||||
try: page = int(request.vars.page or 1)-1
|
||||
except ValueError: page = 0
|
||||
limitby = (paginate*page, paginate*(page+1))
|
||||
try:
|
||||
page = int(request.vars.page or 1) - 1
|
||||
except ValueError:
|
||||
page = 0
|
||||
elif paginate and paginate < nrows:
|
||||
try:
|
||||
page = int(request.vars.page or 1) - 1
|
||||
except ValueError:
|
||||
page = 0
|
||||
limitby = (paginate * page, paginate * (page + 1))
|
||||
else:
|
||||
limitby = None
|
||||
try:
|
||||
table_fields = [field for field in fields
|
||||
if (field.tablename in tablenames and not(isinstance(field, Field.Virtual)))]
|
||||
if (field.tablename in tablenames and
|
||||
not(isinstance(field, Field.Virtual)))]
|
||||
if dbset._db._adapter.dbengine == 'google:datastore':
|
||||
rows = dbset.select(left=left, orderby=orderby,
|
||||
groupby=groupby, limitby=limitby,
|
||||
@@ -2514,8 +2533,15 @@ class SQLFORM(FORM):
|
||||
paginator.append(LI('page %s' % (page+1)))
|
||||
if next_cursor:
|
||||
d = dict(page=page+2, cursor=next_cursor)
|
||||
if order: d['order'] = order
|
||||
if request.vars.keywords: d['keywords'] = request.vars.keywords
|
||||
if order:
|
||||
d['order'] = order
|
||||
# see issue 1980, also at the top of the definition
|
||||
# if keyworkds is in request.vars, we don't need to
|
||||
# copy over the keywords parameter in the links for pagination
|
||||
if 'keywords' in request.vars and not keywords:
|
||||
d['keywords'] = ''
|
||||
elif keywords:
|
||||
d['keywords'] = keywords
|
||||
paginator.append(LI(
|
||||
A('next', _href=url(vars=d), cid=request.cid)))
|
||||
elif paginate and paginate < nrows:
|
||||
@@ -2531,8 +2557,13 @@ class SQLFORM(FORM):
|
||||
d = dict(page=p + 1)
|
||||
if order:
|
||||
d['order'] = order
|
||||
if request.vars.keywords:
|
||||
d['keywords'] = request.vars.keywords
|
||||
# see issue 1980, also at the top of the definition
|
||||
# if keyworkds is in request.vars, we don't need to
|
||||
# copy over the keywords parameter in the links for pagination
|
||||
if 'keywords' in request.vars and not keywords:
|
||||
d['keywords'] = ''
|
||||
elif keywords:
|
||||
d['keywords'] = keywords
|
||||
return A(name, _href=url(vars=d), cid=request.cid)
|
||||
NPAGES = 5 # window is 2*NPAGES
|
||||
if page > NPAGES + 1:
|
||||
@@ -2660,7 +2691,8 @@ class SQLFORM(FORM):
|
||||
_style='width:100%;overflow-x:auto;-ms-overflow-x:scroll')
|
||||
if selectable:
|
||||
if not callable(selectable):
|
||||
#now expect that selectable and related parameters are iterator (list, tuple, etc)
|
||||
#now expect that selectable and related parameters are
|
||||
#iterator (list, tuple, etc)
|
||||
inputs = []
|
||||
for i, submit_info in enumerate(selectable):
|
||||
submit_text = submit_info[0]
|
||||
@@ -2708,7 +2740,7 @@ class SQLFORM(FORM):
|
||||
link = url2(vars=dict(
|
||||
order=request.vars.order or '',
|
||||
_export_type=k,
|
||||
keywords=request.vars.keywords or ''))
|
||||
keywords=keywords or ''))
|
||||
export_links.append(A(T(label), _href=link, _title=title, _class='btn btn-default'))
|
||||
export_menu = \
|
||||
DIV(T('Export:'), _class="w2p_export_menu", *export_links)
|
||||
@@ -2797,7 +2829,7 @@ class SQLFORM(FORM):
|
||||
elif callable(table._format):
|
||||
return table._format(row)
|
||||
else:
|
||||
return '#'+str(row.id)
|
||||
return '#' + str(row.id)
|
||||
try:
|
||||
nargs = len(args) + 1
|
||||
previous_tablename, previous_fieldname, previous_id = \
|
||||
@@ -2876,7 +2908,7 @@ class SQLFORM(FORM):
|
||||
opts = [OPTION(T('References')+':', _value='')]
|
||||
linked = []
|
||||
if linked_tables:
|
||||
for item in linked_tables:
|
||||
for item in linked_tables:
|
||||
tb = None
|
||||
if isinstance(item, Table) and item._tablename in check:
|
||||
tablename = item._tablename
|
||||
|
||||
Reference in New Issue
Block a user