def add_json_view(self, request, form_url='', extra_context=None): "The 'add' admin view for this model. Communicating with client in JSON format only." if request.method.upper() != 'POST': msg = _( 'This view is designed for saving data only, thus POST method is required.' ) return HttpResponseForbidden(msg) context = self.get_add_view_context(request, form_url) context.update(extra_context or {}) if 'object_added' in context: obj = context['object'] msg = unicode(list(messages.get_messages(request))[0]) if request.FILES and not request.is_ajax(): return_url = '%s#/%s/%s/' % (reverse('newman:index'), obj._meta.app_label, obj._meta.module_name) if request.POST.get('_continue'): return_url += '%s/' % obj.pk if request.POST.get('_addanother'): return_url += 'add/' return HttpResponseRedirect(return_url) return utils.JsonResponse( msg, { 'id': obj.pk, 'title': getattr(obj, '__unicode__', obj.__str__)(), }) elif 'error_dict' in context: return self.json_error_response(request, context)
def delete_draft_view(self, request, extra_context=None): self.register_newman_variables(request) id = request.GET.get('id', None) if not id: return utils.JsonResponse( _('No id found in GET variable "id".'), status=newman_settings.STATUS_VAR_MISSING) try: draft = AdminUserDraft.objects.get(ct=self.model_content_type, user=request.user, pk=id) except AdminUserDraft.DoesNotExist: return utils.JsonResponse( _('No matching draft found.'), status=newman_settings.STATUS_OBJECT_NOT_FOUND) msg = _('Draft %s was deleted.' % draft.__unicode__()) draft.delete() return utils.JsonResponse(msg)
def load_draft_view(self, request, extra_context=None): """ Returns draft identified by request.GET['id'] variable. """ self.register_newman_variables(request) id = request.GET.get('id', None) if not id: return utils.JsonResponse( _('No id found in GET variable "id".'), status=newman_settings.STATUS_VAR_MISSING) drafts = AdminUserDraft.objects.filter(ct=self.model_content_type, user=request.user, pk=id) if not drafts: return utils.JsonResponse( _('No matching draft found.'), status=newman_settings.STATUS_OBJECT_NOT_FOUND) draft = drafts[0] return utils.JsonResponse(_('Loaded draft "%s"' % draft.__unicode__()), draft.data)
def model_detail_json_view(self, request, object_id, extra_context=None): " Outputs basic object's data. " obj = None try: obj = self.queryset(request).get(pk=unquote(object_id)) except obj.DoesNotExist: obj = None if not self.has_model_view_permission(request, obj): raise PermissionDenied result_dict = dict() for field in obj._meta.fields: result_dict[field.name] = field.value_to_string(obj) return utils.JsonResponse('JSON object detail data.', result_dict, status=newman_settings.STATUS_OK)
def save_draft_view(self, request, extra_context=None): """ Autosave data (dataloss-prevention) or save as (named) template """ def delete_too_old_drafts(): " remove autosaves too old to rock'n'roll " to_delete = AdminUserDraft.objects.filter( title__exact='', user=request.user).order_by('-ts') for draft in to_delete[newman_settings.AUTOSAVE_MAX_AMOUNT:]: log.debug('Deleting too old user draft (autosave) %d' % draft.pk) draft.delete() self.register_newman_variables(request) data = request.POST.get('data', None) if not data: return utils.JsonResponseError( _('No data passed in POST variable "data".'), status=newman_settings.STATUS_VAR_MISSING) title = request.POST.get('title', '') id = request.POST.get('id', None) if id: # modifying existing draft/preset try: obj = AdminUserDraft.objects.get(pk=id) obj.data = data obj.title = title obj.save() except AdminUserDraft.DoesNotExist: obj = AdminUserDraft.objects.create(ct=self.model_content_type, user=request.user, data=data, title=title) else: obj = AdminUserDraft.objects.create(ct=self.model_content_type, user=request.user, data=data, title=title) delete_too_old_drafts() data = {'id': obj.pk, 'title': obj.__unicode__()} return utils.JsonResponse( _('Preset %s was saved.' % obj.__unicode__()), data)
def change_json_view(self, request, object_id, extra_context=None): "The 'change' admin view for this model." if request.method.upper() != 'POST': msg = _( 'This view is designed for saving data only, thus POST method is required.' ) return HttpResponseForbidden(msg) context = self.change_view_prepare_context(request, object_id) if type(context) != dict: obj = self.get_change_view_object(object_id) opts = obj._meta if request.FILES and not request.is_ajax(): return_url = '%s#/%s/%s/' % (reverse('newman:index'), opts.app_label, opts.module_name) if request.POST.get('_continue'): return_url += '%s/' % object_id if request.POST.get('_addanother'): return_url += 'add/' return HttpResponseRedirect(return_url) redir = request.POST.get('http_redirect_to', None) if redir: return utils.JsonResponseRedirect(redir) return utils.JsonResponse( _('The %(name)s "%(obj)s" was changed successfully.') % { 'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj) }, { 'id': obj.pk, 'title': obj.__unicode__(), }, status=newman_settings.STATUS_OK) context.update(extra_context or {}) return self.json_error_response(request, context) # Json response
def json_error_response(self, request, context): """ Chyby v polich formulare Chyba v poli formulare napr.: context['adminform'].form['slug'].errors Chyba v poli inline napr.: context['inline_admin_formsets'][0].formset.errors tj.: [{'content': [u'Toto pole je povinn\xe9.']}] id inline v sablone: id_ + context['inline_admin_formsets'][0].formset.prefix + [poradove cislo formsetu tj. 0 + jmeno sloupce priklad id: id_articlecontents_set-0-content """ fcounter = {} def get_formset_counter(fset): if fset not in fcounter: fcounter[fset] = 0 else: fcounter[fset] += 1 return fcounter[fset] def give_me_unicode(ei): if not hasattr(ei, '__unicode__'): return u'%s' % ei return ei.__unicode__() error_list = [] # Form fields frm = context['adminform'].form for field_name in frm.fields: field = frm[field_name] if field.errors: err_dict = { 'id': u"id_%s" % field_name, 'label': u"%s" % field.label, 'messages': map(lambda item: u'%s' % item, map(give_me_unicode, field.errors)) } error_list.append(err_dict) # Inline Form fields for fset in context['inline_admin_formsets']: for err_item in fset.formset.errors: counter = get_formset_counter(fset.formset.prefix) for key in err_item: label = u'' """ for mfield in fset.formset.model._meta.fields: if mfield.name == key: label = mfield.verbose_name break """ for fkey, mfield in fset.formset.form.base_fields.items(): if fkey == key: if hasattr(mfield.label, '__unicode__'): label = mfield.label.__unicode__() else: label = mfield.label.__str__() break err_dict = { 'id': u'id_%s-%d-%s' % (fset.formset.prefix, counter, key), 'label': u"%s" % label, 'messages': map(lambda item: item, map(give_me_unicode, err_item[key])) } error_list.append(err_dict) # Other errors (e.g. db errors) if 'error_dict' in context and 'id___all__' in context['error_dict']: error_list.append({ 'messages': context['error_dict']['id___all__'], 'id': 'id___all__', }) return utils.JsonResponse(_('Please correct errors in form'), errors=error_list, status=newman_settings.STATUS_FORM_ERROR)
class NewmanModelAdmin(XModelAdmin): changelist_view_cl = NewmanChangeList actions = None def get_template_list(self, base_template): model = self.model opts = model._meta app_label = opts.app_label return [ "newman/%s/%s/%s" % (app_label, opts.object_name.lower(), base_template), "newman/%s/%s" % (app_label, base_template), "newman/%s" % base_template ] def __init__(self, *args, **kwargs): super(NewmanModelAdmin, self).__init__(*args, **kwargs) # newman's custom templates self.delete_confirmation_template = self.get_template_list( 'delete_confirmation.html') self.delete_selected_confirmation_template = self.get_template_list( 'delete_selected_confirmation.html') self.object_history_template = self.get_template_list( 'object_history.html') self.change_form_template = self.get_template_list('change_form.html') self.change_list_template = self.get_template_list('change_list.html') self.filters_template = self.get_template_list('filters.html') self.list_per_page = newman_settings.DEFAULT_LIST_PER_PAGE self.model_content_type = ContentType.objects.get_for_model(self.model) self.saveasnew_add_view = self.add_json_view # useful when self.queryset(request) is called multiple times self._cached_queryset_request_id = -1 self._cached_queryset = None def _media(self): js = [] if self.actions is not None: js.extend(['js/actions.min.js']) if self.prepopulated_fields: js.append('js/urlify.js') js.append('js/prepopulate.min.js') if self.opts.get_ordered_objects(): js.extend([ 'js/getElementsBySelector.js', 'js/dom-drag.js', 'js/admin/ordering.js' ]) return forms.Media( js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js]) media = property(_media) def get_form(self, request, obj=None, **kwargs): self._magic_instance = obj # adding edited object to ModelAdmin instance. return super(NewmanModelAdmin, self).get_form(request, obj, **kwargs) def get_urls(self): from django.conf.urls.defaults import patterns, url def wrap(view): def wrapper(*args, **kwargs): return self.admin_site.admin_view(view)(*args, **kwargs) return update_wrapper(wrapper, view) info = self.model._meta.app_label, self.model._meta.module_name urlpatterns = patterns( '', url(r'^suggest/$', wrap(self.suggest_view), name='%s_%s_suggest' % info), url(r'^filters/$', wrap(self.filters_view), name='%s_%s_filters' % info), url(r'^log/$', wrap(self.log_view), name='%s_%s_log' % info), url(r'^(.+)/help/$', wrap(self.model_help_view), name='%s_%s_help' % info), url(r'^(.+)/draft/save/$', wrap(self.save_draft_view), name='%s_%s_save_draft' % info), url(r'^(.+)/draft/load/$', wrap(self.load_draft_view), name='%s_%s_load_draft' % info), url(r'^(.+)/draft/delete/$', wrap(self.delete_draft_view), name='%s_%s_delete_draft' % info), url(r'^add/json/$', wrap(self.add_json_view), name='%s_%s_add_json' % info), url(r'^(.+)/json/$', wrap(self.change_json_view), name='%s_%s_change_json' % info), url(r'^(.+)/json/detail/$', wrap(self.model_detail_json_view), name='%s_%s_json_detail' % info), ) urlpatterns += super(NewmanModelAdmin, self).get_urls() return urlpatterns @require_AJAX def model_help_view(self, request, extra_context=None): """ Returns help for model and his fields. """ base_help_items = AdminHelpItem.objects.filter( ct=self.model_content_type, lang=settings.LANGUAGE_CODE).values() model_help = base_help_items.filter(field='') if model_help: model_help = model_help[0] model_fields = self.model._meta.fields bhi = {} help_total = [] for f in model_fields: if f.editable: bhi[f.name] = { 'verbose_name': f.verbose_name, 'help_text': f.help_text } for h in base_help_items: try: bhi[h['field']].update(h) except KeyError: pass #log.warning('Field %s is not in model %s' % (h['field'], self.model)) for f in model_fields: if f.editable: help_total.append(bhi[f.name]) context = { 'ct': self.model_content_type, 'model_help': model_help, 'model_doc': self.model.__doc__, 'fields_help': help_total, 'inline_help_items': None } return render_to_response( self.get_template_list('model_help.html'), context, context_instance=template.RequestContext(request)) @require_AJAX def save_draft_view(self, request, extra_context=None): """ Autosave data (dataloss-prevention) or save as (named) template """ def delete_too_old_drafts(): " remove autosaves too old to rock'n'roll " to_delete = AdminUserDraft.objects.filter( title__exact='', user=request.user).order_by('-ts') for draft in to_delete[newman_settings.AUTOSAVE_MAX_AMOUNT:]: log.debug('Deleting too old user draft (autosave) %d' % draft.pk) draft.delete() self.register_newman_variables(request) data = request.POST.get('data', None) if not data: return utils.JsonResponseError( _('No data passed in POST variable "data".'), status=newman_settings.STATUS_VAR_MISSING) title = request.POST.get('title', '') id = request.POST.get('id', None) if id: # modifying existing draft/preset try: obj = AdminUserDraft.objects.get(pk=id) obj.data = data obj.title = title obj.save() except AdminUserDraft.DoesNotExist: obj = AdminUserDraft.objects.create(ct=self.model_content_type, user=request.user, data=data, title=title) else: obj = AdminUserDraft.objects.create(ct=self.model_content_type, user=request.user, data=data, title=title) delete_too_old_drafts() data = {'id': obj.pk, 'title': obj.__unicode__()} return utils.JsonResponse( _('Preset %s was saved.' % obj.__unicode__()), data) @require_AJAX def load_draft_view(self, request, extra_context=None): """ Returns draft identified by request.GET['id'] variable. """ self.register_newman_variables(request) id = request.GET.get('id', None) if not id: return utils.JsonResponse( _('No id found in GET variable "id".'), status=newman_settings.STATUS_VAR_MISSING) drafts = AdminUserDraft.objects.filter(ct=self.model_content_type, user=request.user, pk=id) if not drafts: return utils.JsonResponse( _('No matching draft found.'), status=newman_settings.STATUS_OBJECT_NOT_FOUND) draft = drafts[0] return utils.JsonResponse(_('Loaded draft "%s"' % draft.__unicode__()), draft.data) @require_AJAX def delete_draft_view(self, request, extra_context=None): self.register_newman_variables(request) id = request.GET.get('id', None) if not id: return utils.JsonResponse( _('No id found in GET variable "id".'), status=newman_settings.STATUS_VAR_MISSING) try: draft = AdminUserDraft.objects.get(ct=self.model_content_type, user=request.user, pk=id) except AdminUserDraft.DoesNotExist: return utils.JsonResponse( _('No matching draft found.'), status=newman_settings.STATUS_OBJECT_NOT_FOUND) msg = _('Draft %s was deleted.' % draft.__unicode__()) draft.delete() return utils.JsonResponse(msg) @require_AJAX def filters_view(self, request, extra_context=None): "stolen from: The 'change list' admin view for this model." self.register_newman_variables(request) opts = self.model._meta app_label = opts.app_label try: cl = FilterChangeList(request, self.model, self.list_display, self.list_display_links, self.list_filter, self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self) except IncorrectLookupParameters: # Wacky lookup parameters were given, so redirect to the main # changelist page, without parameters, and pass an 'invalid=1' # parameter via the query string. If wacky parameters were given and # the 'invalid=1' parameter was already in the query string, something # is screwed up with the database, so display an error page. if ERROR_FLAG in request.GET.keys(): return render_to_response('newman/invalid_setup.html', {'title': _('Database error')}) #return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1') return utils.JsonResponseRedirect(request.path + '?' + ERROR_FLAG + '=1') cl.formset = None context = { 'title': cl.title, 'is_popup': cl.is_popup, 'cl': cl, 'has_add_permission': self.has_add_permission(request), 'root_path': self.admin_site.root_path, 'app_label': app_label, } context.update(extra_context or {}) out = render_to_response( self.filters_template or 'newman/filters.html', context, context_instance=template.RequestContext(request)) return HttpResponse(out, mimetype='text/plain;charset=utf-8') @require_AJAX def log_view(self, request, extra_context=None): self.register_newman_variables(request) ct = ContentType.objects.get_for_model(self.model) if ct.model_class() == Publishable: publishable_cts = [] cts = ContentType.objects.all() for ctc in cts: if ctc.model_class() and issubclass(ctc.model_class(), Publishable): publishable_cts.append(ctc.id) params = {'content_type__in': publishable_cts} else: params = {'content_type': ct} if not request.user.is_superuser: params.update({'user': request.user}) entries = utils.get_log_entries(limit=15, filters=params) context = {'entry_list': entries, 'ct': ct} return render_to_response( self.get_template_list('action_log.html'), context, context_instance=template.RequestContext(request)) #@require_AJAX def changelist_view(self, request, extra_context=None): self.register_newman_variables(request) # save per user filtered content type. is_popup = False req_path = request.get_full_path() ct = ContentType.objects.get_for_model(self.model) # persistent filter for non-popupped changelists only key = 'filter__%s__%s' % (ct.app_label, ct.model) if req_path.find( 'pop' ) >= 0: # if popup is displayed, remove pop string from request path is_popup = True req_path = re.sub(r'(.*)(pop=&|&pop=|pop=|pop&|&pop|pop)(.*)', r'\1\3', req_path) if req_path.endswith('?') and is_popup: req_path = '' # if popup with no active filters is displayed, do not save empty filter settings if req_path.find('?') > 0: url_args = req_path.split('?', 1)[1] utils.set_user_config_db(request.user, key, url_args) log.debug('SAVING FILTERS %s' % url_args) else: user_filter = utils.get_user_config(request.user, key) if user_filter: if is_popup: user_filter = 'pop&%s' % user_filter redirect_to = '%s?%s' % (request.path, user_filter) if not redirect_to.endswith('?q='): log.debug('REDIRECTING TO %s' % redirect_to) return utils.JsonResponseRedirect(redirect_to) context = super(NewmanModelAdmin, self).get_changelist_context(request) if type(context) != dict: return context if context['media']: raw_media = self.prepare_media(context['media']) context['media'] = raw_media context['is_filtered'] = context['cl'].is_filtered() context['is_user_category_filtered'] = utils.is_user_category_filtered( self.queryset(request)) context.update(extra_context or {}) return render_to_response( self.change_list_template, context, context_instance=template.RequestContext(request)) @require_AJAX def suggest_view(self, request, extra_context=None): self.register_newman_variables(request) if not ('f' in request.GET.keys() and 'q' in request.GET.keys()): raise AttributeError, 'Invalid query attributes. Example: ".../?f=field_a&f=field_b&q=search_term&o=offset"' elif len(request.GET.get( 'q')) < newman_settings.SUGGEST_VIEW_MIN_LENGTH: return HttpResponse('', mimetype='text/plain;charset=utf-8') offset = 0 if 'o' in request.GET.keys() and request.GET.get('o'): offset = int(request.GET.get('o')) limit = offset + newman_settings.SUGGEST_VIEW_LIMIT model_fields = [mf.name for mf in self.model._meta.fields] lookup_fields = [] lookup_value = request.GET.get('q') lookup = None has_non_lookup_attr = False all_fields = [u'id'] + request.GET.getlist('f') for lf in all_fields: if lf in model_fields or lf.split('__')[0] in model_fields: lookup_fields.append(lf) elif hasattr(self.model, lf): has_non_lookup_attr = True else: raise AttributeError, 'Model "%s" has not field "%s". Possible fields are "%s".' \ % (self.model._meta.object_name, lf, ', '.join(model_fields)) for f in lookup_fields: lookup_key = str('%s__icontains' % f) if not lookup: lookup = models.Q(**{lookup_key: lookup_value}) else: lookup = lookup | models.Q(**{lookup_key: lookup_value}) # user role based category filtering if not is_category_model(self.model): category_field = model_category_fk(self.model) if category_field and request.user: applicable = applicable_categories(request.user) args_lookup = {'%s__in' % category_field.name: applicable} lookup = lookup & models.Q(**args_lookup) else: applicable = applicable_categories(request.user) lookup = lookup & models.Q(pk__in=applicable) # user category filter qs = utils.user_category_filter(self.model.objects.filter(lookup), request.user) if not has_non_lookup_attr: data = qs.values(*lookup_fields) else: data = qs.only(*lookup_fields) def construct_row(inst, fields): row = {} for f in fields: attr = getattr(inst, f) if callable(attr): row[f] = attr() else: row[f] = attr row[f] = truncatewords(striptags(unicode(row[f])), 5) return row if has_non_lookup_attr: outdata = [] for i in data: outdata.append(construct_row(i, all_fields)) data = outdata # sort the suggested items so that those starting with the sought term come first def compare(a, b): def _cmp(a, b, sought): a_starts = unicode(a).lower().startswith(sought) b_starts = unicode(b).lower().startswith(sought) # if exactly one of (a,b) starts with sought, the one starting with it comes first if a_starts ^ b_starts: if a_starts: return -1 if b_starts: return +1 # else compare lexicographically return cmp(a, b) return _cmp(a, b, unicode(lookup_value).lower()) cnt = len(data) data = list(data) if offset >= len(data): return HttpResponse('SPECIAL: OFFSET OUT OF RANGE', mimetype='text/plain') data.sort(cmp=compare, key=lambda x: x[lookup_fields[1]]) data = data[offset:limit] ft = [] ft.append('{cnt:%d}' % cnt) for item in data: ft.append("%s".encode('utf-8') % '|'.join("%s" % item[f] for f in all_fields)) return HttpResponse('\n'.join(ft), mimetype='text/plain;charset=utf-8') def register_newman_variables(self, request): self.user = request.user def has_view_permission(self, request, obj): opts = self.opts view_perm = '%s.view_%s' % (opts.app_label, opts.object_name.lower()) return request.user.has_perm(view_perm) def has_model_view_permission(self, request, obj=None): """ returns True if user has permission to view this model, otherwise False. """ # try to find view or change perm. for given user in his permissions or groups permissions can_change = super(NewmanModelAdmin, self).has_change_permission(request, obj) can_view = self.has_view_permission(request, obj) if can_view or can_change: return True # find permission to view or change in CategoryUserRoles for given user user = request.user opts = self.opts change_perm = '%s.%s' % (opts.app_label, opts.get_change_permission()) view_perm = '%s.view_%s' % (opts.app_label, opts.object_name.lower()) perms = [change_perm, view_perm] for role in user.categoryuserrole_set.all(): for perm in role.group.permissions.all(): p = '%s.%s' % (opts.app_label, perm.codename) if p in perms: return True # no permission found return False def has_change_permission(self, request, obj=None): """ Returns True if the given request has permission to change the given Django model instance. If `obj` is None, this should return True if the given request has permission to change *any* object of the given type. If request is GET type, at least view_permission is needed. In case of POST request change permission is needed. """ cfield = model_category_fk_value(obj) if obj is None or not cfield: if request.method == 'POST': return super(NewmanModelAdmin, self).has_change_permission(request, obj) else: return self.has_model_view_permission(request, obj) opts = self.opts change_perm = '%s.%s' % (opts.app_label, opts.get_change_permission()) view_perm = '%s.view_%s' % (opts.app_label, opts.object_name.lower()) can_view = has_category_permission(request.user, cfield, view_perm) can_change = has_category_permission(request.user, cfield, change_perm) if request.method == 'POST' and can_change: return True elif request.method == 'GET' and (can_view or can_change): return True return False def has_delete_permission(self, request, obj=None): """ Returns True if the given request has permission to change the given Django model instance. If `obj` is None, this should return True if the given request has permission to delete *any* object of the given type. """ opts = self.opts del_perm = opts.app_label + '.' + opts.get_delete_permission() if request.user.has_perm(del_perm): return True user = request.user roles = DenormalizedCategoryUserRole.objects.filter( user_id=user.pk, permission_codename=del_perm) if roles: return True # no permission found return False def has_add_permission(self, request): "Returns True if the given request has permission to add an object." opts = self.opts add_perm = opts.app_label + '.' + opts.get_add_permission() if request.user.has_perm(add_perm): return True user = request.user roles = DenormalizedCategoryUserRole.objects.filter( user_id=user.pk, permission_codename=add_perm) if roles: return True # no permission found return False def get_change_view_inline_formsets(self, request, obj, formsets, media): inline_admin_formsets = [] self._raw_inlines = {} for inline, formset in zip(self.inline_instances, formsets): self._raw_inlines[str(inline.model._meta).replace('.', '__')] = formset fieldsets = list(inline.get_fieldsets(request, obj)) inline_admin_formset = InlineNewmanFormset(inline, formset, fieldsets) inline_admin_formsets.append(inline_admin_formset) media = media + inline_admin_formset.media return inline_admin_formsets, media def json_error_response(self, request, context): """ Chyby v polich formulare Chyba v poli formulare napr.: context['adminform'].form['slug'].errors Chyba v poli inline napr.: context['inline_admin_formsets'][0].formset.errors tj.: [{'content': [u'Toto pole je povinn\xe9.']}] id inline v sablone: id_ + context['inline_admin_formsets'][0].formset.prefix + [poradove cislo formsetu tj. 0 + jmeno sloupce priklad id: id_articlecontents_set-0-content """ fcounter = {} def get_formset_counter(fset): if fset not in fcounter: fcounter[fset] = 0 else: fcounter[fset] += 1 return fcounter[fset] def give_me_unicode(ei): if not hasattr(ei, '__unicode__'): return u'%s' % ei return ei.__unicode__() error_list = [] # Form fields frm = context['adminform'].form for field_name in frm.fields: field = frm[field_name] if field.errors: err_dict = { 'id': u"id_%s" % field_name, 'label': u"%s" % field.label, 'messages': map(lambda item: u'%s' % item, map(give_me_unicode, field.errors)) } error_list.append(err_dict) # Inline Form fields for fset in context['inline_admin_formsets']: for err_item in fset.formset.errors: counter = get_formset_counter(fset.formset.prefix) for key in err_item: label = u'' """ for mfield in fset.formset.model._meta.fields: if mfield.name == key: label = mfield.verbose_name break """ for fkey, mfield in fset.formset.form.base_fields.items(): if fkey == key: if hasattr(mfield.label, '__unicode__'): label = mfield.label.__unicode__() else: label = mfield.label.__str__() break err_dict = { 'id': u'id_%s-%d-%s' % (fset.formset.prefix, counter, key), 'label': u"%s" % label, 'messages': map(lambda item: item, map(give_me_unicode, err_item[key])) } error_list.append(err_dict) # Other errors (e.g. db errors) if 'error_dict' in context and 'id___all__' in context['error_dict']: error_list.append({ 'messages': context['error_dict']['id___all__'], 'id': 'id___all__', }) return utils.JsonResponse(_('Please correct errors in form'), errors=error_list, status=newman_settings.STATUS_FORM_ERROR) def change_view_process_context(self, request, context, object_id): form = context['raw_form'] # raw forms for JS manipulations raw_frm_all = {'form': form, 'inlines': self._raw_inlines} # form for autosaved and draft objects draft_form = DraftForm(user=request.user, content_type=self.model_content_type) info = self.admin_site.app_name, self.model._meta.app_label, self.model._meta.module_name rev = '%s:%s_%s_change_json' % info context.update({ 'media': self.prepare_media(context['media']), 'raw_form': raw_frm_all, 'draft_form': draft_form, 'save_url': reverse(rev, args=[object_id]) }) return context def change_view_prepare_context(self, request, object_id): self.register_newman_variables(request) out = self.change_view_preprocess(request, object_id) if out is not None: # HttpReponse return out context = self.get_change_view_context(request, object_id) # Newman's additions to the context self.change_view_process_context(request, context, object_id) return context def model_detail_json_view(self, request, object_id, extra_context=None): " Outputs basic object's data. " obj = None try: obj = self.queryset(request).get(pk=unquote(object_id)) except obj.DoesNotExist: obj = None if not self.has_model_view_permission(request, obj): raise PermissionDenied result_dict = dict() for field in obj._meta.fields: result_dict[field.name] = field.value_to_string(obj) return utils.JsonResponse('JSON object detail data.', result_dict, status=newman_settings.STATUS_OK) @transaction.commit_on_success def change_json_view(self, request, object_id, extra_context=None): "The 'change' admin view for this model." if request.method.upper() != 'POST': msg = _( 'This view is designed for saving data only, thus POST method is required.' ) return HttpResponseForbidden(msg) context = self.change_view_prepare_context(request, object_id) if type(context) != dict: obj = self.get_change_view_object(object_id) opts = obj._meta if request.FILES and not request.is_ajax(): return_url = '%s#/%s/%s/' % (reverse('newman:index'), opts.app_label, opts.module_name) if request.POST.get('_continue'): return_url += '%s/' % object_id if request.POST.get('_addanother'): return_url += 'add/' return HttpResponseRedirect(return_url) redir = request.POST.get('http_redirect_to', None) if redir: return utils.JsonResponseRedirect(redir) return utils.JsonResponse( _('The %(name)s "%(obj)s" was changed successfully.') % { 'name': force_unicode(opts.verbose_name), 'obj': force_unicode(obj) }, { 'id': obj.pk, 'title': obj.__unicode__(), }, status=newman_settings.STATUS_OK) context.update(extra_context or {}) return self.json_error_response(request, context) # Json response def change_view(self, request, object_id, extra_context=None): "The 'change' admin view for this model." if request.method.upper() != 'GET': msg = _( 'This view is designed for viewing form, thus GET method is required.' ) return HttpResponseForbidden(msg) context = self.change_view_prepare_context(request, object_id) context.update(extra_context or {}) obj = self.get_change_view_object(object_id) return self.render_change_form(request, context, change=True, obj=obj) def get_add_view_context(self, request, form_url): self.register_newman_variables(request) context = super(NewmanModelAdmin, self).get_add_view_context(request, form_url) # form for autosaved and draft objects draft_form = DraftForm(user=request.user, content_type=self.model_content_type) info = self.admin_site.app_name, self.model._meta.app_label, self.model._meta.module_name rev = '%s:%s_%s_add_json' % info context.update({ 'media': self.prepare_media(context['media']), 'draft_form': draft_form, 'save_url': reverse(rev) }) return context def get_inline_admin_formset(self, inline, formset, fieldsets): return InlineNewmanFormset(inline, formset, fieldsets) @require_AJAX def delete_view(self, request, object_id, extra_context=None): try: result = super(NewmanModelAdmin, self).delete_view(request, object_id, extra_context) if not isinstance(result, HttpResponseRedirect): return result except Exception, e: # in case of exception return JSON error dict instead of 500.html return utils.JsonResponseError(str(e)) # create JsonResponse containing success message return utils.JsonResponse(_('Object was deleted.'))