def fill_output(self, output, choices, str_values, label_list): if len(choices): output.append(u'<ul>') for (option_value, option_label, children) in choices: option_value = force_unicode(option_value) option_label = conditional_escape(force_unicode(option_label)) children_output = [] self.fill_output(children_output, children, str_values, label_list) classes = [] if children_output: classes.append('jstree-open') if option_value in str_values: classes.append('jstree-checked') label_list.append(option_label) output.append(u'<li value="%s" label="%s" class="%s"><a href="javascript:void(0);">%s</a>' % \ (option_value, option_label, " ".join(classes), option_label)) if children_output: output.extend(children_output) output.append(u'</li>') output.append(u'</ul>')
def do_action(self, queryset): if not self.has_change_permission(): raise PermissionDenied change_fields = [ f for f in self.request.POST.getlist(BATCH_CHECKBOX_NAME) if f in self.batch_fields ] if change_fields and self.request.POST.get('post'): self.form_obj = self.get_change_form(True, change_fields)( data=self.request.POST, files=self.request.FILES) if self.form_obj.is_valid(): self.change_models(queryset, self.form_obj.cleaned_data) return None else: self.form_obj = self.get_change_form(False, self.batch_fields)() helper = FormHelper() helper.form_tag = False helper.include_media = False helper.add_layout( Layout( Container( Col('full', Fieldset("", *self.form_obj.fields.keys(), css_class="unsort no_title"), horizontal=True, span=12)))) self.form_obj.helper = helper count = len(queryset) if count == 1: objects_name = force_unicode(self.opts.verbose_name) else: objects_name = force_unicode(self.opts.verbose_name_plural) context = self.get_context() context.update({ "title": _("Batch change %s") % objects_name, 'objects_name': objects_name, 'form': self.form_obj, 'queryset': queryset, 'count': count, "opts": self.opts, "app_label": self.app_label, 'action_checkbox_name': ACTION_CHECKBOX_NAME, }) return TemplateResponse( self.request, self.batch_change_form_template or self.get_template_list('views/batch_change_form.html'), context)
def post_response(self): """ 删除成功后的操作。首先提示用户信息,而后根据用户权限做跳转,如果用户有列表产看权限就跳转到列表页面,否则跳到网站首页。 """ self.message_user( _('The %(name)s "%(obj)s" was deleted successfully.') % { 'name': force_unicode(self.opts.verbose_name), 'obj': force_unicode(self.obj) }, 'success') if not self.has_view_permission(): return self.get_admin_url('index') return self.model_admin_url('changelist')
def render(self, name, value, attrs=None): if value is None: value = '' final_attrs = self.build_attrs(attrs, name=name) final_attrs['class'] = 'nav nav-pills nav-stacked' output = [u'<ul%s>' % dutils.flatatt(final_attrs)] options = self.render_options(force_unicode(value), final_attrs['id']) if options: output.append(options) output.append(u'</ul>') output.append( '<input type="hidden" id="%s_input" name="%s" value="%s"/>' % (final_attrs['id'], name, force_unicode(value))) return mark_safe(u'\n'.join(output))
def get_context(self): """ **Context Params** : ``model_fields`` : 用于 ``选择显示列`` 功能, 保存所有可显示的列信息 ``result_headers`` : 显示列表的头部信息, 是 :class:`ResultHeader` 列表 ``results`` : 显示列表的内容信息, 是 :class:`ResultItem` 列表 """ if hasattr(self, 'verbose_name'): self.opts.verbose_name = self.verbose_name self.opts.verbose_name_plural = self.verbose_name self.title = _('%s') % force_unicode(self.opts.verbose_name) # 获取所有可供显示的列的信息 model_fields = [ (f, f.name in self.list_display, self.get_check_field_url(f)) for f in (list(self.opts.fields) + self.get_model_method_fields()) if f.name not in self.list_exclude ] new_context = { 'module_name': force_unicode(self.opts.verbose_name_plural), 'title': self.title, 'cl': self, 'model_fields': self.get_model_fields(), 'clean_select_field_url': self.get_query_string(remove=[COL_LIST_VAR]), 'has_add_permission': self.has_add_permission(), 'app_label': self.app_label, 'brand_name': self.opts.verbose_name_plural, 'brand_icon': self.get_model_icon(self.model), 'add_url': self.model_admin_url('add'), 'result_headers': self.result_headers(), 'results': self.results(), 'nav_buttons': mark_safe(' '.join(self.get_nav_btns())), } if self.list_tabs: cur_tab = self.request.GET.get('_tab', '0') new_context['cur_tab'] = int(cur_tab) context = super(ListAdminView, self).get_context() context.update(new_context) if self.pop: if self.admin_site.ext_ui: context['base_template'] = 'xadmin/base_pure_ext.html' else: context['base_template'] = 'xadmin/base_pure.html' return context
def do_action(self, queryset): # 检查是否有删除权限 if not self.has_delete_permission(): raise PermissionDenied using = router.db_for_write(self.model) # Populate deletable_objects, a data structure of all related objects that # will also be deleted. deletable_objects, perms_needed, protected = get_deleted_objects( queryset, self.opts, self.user, self.admin_site, using) # The user has already confirmed the deletion. # Do the deletion and return a None to display the change list view again. if self.request.POST.get('post'): if perms_needed: raise PermissionDenied self.delete_models(queryset) # Return None to display the change list page again. return None # GET请求 删除确认页面 if len(queryset) == 1: objects_name = force_unicode(self.opts.verbose_name) else: objects_name = force_unicode(self.opts.verbose_name_plural) if perms_needed or protected: title = _("Cannot delete %(name)s") % {"name": objects_name} else: title = _("Are you sure?") context = self.get_context() context.update({ "title": title, "objects_name": objects_name, "deletable_objects": [deletable_objects], 'queryset': queryset, "perms_lacking": perms_needed, "protected": protected, "opts": self.opts, "app_label": self.app_label, 'action_checkbox_name': ACTION_CHECKBOX_NAME, }) return TemplateResponse( self.request, self.delete_selected_confirmation_template or self.get_template_list('views/model_delete_selected_confirm.html'), context)
def get_breadcrumb(self): bcs = super(DetailAdminView, self).get_breadcrumb() item = {'title': force_unicode(self.obj)} if self.has_view_permission(): item['url'] = self.model_admin_url('detail', self.obj.pk) bcs.append(item) return bcs
def get_breadcrumb(self, bcs): u''' 导航链接基础部分 ''' if self.admin_site.head_fix: return [] base = [{ 'url': self.get_admin_url('index'), 'title': _('Home') }] to_model = self.relate_obj.to_model model_admin = self.admin_site._registry[to_model] app_label = getattr(model_admin, 'app_label', to_model._meta.app_label) app_mod = self.admin_site.app_dict[app_label] base.append({ 'url': app_mod.index_url, 'title': hasattr(app_mod,'verbose_name') and app_mod.verbose_name or app_label }) item = {} opts = to_model._meta item = {'title': opts.verbose_name_plural} item['url'] = self.admin_view.get_model_url(to_model,'changelist') base.append(item) to_objs = self.relate_obj.to_objs if len(to_objs) == 1: to_model_name = str(to_objs[0]) else: to_model_name = force_unicode(to_model._meta.verbose_name) base.append({'title': to_model_name,'url':''}) return base
def get_context(self): """ **Context Params**: ``title`` : 确认删除的标题,如果您没有权限删除的话,会提示无法删除 ``object`` : 要被删除的对象 ``deleted_objects`` : 关联被删除的所有数据对象 ``perms_lacking`` : 缺少的权限 ``protected`` : 被保护的数据,无法被删除的数据对象 """ if self.perms_needed or self.protected: title = _("Cannot delete %(name)s") % { "name": force_unicode(self.opts.verbose_name) } else: title = _("Are you sure?") new_context = { "title": title, "object": self.obj, "deleted_objects": self.deleted_objects, "perms_lacking": self.perms_needed, "protected": self.protected, } context = super(DeleteAdminView, self).get_context() context.update(new_context) return context
def get_breadcrumb(self): bcs = super(ModelFormAdminView, self).get_breadcrumb() item = {'title': _('Add %s') % force_unicode(self.opts.verbose_name)} if self.has_add_permission(): item['url'] = self.model_admin_url('add') bcs.append(item) return bcs
def get(self, request, name): if name not in self.data_charts: return HttpResponseNotFound() self.chart = self.data_charts[name] self.x_field = self.chart['x-field'] y_fields = self.chart['y-field'] self.y_fields = (y_fields, ) if type(y_fields) not in ( list, tuple) else y_fields datas = [{ "data": [], "label": force_unicode(label_for_field(i, self.model, model_admin=self)) } for i in self.y_fields] self.make_result_list() for obj in self.result_list: xf, attrs, value = lookup_field(self.x_field, obj, self) for i, yfname in enumerate(self.y_fields): yf, yattrs, yv = lookup_field(yfname, obj, self) datas[i]["data"].append((value, yv)) option = { 'series': { 'lines': { 'show': True }, 'points': { 'show': False } }, 'grid': { 'hoverable': True, 'clickable': True } } try: xfield = self.opts.get_field(self.x_field) if type(xfield) in (models.DateTimeField, models.DateField, models.TimeField): option['xaxis'] = {'mode': "time", 'tickLength': 5} if type(xfield) is models.DateField: option['xaxis']['timeformat'] = "%y/%m/%d" elif type(xfield) is models.TimeField: option['xaxis']['timeformat'] = "%H:%M:%S" else: option['xaxis']['timeformat'] = "%y/%m/%d %H:%M:%S" except Exception: pass option.update(self.chart.get('option', {})) content = {'data': datas, 'option': option} result = json.dumps(content, cls=JSONEncoder, ensure_ascii=False) return HttpResponse(result)
def label(self): text = mark_safe(self.text) if self.allow_tags else conditional_escape( self.text) if dutils.force_unicode(text) == '': text = mark_safe(' ') for wrap in self.wraps: text = mark_safe(wrap % text) return text
def get_breadcrumb(self): bcs = super(ModelFormAdminView, self).get_breadcrumb() item = {'title': force_unicode(self.org_obj)} if self.has_change_permission(): item['url'] = self.model_admin_url('change', self.org_obj.pk) bcs.append(item) return bcs
def post_response(self): self.message_user( _('The %(model)s "%(name)s" was recovered successfully. You may edit it again below.' ) % { "model": force_unicode(self.opts.verbose_name), "name": unicode(self.new_obj) }, 'success') return HttpResponseRedirect( self.model_admin_url('change', self.new_obj.pk))
def model_format_dict(obj): """ Return a `dict` with keys 'verbose_name' and 'verbose_name_plural', typically for use with string formatting. `obj` may be a `Model` instance, `Model` subclass, or `QuerySet` instance. """ if isinstance(obj, (models.Model, models.base.ModelBase)): opts = obj._meta elif isinstance(obj, models.query.QuerySet): opts = obj.model._meta else: opts = obj return { 'verbose_name': force_unicode(opts.verbose_name), 'verbose_name_plural': force_unicode(opts.verbose_name_plural) }
def _get_objects(self, context): headers = [c for c in context['result_headers'].cells if c.export] rows = context['results'] return [ dict([(force_unicode(headers[i].text), self._format_value(o)) for i, o in enumerate( filter(lambda c: getattr(c, 'export', False), r.cells))]) for r in rows ]
def val(self): text = mark_safe(self.text) if self.allow_tags else conditional_escape( self.text) if force_unicode( text ) == '' or text == 'None' or text == EMPTY_CHANGELIST_VALUE: text = mark_safe('<span class="text-muted">%s</span>' % EMPTY_CHANGELIST_VALUE) for wrap in self.wraps: text = mark_safe(wrap % text) return text
def get_context(self): new_context = { "opts": self.opts, "app_label": self.app_label, "module_name": self.module_name, "verbose_name": force_unicode(self.opts.verbose_name), 'model_icon': self.get_model_icon(self.model), } context = super(ModelAdminView, self).get_context() context.update(new_context) return context
def _get_datas(self, context): rows = context['results'] new_rows = [[ self._format_value(o) for o in filter(lambda c: getattr(c, 'export', False), r.cells) ] for r in rows] new_rows.insert(0, [ force_unicode(c.text) for c in context['result_headers'].cells if c.export ]) return new_rows
def get_context(self): """ **Context Params**: ``title`` : 表单标题 """ new_context = { 'title': _('Add %s') % force_unicode(self.opts.verbose_name), } context = super(CreateAdminView, self).get_context() context.update(new_context) return context
def get_breadcrumb(self): bcs = super(DeleteAdminView, self).get_breadcrumb() bcs.append({ 'title': force_unicode(self.obj), 'url': self.get_object_url(self.obj) }) item = {'title': _('Delete')} if self.has_delete_permission(): item['url'] = self.model_admin_url('delete', self.obj.pk) bcs.append(item) return bcs
def render(self, name, value, attrs=None, choices=()): if value is None: value = [] if self.base_css == 'admin-fk-tree-leaf': _base_css = "admin-fk-tree leaf" else: _base_css = self.base_css if attrs: attrs['class'] = attrs.get('class', '') + ' %s open' % _base_css else: attrs['class'] = '%s open' % _base_css final_attrs = self.build_attrs(attrs, name=name) label_list = [] output = [ u'<div class="dropdown-menu jstree-container"><input type="search" placeholder="Search" id="jstree-search"></input><div%s role="combobox">' % dutils.flatatt(final_attrs) ] # Normalize to strings if self.base_css == 'admin-m2m-tree': str_values = set([force_unicode(v) for v in value]) else: if value: str_values = [force_unicode(value)] else: str_values = [] self.fill_output(output, self.choices, str_values, label_list) raw_str = '' if self.base_css in ['admin-fk-tree', 'admin-fk-tree-leaf']: raw_str = '<input type="hidden" id="id_%s" name="%s" value="%s"></input>' % ( name, name, str_values and str_values.pop() or '') output.append(u'</div></div>') wapper = ''' <div class="dropdown">%s <button type="button" class="btn dropdown-toggle btn-default bs-placeholder" data-toggle="dropdown" role="button" title="点击下拉选择" aria-expanded="true"><span class="filter-option pull-left">%s</span> <span class="bs-caret"><span class="caret"></span></span></button> ''' % (raw_str, (', '.join(label_list) or '请选择...')) output.insert(0, wapper) output.append(u'</div>') return mark_safe(u'\n'.join(output))
def init_request(self, object_id, *args, **kwargs): self.org_obj = self.get_object(unquote(object_id)) if not self.has_change_permission(self.org_obj): raise PermissionDenied if self.org_obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.') % { 'name': dutils.force_unicode(self.opts.verbose_name), 'key': escape(object_id) })
def get_xlsx_export(self, context): u''' 导出 xlsx ''' datas = self._get_datas(context) output = StringIO.StringIO() export_header = (self.request.GET.get('export_xlsx_header', 'off') == 'on') model_name = self.opts.verbose_name book = xlsxwriter.Workbook(output) sheet = book.add_worksheet(u"%s %s" % (_(u'Sheet'), force_unicode(model_name))) styles = { 'datetime': book.add_format({'num_format': 'yyyy-mm-dd hh:mm:ss'}), 'date': book.add_format({'num_format': 'yyyy-mm-dd'}), 'time': book.add_format({'num_format': 'hh:mm:ss'}), 'header': book.add_format({ 'font': 'name Times New Roman', 'color': 'red', 'bold': 'on', 'num_format': '#,##0.00' }), 'default': book.add_format() } if not export_header: datas = datas[1:] for rowx, row in enumerate(datas): for colx, value in enumerate(row): if export_header and rowx == 0: cell_style = styles['header'] else: if isinstance(value, datetime.datetime): cell_style = styles['datetime'] elif isinstance(value, datetime.date): cell_style = styles['date'] elif isinstance(value, datetime.time): cell_style = styles['time'] else: cell_style = styles['default'] sheet.write(rowx, colx, value, cell_style) book.close() output.seek(0) return output.getvalue()
def label_for_field(name, model, model_admin=None, return_attr=False): """ Returns a sensible label for a field name. The name can be a callable or the name of an object attributes, as well as a genuine fields. If return_attr is True, the resolved attribute (which could be a callable) is also returned. This will be None if (and only if) the name refers to a field. """ name_split = name.split('.') name = name_split[0] attr = None try: field = model._meta.get_field_by_name(name)[0] if isinstance(field, RelatedObject): label = field.opts.verbose_name else: label = field.verbose_name except models.FieldDoesNotExist: if name == "__unicode__": label = force_unicode(model._meta.verbose_name) attr = unicode elif name == "__str__": label = smart_str(model._meta.verbose_name) attr = str else: if callable(name): attr = name elif model_admin is not None and hasattr(model_admin, name): attr = getattr(model_admin, name) elif hasattr(model, name): attr = getattr(model, name) else: message = "Unable to lookup '%s' on %s" % ( name, model._meta.object_name) if model_admin: message += " or %s" % (model_admin.__class__.__name__, ) raise AttributeError(message) if hasattr(attr, "short_description"): label = attr.short_description elif callable(attr): if attr.__name__ == "<lambda>": label = "--" else: label = pretty_name(attr.__name__) else: label = pretty_name(name) if return_attr: return (label, attr) else: return label
def post_response(self): """ 当成功保存数据后,会调用该方法返回 HttpResponse 或跳转地址 """ request = self.request msg = _('The %(name)s "%(obj)s" was added successfully.') % { 'name': force_unicode(self.opts.verbose_name), 'obj': force_unicode(self.new_obj) } param_list = self.param_list() if "_continue" in param_list: self.message_user(msg + ' ' + _("You may edit it again below."), 'success') # 继续编辑 return self.model_admin_url('change', self.new_obj._get_pk_val()) if "_addanother" in param_list: self.message_user( msg + ' ' + (_("You may add another %s below.") % force_unicode(self.opts.verbose_name)), 'success') # 返回添加页面添加另外一个 return request.path else: self.message_user(msg, 'success') # 如果没有查看列表的权限就跳转到主页 if "_redirect" in param_list: return self.get_param('_redirect') elif self.has_view_permission(): if self.add_redirect_url: return self.add_redirect_url % self.new_obj._get_pk_val() else: return self.model_admin_url('changelist') else: return self.get_admin_url('index')
def get_context(self): context = super(RevisionListView, self).get_context() opts = self.opts action_list = [{ "revision": version.revision, "url": self.model_admin_url('revision', quote(version.object_id), version.id), "version": version } for version in self._order_version_queryset( self.revision_manager.get_for_object_reference( self.model, self.obj.pk, ).select_related("revision__user"))] context.update({ 'title': _('Change history: %s') % force_unicode(self.obj), 'action_list': action_list, 'module_name': capfirst(force_unicode(opts.verbose_name_plural)), 'object': self.obj, 'app_label': opts.app_label, "changelist_url": self.model_admin_url("changelist"), "update_url": self.model_admin_url("change", self.obj.pk), 'opts': opts, }) return context
def post_response(self): """ 当成功修改数据后,会调用该方法返回 HttpResponse 或跳转地址 """ opts = self.new_obj._meta obj = self.new_obj request = self.request verbose_name = opts.verbose_name pk_value = obj._get_pk_val() msg = _('The %(name)s "%(obj)s" was changed successfully.') % { 'name': force_unicode(verbose_name), 'obj': force_unicode(obj) } param_list = self.param_list() if "_continue" in param_list: self.message_user(msg + ' ' + _("You may edit it again below."), 'success') # 返回原页面继续编辑 return request.path elif "_addanother" in param_list: self.message_user( msg + ' ' + (_("You may add another %s below.") % force_unicode(verbose_name)), 'success') return self.model_admin_url('add') else: self.message_user(msg, 'success') # 如果没有查看列表的权限就跳转到主页 if "_redirect" in param_list: return self.get_param('_redirect') elif self.has_view_permission(): change_list_url = self.model_admin_url('changelist') return change_list_url else: return self.get_admin_url('index')
def get_context(self): """ **Context Params**: ``title`` : 表单标题 ``object_id`` : 修改的数据对象的 id """ new_context = { 'title': _('Change %s') % force_unicode(self.org_obj), 'object_id': str(self.org_obj.pk), 'cl': self } context = super(UpdateAdminView, self).get_context() context.update(new_context) return context
def get_context(self): context = super(RecoverListView, self).get_context() opts = self.opts deleted = self._order_version_queryset( self.revision_manager.get_deleted(self.model)) context.update({ "opts": opts, "app_label": opts.app_label, "module_name": capfirst(opts.verbose_name), "title": _("Recover deleted %(name)s") % { "name": force_unicode(opts.verbose_name_plural) }, "deleted": deleted, "changelist_url": self.model_admin_url("changelist"), }) return context