Coverage for lino/modlib/extjs/views.py : 27%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: UTF-8 -*- # Copyright 2009-2015 Luc Saffre # License: BSD (see file COPYING for details)
Summary from <http://en.wikipedia.org/wiki/Restful>:
On an element:
- GET : Retrieve a representation of the addressed member of the collection expressed in an appropriate MIME type. - PUT : Update the addressed member of the collection or create it with the specified ID. - POST : Treats the addressed member as a collection and creates a new subordinate of it. - DELETE : Delete the addressed member of the collection.
On a list:
- GET : List the members of the collection. - PUT : Replace the entire collection with another collection. - POST : Create a new entry in the collection where the ID is assigned automatically by the collection. The ID created is included as part of the data returned by this operation. - DELETE : Delete the entire collection.
"""
""" Returns a dict of this record, designed for usage by an EmptyTable. """ #~ rec.update(data=rh.store.row2dict(ar,elem)) rec.update(data=elem._data) #~ rec = elem2rec1(ar,ah,elem) #~ rec.update(title=_("Insert into %s...") % ar.get_title()) rec.update(title=ar.get_action_title()) rec.update(id=-99998) #~ rec.update(id=elem.pk) or -99999) if ar.actor.parameters: #~ rec.update(param_values=ar.ah.store.pv2dict(ar.ui,ar.param_values)) rec.update( param_values=ar.actor.params_layout.params_store.pv2dict( ar.param_values)) return rec
if elem is None: raise Warning("Cannot delete None") msg = ar.actor.disable_delete(elem, ar) if msg is not None: ar.error(None, msg, alert=True) return settings.SITE.kernel.render_action_response(ar)
#~ dblogger.log_deleted(ar.request,elem)
#~ changes.log_delete(ar.request,elem)
dd.pre_ui_delete.send(sender=elem, request=ar.request)
try: elem.delete() except Exception as e: dblogger.exception(e) msg = _("Failed to delete %(record)s : %(error)s." ) % dict(record=dd.obj2unicode(elem), error=e) #~ msg = "Failed to delete %s." % element_name(elem) ar.error(None, msg) return settings.SITE.kernel.render_action_response(ar) #~ raise Http404(msg)
return HttpResponseDeleted()
""" Similar to PlainIndex """
# logger.info("20150427 AdminIndex.get()") # settings.SITE.startup() renderer = dd.plugins.extjs.renderer # if settings.SITE.user_model is not None: # user = request.subst_user or request.user # a = settings.SITE.get_main_action(user) # if a is not None and a.get_view_permission(user.profile): # kw.update(on_ready=renderer.action_call(request, a, {})) return http.HttpResponse(renderer.html_page(request, **kw))
#~ logger.info("20130719 MainHtml") settings.SITE.startup() ui = settings.SITE.kernel #~ raise Exception("20131023") ar = BaseRequest(request) ar.success(html=settings.SITE.get_main_html(request)) return ui.render_action_response(ar)
"""This view is being used when :setting:`remote_user_header` is empty (and :setting:`user_model` not). :class:`lino.core.auth.SessionUserMiddleware`
"""
action_name = request.GET.get(constants.URL_PARAM_ACTION_NAME) if action_name == 'logout': username = request.session.pop('username', None) request.session.pop('password', None) #~ username = request.session['username'] #~ del request.session['password']
ar = BaseRequest(request) ar.success("User %r logged out." % username) return settings.SITE.kernel.render_action_response(ar) raise http.Http404()
username = request.POST.get('username') password = request.POST.get('password') user = auth.authenticate(username, password) ar = BaseRequest(request) if user is None: ar.error("Could not authenticate %r" % username) else: request.session['username'] = username request.session['password'] = password ar.success(("Now logged in as %r" % username)) # print "20150428 Now logged in as %r (%s)" % (username, user) return settings.SITE.kernel.render_action_response(ar)
""" """
ui = settings.SITE.kernel return http.HttpResponse( ui.extjs_renderer.html_page(request, run_jasmine=True))
""" """
ui = settings.SITE.kernel return ui.success(html='Hallo?')
return settings.SITE.kernel.run_callback(request, thread_id, button_id)
# Return the choices for the given field and the given web request # (whose requesting holder is given as `holder`). # holder is either a Model, an Actor or an Action. # model = holder.get_chooser_model() chooser = holder.get_chooser_for_field(field.name) # logger.info('20140822 choices_for_field(%s.%s) --> %s', # holder, field.name, chooser) if chooser: qs = chooser.get_request_choices(request, holder) if not isiterable(qs): raise Exception("%s.%s_choices() returned non-iterable %r" % ( holder.model, field.name, qs)) if chooser.simple_values: def row2dict(obj, d): d[constants.CHOICES_TEXT_FIELD] = str(obj) d[constants.CHOICES_VALUE_FIELD] = obj return d elif chooser.instance_values: # same code as for ForeignKey def row2dict(obj, d): d[constants.CHOICES_TEXT_FIELD] = holder.get_choices_text( obj, request, field) d[constants.CHOICES_VALUE_FIELD] = obj.pk return d else: # values are (value,text) tuples def row2dict(obj, d): d[constants.CHOICES_TEXT_FIELD] = str(obj[1]) d[constants.CHOICES_VALUE_FIELD] = obj[0] return d
elif field.choices: qs = field.choices
def row2dict(obj, d): if type(obj) is list or type(obj) is tuple: d[constants.CHOICES_TEXT_FIELD] = str(obj[1]) d[constants.CHOICES_VALUE_FIELD] = obj[0] else: d[constants.CHOICES_TEXT_FIELD] = holder.get_choices_text( obj, request, field) d[constants.CHOICES_VALUE_FIELD] = str(obj) return d
elif isinstance(field, models.ForeignKey): m = field.rel.model t = m.get_default_table() qs = t.request(request=request).data_iterator # logger.info('20120710 choices_view(FK) %s --> %s', t, qs.query)
def row2dict(obj, d): d[constants.CHOICES_TEXT_FIELD] = holder.get_choices_text( obj, request, field) d[constants.CHOICES_VALUE_FIELD] = obj.pk return d else: raise http.Http404("No choices for %s" % field) return (qs, row2dict)
quick_search = request.GET.get(constants.URL_PARAM_FILTER, None) if quick_search is not None: qs = dbtables.add_quick_search_filter(qs, quick_search)
count = len(qs)
offset = request.GET.get(constants.URL_PARAM_START, None) if offset: qs = qs[int(offset):] #~ kw.update(offset=int(offset)) limit = request.GET.get(constants.URL_PARAM_LIMIT, None) if limit: #~ kw.update(limit=int(limit)) qs = qs[:int(limit)]
rows = [row2dict(row, {}) for row in qs] if emptyValue is not None: # 20121203 empty = dict() empty[constants.CHOICES_TEXT_FIELD] = emptyValue empty[constants.CHOICES_VALUE_FIELD] = None rows.insert(0, empty) return json_response_kw(count=count, rows=rows) #~ return json_response_kw(count=len(rows),rows=rows) #~ return json_response_kw(count=len(rows),rows=rows,title=_('Choices for %s') % fldname)
# Examples: `welfare.pcsw.CreateCoachingVisit` actor = requested_actor(app_label, actor) ba = actor.get_url_action(an) if ba is None: raise Exception("Unknown action %r for %s" % (an, actor)) field = ba.action.get_param_elem(field) qs, row2dict = choices_for_field(request, ba.action, field) if field.blank: emptyValue = '<br/>' else: emptyValue = None return choices_response(request, qs, row2dict, emptyValue)
#~ def choices_view(self,request,app_label=None,rptname=None,fldname=None,**kw): """ Return a JSON object with two attributes `count` and `rows`, where `rows` is a list of `(display_text, value)` tuples. Used by ComboBoxes or similar widgets. If `fldname` is not specified, returns the choices for the `record_selector` widget. """ rpt = requested_actor(app_label, rptname) emptyValue = None if fldname is None: ar = rpt.request(request=request) # ,rpt.default_action) #~ rh = rpt.get_handle(self) #~ ar = ViewReportRequest(request,rh,rpt.default_action) #~ ar = dbtables.TableRequest(self,rpt,request,rpt.default_action) #~ rh = ar.ah #~ qs = ar.get_data_iterator() qs = ar.data_iterator #~ qs = rpt.request(self).get_queryset()
def row2dict(obj, d): d[constants.CHOICES_TEXT_FIELD] = str(obj) # getattr(obj,'pk') d[constants.CHOICES_VALUE_FIELD] = obj.pk return d else: """ NOTE: if you define a *parameter* with the same name as some existing *data element* name, then the parameter will override the data element. At least here in choices view. """ #~ field = find_field(rpt.model,fldname) field = rpt.get_param_elem(fldname) if field is None: field = rpt.get_data_elem(fldname) if field.blank: #~ logger.info("views.Choices: %r is blank",field) emptyValue = '<br/>' qs, row2dict = choices_for_field(request, rpt, field)
return choices_response(request, qs, row2dict, emptyValue)
""" Used to collaborate with a restful Ext.data.Store. """
rpt = requested_actor(app_label, actor) ar = rpt.request(request=request)
instance = ar.create_instance() # store uploaded files. # html forms cannot send files with PUT or GET, only with POST if ar.actor.handle_uploaded_files is not None: ar.actor.handle_uploaded_files(instance, request)
data = request.POST.get('rows') data = json.loads(data) ar.form2obj_and_save(data, instance, True)
# Ext.ensible needs list_fields, not detail_fields ar.set_response( rows=[ar.ah.store.row2dict( ar, instance, ar.ah.store.list_fields)]) return json_response(ar.response)
rpt = requested_actor(app_label, actor) ar = rpt.request(request=request) ar.set_selected_pks(pk) return delete_element(ar, ar.selected_rows[0])
rpt = requested_actor(app_label, actor) assert pk is None, 20120814 ar = rpt.request(request=request) rh = ar.ah rows = [ rh.store.row2dict(ar, row, rh.store.list_fields) for row in ar.sliced_data_iterator] kw = dict(count=ar.get_total_count(), rows=rows) kw.update(title=str(ar.get_title())) return json_response(kw)
rpt = requested_actor(app_label, actor) ar = rpt.request(request=request) ar.set_selected_pks(pk) elem = ar.selected_rows[0] rh = ar.ah
data = http.QueryDict(request.body).get('rows') data = json.loads(data) a = rpt.get_url_action(rpt.default_list_action_name) ar = rpt.request(request=request, action=a) ar.renderer = settings.SITE.kernel.extjs_renderer ar.form2obj_and_save(data, elem, False) # Ext.ensible needs list_fields, not detail_fields ar.set_response( rows=[rh.store.row2dict(ar, elem, rh.store.list_fields)]) return json_response(ar.response)
rpt.default_elem_action_name) raise http.Http404("%s has no action %r" % (rpt, action_name))
#~ ar = ba.request(request=request,selected_pks=[pk]) #~ print 20131004, ba.actor
else: ar = ba.request(request=request) elem = None
constants.URL_PARAM_FORMAT, ba.action.default_format)
elem = ar.create_instance() datarec = ar.elem2rec_insert(ah, elem) elem = ar.create_instance() datarec = elem2rec_empty(ar, ah, elem) datarec = dict( success=False, message=NOT_FOUND % (rpt, pk)) else:
after_show = ar.get_status(record_id=pk) tab = request.GET.get(constants.URL_PARAM_TAB, None) if tab is not None: tab = int(tab) after_show.update(active_tab=tab)
return http.HttpResponse( ui.extjs_renderer.html_page( request, ba.action.label, on_ready=ui.extjs_renderer.action_call( request, ba, after_show)))
if isinstance(ba.action, actions.RedirectAction): target = ba.action.get_target_url(elem) if target is None: raise http.Http404("%s failed for %r" % (ba, elem)) return http.HttpResponseRedirect(target)
if pk == '-99998': assert elem is None elem = ar.create_instance() ar.selected_rows = [elem] elif elem is None: raise http.Http404(NOT_FOUND % (rpt, pk)) return settings.SITE.kernel.run_action(ar)
ar = action_request( app_label, actor, request, request.POST, True, renderer=settings.SITE.kernel.extjs_renderer) if pk == '-99998': elem = ar.create_instance() ar.selected_rows = [elem] else: ar.set_selected_pks(pk) return settings.SITE.kernel.run_action(ar)
data = http.QueryDict(request.body) # raw_post_data before Django 1.4 # logger.info("20150130 %s", data) ar = action_request( app_label, actor, request, data, False, renderer=settings.SITE.kernel.extjs_renderer) ar.set_selected_pks(pk) return settings.SITE.kernel.run_action(ar)
data = http.QueryDict(request.body) ar = action_request( app_label, actor, request, data, False, renderer=settings.SITE.kernel.extjs_renderer) ar.set_selected_pks(pk) return settings.SITE.kernel.run_action(ar)
rpt = requested_actor(app_label, actor) ar = rpt.request(request=request) ar.set_selected_pks(pk) elem = ar.selected_rows[0] return delete_element(ar, elem)
ar = action_request(app_label, actor, request, request.POST, True) ar.renderer = settings.SITE.kernel.extjs_renderer return settings.SITE.kernel.run_action(ar)
constants.URL_PARAM_FORMAT, ar.bound_action.action.default_format)
for row in ar.sliced_data_iterator] rows=rows, success=True, no_data_text=ar.no_data_text, title=str(ar.get_title())) kw.update( param_values=ar.actor.params_layout.params_store.pv2dict( ar.param_values))
if fmt == constants.URL_FORMAT_HTML: after_show = ar.get_status()
sp = request.GET.get( constants.URL_PARAM_SHOW_PARAMS_PANEL, None) if sp is not None: #~ after_show.update(show_params_panel=sp) after_show.update( show_params_panel=constants.parse_boolean(sp))
# if isinstance(ar.bound_action.action, actions.InsertRow): # elem = ar.create_instance() # rec = ar.elem2rec_insert(rh, elem) # after_show.update(data_record=rec)
kw = dict(on_ready= ar.renderer.action_call( ar.request, ar.bound_action, after_show)) #~ print '20110714 on_ready', params kw.update(title=ar.get_title()) return http.HttpResponse(ar.renderer.html_page(request, **kw))
if fmt == 'csv': #~ response = HttpResponse(mimetype='text/csv') charset = settings.SITE.csv_params.get('encoding', 'utf-8') response = http.HttpResponse( content_type='text/csv;charset="%s"' % charset) if False: response['Content-Disposition'] = \ 'attachment; filename="%s.csv"' % ar.actor else: #~ response = HttpResponse(content_type='application/csv') response['Content-Disposition'] = \ 'inline; filename="%s.csv"' % ar.actor
#~ response['Content-Disposition'] = 'attachment; filename=%s.csv' % ar.get_base_filename() w = ucsv.UnicodeWriter(response, **settings.SITE.csv_params) w.writerow(ar.ah.store.column_names()) if True: # 20130418 : also column headers, not only internal names column_names = None fields, headers, cellwidths = ar.get_field_info(column_names) w.writerow(headers)
for row in ar.data_iterator: w.writerow([str(v) for v in rh.store.row2list(ar, row)]) return response
if fmt == constants.URL_FORMAT_PRINTER: if ar.get_total_count() > MAX_ROW_COUNT: raise Exception(_("List contains more than %d rows") % MAX_ROW_COUNT) response = http.HttpResponse( content_type='text/html;charset="utf-8"') doc = xghtml.Document(force_text(ar.get_title())) doc.body.append(E.h1(doc.title)) t = doc.add_table() #~ settings.SITE.kernel.ar2html(ar,t,ar.data_iterator) ar.dump2html(t, ar.data_iterator) doc.write(response, encoding='utf-8') return response
return settings.SITE.kernel.run_action(ar)
rpt = requested_actor(app_label, actor) PUT = http.QueryDict(request.body) # raw_post_data before Django 1.4 gc = dict( widths=[int(x) for x in PUT.getlist(constants.URL_PARAM_WIDTHS)], columns=[str(x) for x in PUT.getlist(constants.URL_PARAM_COLUMNS)], hiddens=[(x == 'true') for x in PUT.getlist(constants.URL_PARAM_HIDDENS)], #~ hidden_cols=[str(x) for x in PUT.getlist('hidden_cols')], )
filter = PUT.get('filter', None) if filter is not None: filter = json.loads(filter) gc['filters'] = [constants.dict2kw(flt) for flt in filter]
name = PUT.get('name', None) if name is None: name = constants.DEFAULT_GC_NAME else: name = int(name)
gc.update(label=PUT.get('label', "Standard")) try: msg = rpt.save_grid_config(name, gc) except IOError as e: msg = _("Error while saving GC for %(table)s: %(error)s") % dict( table=rpt, error=e) return settings.SITE.kernel.error(None, msg, alert=True) #~ logger.info(msg) settings.SITE.kernel.extjs_renderer.build_site_cache(True) return settings.SITE.kernel.success(msg)
|