예제 #1
0
    def get_mass_upload_context(self, request):
        model = self.model
        opts = model._meta
        self.register_newman_variables(request)

        # To enable admin-specific fields, we need to run the form class
        # through modelform_factory using curry
        FormClass = modelform_factory(
            Photo,
            form=MassUploadForm,
            fields=flatten_fieldsets(self.mass_upload_fieldsets),
            formfield_callback=curry(self.formfield_for_dbfield,
                                     request=request))

        context = {}
        if request.method == 'POST':
            error_dict = {}
            # Unfortunately, FLASH uploader sends array data in weird format
            # so that Django doesn't recognize it as array of values, but
            # as one string with commas inside. The only way to expect it
            # and preprocess the values by ourselves.
            data = dict((key, val) for key, val in request.POST.items())
            form = FormClass(data, request.FILES)

            if form.is_valid():
                # To prevent newman from handling our field by common flash editor
                # we need to use a different mechanism
                new_object = form.save(commit=False)
                new_object.image = form.cleaned_data['image_file']
                new_object.save()
                form.save_m2m()
                context.update({'object': new_object})
            else:
                for e in form.errors:
                    error_dict[u"id_%s" %
                               e] = [u"%s" % ee for ee in form.errors[e]]
                context.update({'error_dict': error_dict})
        else:
            form = FormClass()

        adminForm = helpers.AdminForm(form, list(self.mass_upload_fieldsets),
                                      self.prepopulated_fields)
        media = self.media + adminForm.media

        context.update({
            'title':
            _('Mass upload'),
            'adminform':
            adminForm,
            'is_popup':
            request.REQUEST.has_key('_popup'),
            'show_delete':
            False,
            'media':
            media,
            'inline_admin_formsets': [],
            'errors':
            helpers.AdminErrorList(form, ()),
            'root_path':
            self.admin_site.root_path,
            'app_label':
            opts.app_label,
            'opts':
            opts,
            'has_change_permission':
            self.has_change_permission(request, None),
            'raw_form':
            form
        })
        return context
예제 #2
0
def merge(modeladmin, request, queryset):  # noqa
    """
    Merge two model instances. Move all foreign keys.

    """

    opts = modeladmin.model._meta
    perm = "{0}.{1}".format(
        opts.app_label, get_permission_codename('adminactions_merge', opts))
    if not request.user.has_perm(perm):
        messages.error(
            request, _('Sorry you do not have rights to execute this action'))
        return

    def raw_widget(field, **kwargs):
        """ force all fields as not required"""
        kwargs['widget'] = TextInput({'class': 'raw-value'})
        return field.formfield(**kwargs)

    merge_form = getattr(modeladmin, 'merge_form', MergeForm)
    MForm = modelform_factory(modeladmin.model,
                              form=merge_form,
                              exclude=('pk', ),
                              formfield_callback=raw_widget)
    OForm = modelform_factory(modeladmin.model,
                              exclude=('pk', ),
                              formfield_callback=raw_widget)

    tpl = 'adminactions/merge.html'
    # transaction_supported = model_supports_transactions(modeladmin.model)
    ctx = {
        '_selected_action':
        request.POST.getlist(helpers.ACTION_CHECKBOX_NAME),
        'transaction_supported':
        'Un',
        'select_across':
        request.POST.get('select_across') == '1',
        'action':
        request.POST.get('action'),
        'fields': [
            f for f in queryset.model._meta.fields
            if not f.primary_key and f.editable
        ],
        'app_label':
        queryset.model._meta.app_label,
        'result':
        '',
        'opts':
        queryset.model._meta
    }

    if 'preview' in request.POST:
        master = queryset.get(pk=request.POST.get('master_pk'))
        original = clone_instance(master)
        other = queryset.get(pk=request.POST.get('other_pk'))
        formset = formset_factory(OForm)(
            initial=[model_to_dict(master),
                     model_to_dict(other)])
        with transaction.nocommit():
            form = MForm(request.POST, instance=master)
            other.delete()
            form_is_valid = form.is_valid()
        if form_is_valid:
            ctx.update({'original': original})
            tpl = 'adminactions/merge_preview.html'
        else:
            master = queryset.get(pk=request.POST.get('master_pk'))
            other = queryset.get(pk=request.POST.get('other_pk'))

    elif 'apply' in request.POST:
        master = queryset.get(pk=request.POST.get('master_pk'))
        other = queryset.get(pk=request.POST.get('other_pk'))
        formset = formset_factory(OForm)(
            initial=[model_to_dict(master),
                     model_to_dict(other)])
        with transaction.nocommit():
            form = MForm(request.POST, instance=master)
            stored_pk = other.pk
            other.delete()
            ok = form.is_valid()
            other.pk = stored_pk
        if ok:
            if form.cleaned_data['dependencies'] == MergeForm.DEP_MOVE:
                related = api.ALL_FIELDS
            else:
                related = None
            fields = form.cleaned_data['field_names']
            api.merge(master,
                      other,
                      fields=fields,
                      commit=True,
                      related=related)
            return HttpResponseRedirect(request.path)
        else:
            messages.error(request, form.errors)
    else:
        try:
            master, other = queryset.all()
            # django 1.4 need to remove the trailing milliseconds
            for field in master._meta.fields:
                if isinstance(field, models.DateTimeField):
                    for target in (master, other):
                        raw_value = getattr(target, field.name)
                        if raw_value:
                            fixed_value = datetime(raw_value.year,
                                                   raw_value.month,
                                                   raw_value.day,
                                                   raw_value.hour,
                                                   raw_value.minute,
                                                   raw_value.second)
                            setattr(target, field.name, fixed_value)
        except ValueError:
            messages.error(request, _('Please select exactly 2 records'))
            return

        initial = {
            '_selected_action':
            request.POST.getlist(helpers.ACTION_CHECKBOX_NAME),
            'select_across': 0,
            'generic': MergeForm.GEN_IGNORE,
            'dependencies': MergeForm.DEP_MOVE,
            'action': 'merge',
            'master_pk': master.pk,
            'other_pk': other.pk
        }
        formset = formset_factory(OForm)(
            initial=[model_to_dict(master),
                     model_to_dict(other)])
        form = MForm(initial=initial, instance=master)

    adminForm = helpers.AdminForm(form,
                                  modeladmin.get_fieldsets(request), {}, [],
                                  model_admin=modeladmin)
    media = modeladmin.media + adminForm.media
    ctx.update({
        'adminform':
        adminForm,
        'formset':
        formset,
        'media':
        mark_safe(media),
        'action_short_description':
        merge.short_description,
        'title':
        u"%s (%s)" % (
            merge.short_description.capitalize(),
            smart_text(modeladmin.opts.verbose_name_plural),
        ),
        'master':
        master,
        'other':
        other
    })
    if django.VERSION[:2] > (1, 7):
        ctx.update(modeladmin.admin_site.each_context(request))
    else:
        ctx.update(modeladmin.admin_site.each_context())
    if django.VERSION[:2] > (1, 8):
        return render(request, tpl, context=ctx)
    else:
        return render_to_response(tpl, RequestContext(request, ctx))
예제 #3
0
    def positions_by_category_view(self, request, category_id, extra_context=None):

        model = self.model
        self.user = request.user

        try:
            category = Category.objects.get(id=category_id)
        except Category.DoesNotExist:
            # FIXME: redirect
            return HttpResponseRedirect(reverse('newman:index'))

        names = ['featured_secondary_1', 'featured_secondary_2', 'featured_secondary_3', 'poll', 'tipoftheday',
                 'special', 'recipeoftheday', 'featured_small_1', 'featured_small_2',
                 'featured_small_3', ]

        positions = model.objects.filter(category=category_id, name__in=names)

        count = positions.count()

        PositionForm = self.get_form(request)

        if request.method == 'POST':
            forms = [PositionForm(request.POST, prefix=str(positions[x].id),
                                  instance=positions[x]) for x in range(count)]
            if all([form.is_valid() for form in forms]):
                for form in forms:
                    new_object = self.save_form(request, form, change=True)
                    self.save_model(request, new_object, form, change=True)
                    change_message = self.construct_change_message(request, form, None)
                    self.log_change(request, new_object, change_message)

                msg = unicode(_('Positions were changed successfully.'))

                return JsonResponse(msg, data={'category_id': category_id})
        else:
            forms = [PositionForm(prefix=str(positions[x].id),
                                  instance=positions[x]) for x in range(count)]

        adminForms = [helpers.AdminForm(forms[x], self.get_fieldsets(request, positions[x]),
                                self.prepopulated_fields) for x in range(count)]

        errors = []
        for form in forms:
            errors.extend(helpers.AdminErrorList(form, []))

        media = self.media
        if len(adminForms) > 0:
            media += adminForms[0].media

        raw_media = self.prepare_media(media)

        context = {
            'multiple_edit': True,
            'add': False,
            'title': _('Positions in %s') % category.title,
            'category': category,
            'adminforms': adminForms,
            'errors': errors,
            'media': raw_media,
            'is_popup': request.REQUEST.has_key('_popup'),
        }
        context.update(extra_context or {})

        # render change form
        opts = self.model._meta
        app_label = opts.app_label
        ordered_objects = opts.get_ordered_objects()

        context.update({
            'app_label': app_label,
            'change': True,
            'has_add_permission': False,
            'has_change_permission': True,
            'has_delete_permission': False,
            'has_file_field': False,
            'has_absolute_url': hasattr(self.model, 'get_absolute_url'),
            'ordered_objects': ordered_objects,
            'opts': opts,
            'content_type_id': ContentType.objects.get_for_model(self.model).id,
            'save_as': self.save_as,
            'save_on_top': self.save_on_top,
            'save_url': reverse('newman:positions-by-category', args=[category_id]),
        })
        return render_to_response("newman/%s/multi_change_form.html" % app_label,
                            context, context_instance=template.RequestContext(request))
예제 #4
0
    def add_view(self, request, form_url='', extra_context=None):
        "The 'add' admin view for this model."
        model = self.model
        opts = model._meta

        if not self.has_add_permission(request):
            raise PermissionDenied

        ModelForm = self.get_form(request)
        formsets = []
        inline_instances = self.get_inline_instances(request, None)
        if request.method == 'POST':
            form = ModelForm(request.POST, request.FILES)
            if form.is_valid():
                new_object = self.save_form(request, form, change=False)
                form_validated = True
            else:
                form_validated = False
                new_object = self.model()
            prefixes = {}
            for FormSet, inline in self.get_formsets_with_inlines(request):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1 or not prefix:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(data=request.POST, files=request.FILES,
                    instance=new_object,
                    save_as_new="_saveasnew" in request.POST,
                    prefix=prefix, queryset=inline.get_queryset(request))
                formsets.append(formset)
                if inline.inlines:
                    self.add_nested_inline_formsets(request, inline, formset)
            if self.all_valid_with_nesting(formsets) and form_validated:
                self.save_model(request, new_object, form, False)
                self.save_related(request, form, formsets, False)
                args = ()
                # Provide `add_message` argument to ModelAdmin.log_addition for
                # Django 1.9 and up.
                if VERSION[:2] >= (1, 9):
                    add_message = self.construct_change_message(
                        request, form, formsets, add=True
                    )
                    args = (request, new_object, add_message)
                else:
                    args = (request, new_object)
                self.log_addition(*args)
                return self.response_add(request, new_object)
        else:
            # Prepare the dict of initial data from the request.
            # We have to special-case M2Ms as a list of comma-separated PKs.
            initial = dict(request.GET.items())
            for k in initial:
                try:
                    f = opts.get_field(k)
                except models.FieldDoesNotExist:
                    continue
                if isinstance(f, models.ManyToManyField):
                    initial[k] = initial[k].split(",")
            form = ModelForm(initial=initial)
            prefixes = {}
            for FormSet, inline in self.get_formsets_with_inlines(request):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1 or not prefix:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(instance=self.model(), prefix=prefix,
                    queryset=inline.get_queryset(request))
                formsets.append(formset)
                if hasattr(inline, 'inlines') and inline.inlines:
                    self.add_nested_inline_formsets(request, inline, formset)

        adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
            self.get_prepopulated_fields(request),
            self.get_readonly_fields(request),
            model_admin=self)
        media = self.media + adminForm.media

        inline_admin_formsets = []
        for inline, formset in zip(inline_instances, formsets):
            fieldsets = list(inline.get_fieldsets(request))
            readonly = list(inline.get_readonly_fields(request))
            prepopulated = dict(inline.get_prepopulated_fields(request))
            inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
                fieldsets, prepopulated, readonly, model_admin=self)
            inline_admin_formsets.append(inline_admin_formset)
            media = media + inline_admin_formset.media
            if hasattr(inline, 'inlines') and inline.inlines:
                other_media = self.wrap_nested_inline_formsets(request, inline, formset)
                if other_media is not None:
                    media += other_media

        context = {
            'title': _('Add %s') % force_text(opts.verbose_name),
            'adminform': adminForm,
            'is_popup': "_popup" in request.GET,
            'show_delete': False,
            'media': media,
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            'app_label': opts.app_label,
            }
        context.update(self.admin_site.each_context(request))
        context.update(extra_context or {})
        return self.render_change_form(request, context, form_url=form_url, add=True)
예제 #5
0
    def get_add_view_context(self, request, form_url):
        model = self.model
        opts = model._meta

        if not self.has_add_permission(request):
            raise PermissionDenied

        ModelForm = self.get_form(request)
        formsets = []
        context = {}
        if request.method == 'POST':
            error_dict = {}
            form = ModelForm(request.POST.copy(), request.FILES)
            if form.is_valid():
                form_validated = True
                new_object = self.save_form(request, form, change=False)
            else:
                for e in form.errors:
                    error_dict[u"id_%s" % e] = [ u"%s" % ee for ee in form.errors[e] ]
                form_validated = False
                new_object = self.model()
            prefixes = {}
            for FormSet in self.get_formsets(request):
                prefix = FormSet.get_default_prefix()
                prefix_no = prefixes.get(prefix, 0)
                prefixes[prefix] = prefix_no + 1
                if prefixes[prefix] != 1:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(data=request.POST.copy(), files=request.FILES,
                                  instance=new_object,
                                  save_as_new=request.POST.has_key("_saveasnew"),
                                  prefix=prefix)
                if not formset.is_valid():
                    for e in formset.errors[prefix_no]:
                        error_dict[u"id_%s-%d-%s" % (prefix, prefix_no, e)] = [u"%s" % ee for ee in formset.errors[prefix_no][e]]
                formsets.append(formset)
            if all_valid(formsets) and form_validated:
                self.save_model(request, new_object, form, change=False)
                form.save_m2m()
                for formset in formsets:
                    self.save_formset(request, form, formset, change=False)

                self.log_addition(request, new_object)
                self.response_add(request, new_object)
                context.update({
                    'object': new_object,
                    'object_added': True,
                })
            else:
                context.update({
                    'error_dict': error_dict,
                })
        else:
            # Prepare the dict of initial data from the request.
            # We have to special-case M2Ms as a list of comma-separated PKs.
            initial = dict(request.GET.items())
            for k in initial:
                try:
                    f = opts.get_field(k)
                except FieldDoesNotExist:
                    continue
                if isinstance(f, ManyToManyField):
                    initial[k] = initial[k].split(",")
            form = ModelForm(initial=initial)
            prefixes = {}
            for FormSet in self.get_formsets(request):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(instance=self.model(), prefix=prefix)
                formsets.append(formset)

        adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)), self.prepopulated_fields)
        media = self.media + adminForm.media

        inline_admin_formsets = []
        for inline, formset in zip(self.inline_instances, formsets):
            fieldsets = list(inline.get_fieldsets(request))
            inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets)
            inline_admin_formset = self.get_inline_admin_formset(inline, formset, fieldsets)
            inline_admin_formsets.append(inline_admin_formset)
            media = media + inline_admin_formset.media

        context.update({
            'title': _('Add %s') % force_unicode(opts.verbose_name),
            'adminform': adminForm,
            'is_popup': request.REQUEST.has_key('_popup'),
            'show_delete': False,
            'media': media,
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            'root_path': self.admin_site.root_path,
            'app_label': opts.app_label,
        })

        context['raw_form'] = form
        return context
예제 #6
0
    def _changeform_view(self, request, object_id, form_url, extra_context):
        to_field = request.POST.get('_to_field', request.GET.get('_to_field'))
        if to_field and not self.to_field_allowed(request, to_field):
            raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field)

        model = self.model
        opts = model._meta

        if request.method == 'POST' and '_saveasnew' in request.POST:
            object_id = None

        add = object_id is None

        if add:
            if not self.has_add_permission(request):
                raise PermissionDenied
            obj = None

        else:
            obj = self.get_object(request, unquote(object_id), to_field)

            if not self.has_change_permission(request, obj):
                raise PermissionDenied

            if obj is None:
                return self._get_obj_does_not_exist_redirect(request, opts, object_id)

        ModelForm = self.get_form(request, obj)
        if request.method == 'POST':
            form = ModelForm(request.POST, request.FILES, instance=obj)
            if form.is_valid():
                form_validated = True
                new_object = self.save_form(request, form, change=not add)
            else:
                form_validated = False
                new_object = form.instance
            formsets, inline_instances = self._create_formsets(request, new_object, change=not add)
            
            # ----- NUMBER OF CANDIDATES
            number_candidates = 0
            if all_valid(formsets):
                for formset in formsets:
                    for f in formset: 
                        cd = f.cleaned_data
                        candidate = cd.get('president_candidate') or cd.get('congress_candidate')
                        delete = cd.get('DELETE')
                        if candidate:
                            number_candidates += 1
                        if delete:
                            number_candidates -= 1

            valid_number_candidates_congress = True
            if number_candidates > 350 or number_candidates <= 0:
                valid_number_candidates_congress = False
            # Message users
            if not valid_number_candidates_congress:
                msg = 'The number of candidates must be 350 or less as well as having at least one candidate. There are now {} candidates.'.format(number_candidates)
                self.message_user(request, msg, messages.WARNING)
            # ----- END NUMBER OF CANDIDATES

            # ----- GENDER BALANCE LOAD CHECK
            women_number = 0
            men_number = 0
            if all_valid(formsets):
                for formset in formsets:
                    for f in formset: 
                        cd = f.cleaned_data
                        genre = cd.get('gender')
                        delete = cd.get('DELETE')
                        if genre == 'H':
                            men_number += 1
                        elif genre == 'M':
                            women_number += 1
                        if delete:
                            if genre == 'H':
                                men_number -= 1
                            elif genre == 'M':
                                women_number -= 1

            valid_genre_balance = True
            if women_number+men_number == 0:
                women_balance = 0
                men_balance = 0
            else:
                women_balance = (women_number/(women_number+men_number))
                men_balance = (men_number/(women_number+men_number))
            if women_balance < 0.4 or men_balance < 0.4 :
                valid_genre_balance = False
            # Message users
            if not valid_genre_balance:
                msg = 'The number of women candidates and the number of men candidates must be at least a 40% of the total candidates. Women: {}%, Men:{}%'.format(women_balance*100, men_balance*100)
                self.message_user(request, msg, messages.WARNING)
            # ----- END GENDER BALANCE LOAD CHECK

            if all_valid(formsets) and form_validated and valid_number_candidates_congress and valid_genre_balance:
                self.save_model(request, new_object, form, not add)
                self.save_related(request, form, formsets, not add)
                change_message = self.construct_change_message(request, form, formsets, add)
                if add:
                    self.log_addition(request, new_object, change_message)
                    return self.response_add(request, new_object)
                else:
                    self.log_change(request, new_object, change_message)
                    return self.response_change(request, new_object)
            else:
                form_validated = False
        else:
            if add:
                initial = self.get_changeform_initial_data(request)
                form = ModelForm(initial=initial)
                formsets, inline_instances = self._create_formsets(request, form.instance, change=False)
            else:
                form = ModelForm(instance=obj)
                formsets, inline_instances = self._create_formsets(request, obj, change=True)

        adminForm = helpers.AdminForm(
            form,
            list(self.get_fieldsets(request, obj)),
            self.get_prepopulated_fields(request, obj),
            self.get_readonly_fields(request, obj),
            model_admin=self)
        media = self.media + adminForm.media

        inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj)
        for inline_formset in inline_formsets:
            media = media + inline_formset.media

        context = dict(
            self.admin_site.each_context(request),
            title=(_('Add %s') if add else _('Change %s')) % opts.verbose_name,
            adminform=adminForm,
            object_id=object_id,
            original=obj,
            is_popup=('_popup' in request.POST or
                      '_popup' in request.GET),
            to_field=to_field,
            media=media,
            inline_admin_formsets=inline_formsets,
            errors=helpers.AdminErrorList(form, formsets),
            preserved_filters=self.get_preserved_filters(request),
        )

        # Hide the "Save" and "Save and continue" buttons if "Save as New" was
        # previously chosen to prevent the interface from getting confusing.
        if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST:
            context['show_save'] = False
            context['show_save_and_continue'] = False
            # Use the change template instead of the add template.
            add = False

        context.update(extra_context or {})

        return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
예제 #7
0
파일: admin.py 프로젝트: wsghr/DeerU
    def _changeform_view(self, request, object_id, form_url, extra_context):
        to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR))
        if to_field and not self.to_field_allowed(request, to_field):
            raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field)

        model = self.model
        opts = model._meta

        if request.method == 'POST' and '_saveasnew' in request.POST:
            object_id = None

        add = object_id is None

        if add:
            if not self.has_add_permission(request):
                raise PermissionDenied
            obj = None

        else:
            obj = self.get_object(request, unquote(object_id), to_field)

            if request.method == 'POST':
                if not self.has_change_permission(request, obj):
                    raise PermissionDenied
            else:
                if not self.has_view_or_change_permission(request, obj):
                    raise PermissionDenied

            if obj is None:
                return self._get_obj_does_not_exist_redirect(request, opts, object_id)

        ModelForm = self.get_form(request, obj, change=not add)
        if request.method == 'POST':
            form = ModelForm(request.POST, request.FILES, instance=obj)
            form_validated = form.is_valid()
            if form_validated:
                new_object = self.save_form(request, form, change=not add)
            else:
                new_object = form.instance
            formsets, inline_instances = self._create_formsets(request, new_object, change=not add)
            if all_valid(formsets) and form_validated:
                self.save_model(request, new_object, form, not add)
                self.save_related(request, form, formsets, not add)
                change_message = self.construct_change_message(request, form, formsets, add)
                if add:
                    self.log_addition(request, new_object, change_message)
                    return self.response_add(request, new_object)
                else:
                    self.log_change(request, new_object, change_message)
                    return self.response_change(request, new_object)
            else:
                form_validated = False
        else:
            if add:
                initial = self.get_changeform_initial_data(request)
                form = ModelForm(initial=initial)
                formsets, inline_instances = self._create_formsets(request, form.instance, change=False)
            else:
                # Changed
                # 因为ArticleAdminForm中有Article没有的字段,这些字段的值不会变填充
                # field_init_value就是用于给这些字段填充值用的
                form = ModelForm(instance=obj, initial=self.field_init_value)
                formsets, inline_instances = self._create_formsets(request, obj, change=True)

        if not add and not self.has_change_permission(request, obj):
            readonly_fields = flatten_fieldsets(self.get_fieldsets(request, obj))
        else:
            readonly_fields = self.get_readonly_fields(request, obj)
        adminForm = helpers.AdminForm(
            form,
            list(self.get_fieldsets(request, obj)),
            # Clear prepopulated fields on a view-only form to avoid a crash.
            self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {},
            readonly_fields,
            model_admin=self)
        media = self.media + adminForm.media

        inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj)
        for inline_formset in inline_formsets:
            media = media + inline_formset.media

        if add:
            title = _('Add %s')
        elif self.has_change_permission(request, obj):
            title = _('Change %s')
        else:
            title = _('View %s')
        context = {
            **self.admin_site.each_context(request),
            'title': title % opts.verbose_name,
            'adminform': adminForm,
            'object_id': object_id,
            'original': obj,
            'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET,
            'to_field': to_field,
            'media': media,
            'inline_admin_formsets': inline_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            'preserved_filters': self.get_preserved_filters(request),
        }

        # Hide the "Save" and "Save and continue" buttons if "Save as New" was
        # previously chosen to prevent the interface from getting confusing.
        if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST:
            context['show_save'] = False
            context['show_save_and_continue'] = False
            # Use the change template instead of the add template.
            add = False

        context.update(extra_context or {})

        return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url)
예제 #8
0
def mass_update(modeladmin, request, queryset):  # noqa
    """
        mass update queryset
    """
    def not_required(field, **kwargs):
        """ force all fields as not required"""
        kwargs['required'] = False
        return field.formfield(**kwargs)

    def _doit():
        errors = {}
        updated = 0
        for record in queryset:
            for field_name, value_or_func in list(form.cleaned_data.items()):
                if callable(value_or_func):
                    old_value = getattr(record, field_name)
                    setattr(record, field_name, value_or_func(old_value))
                else:
                    setattr(record, field_name, value_or_func)
            if clean:
                record.clean()
            record.save()
            updated += 1
        if updated:
            messages.info(request, _("Updated %s records") % updated)

        if len(errors):
            messages.error(request,
                           "%s records not updated due errors" % len(errors))
        adminaction_end.send(sender=modeladmin.model,
                             action='mass_update',
                             request=request,
                             queryset=queryset,
                             modeladmin=modeladmin,
                             form=form,
                             errors=errors,
                             updated=updated)

    opts = modeladmin.model._meta
    perm = "{0}.{1}".format(
        opts.app_label, get_permission_codename('adminactions_massupdate',
                                                opts))
    if not request.user.has_perm(perm):
        messages.error(
            request, _('Sorry you do not have rights to execute this action'))
        return

    try:
        adminaction_requested.send(sender=modeladmin.model,
                                   action='mass_update',
                                   request=request,
                                   queryset=queryset,
                                   modeladmin=modeladmin)
    except ActionInterrupted as e:
        messages.error(request, str(e))
        return

    # Allows to specified a custom mass update Form in the ModelAdmin
    mass_update_form = getattr(modeladmin, 'mass_update_form', MassUpdateForm)

    MForm = modelform_factory(modeladmin.model,
                              form=mass_update_form,
                              exclude=('pk', ),
                              formfield_callback=not_required)
    grouped = defaultdict(lambda: [])
    selected_fields = []
    initial = {
        '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME),
        'select_across': request.POST.get('select_across') == '1',
        'action': 'mass_update'
    }

    if 'apply' in request.POST:
        form = MForm(request.POST)
        if form.is_valid():
            try:
                adminaction_start.send(sender=modeladmin.model,
                                       action='mass_update',
                                       request=request,
                                       queryset=queryset,
                                       modeladmin=modeladmin,
                                       form=form)
            except ActionInterrupted as e:
                messages.error(request, str(e))
                return HttpResponseRedirect(request.get_full_path())

            # need_transaction = form.cleaned_data.get('_unique_transaction', False)
            validate = form.cleaned_data.get('_validate', False)
            clean = form.cleaned_data.get('_clean', False)

            if validate:
                with compat.atomic():
                    _doit()

            else:
                values = {}
                for field_name, value in list(form.cleaned_data.items()):
                    if isinstance(form.fields[field_name],
                                  ModelMultipleChoiceField):
                        messages.error(
                            request,
                            "Unable no mass update ManyToManyField without 'validate'"
                        )
                        return HttpResponseRedirect(request.get_full_path())
                    elif callable(value):
                        messages.error(
                            request,
                            "Unable no mass update using operators without 'validate'"
                        )
                        return HttpResponseRedirect(request.get_full_path())
                    elif field_name not in [
                            '_selected_action', '_validate', 'select_across',
                            'action', '_unique_transaction', '_clean'
                    ]:
                        values[field_name] = value
                queryset.update(**values)

            return HttpResponseRedirect(request.get_full_path())
    else:
        initial.update({'action': 'mass_update', '_validate': 1})
        # form = MForm(initial=initial)
        prefill_with = request.POST.get('prefill-with', None)
        prefill_instance = None
        try:
            # Gets the instance directly from the queryset for data security
            prefill_instance = queryset.get(pk=prefill_with)
        except ObjectDoesNotExist:
            pass

        form = MForm(initial=initial, instance=prefill_instance)

    for el in queryset.all()[:10]:
        for f in modeladmin.model._meta.fields:
            if f.name not in form._no_sample_for:
                if hasattr(f, 'flatchoices') and f.flatchoices:
                    grouped[f.name] = list(
                        dict(getattr(f, 'flatchoices')).values())
                elif hasattr(f, 'choices') and f.choices:
                    grouped[f.name] = list(
                        dict(getattr(f, 'choices')).values())
                elif isinstance(f, df.BooleanField):
                    grouped[f.name] = [True, False]
                else:
                    value = getattr(el, f.name)
                    if value is not None and value not in grouped[f.name]:
                        grouped[f.name].append(value)
                    initial[f.name] = initial.get(f.name, value)

    adminForm = helpers.AdminForm(form,
                                  modeladmin.get_fieldsets(request), {}, [],
                                  model_admin=modeladmin)
    media = modeladmin.media + adminForm.media
    dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.date
                                                          ) else str(obj)
    tpl = 'adminactions/mass_update.html'
    ctx = {
        'adminform':
        adminForm,
        'form':
        form,
        'action_short_description':
        mass_update.short_description,
        'title':
        u"%s (%s)" % (
            mass_update.short_description.capitalize(),
            smart_text(modeladmin.opts.verbose_name_plural),
        ),
        'grouped':
        grouped,
        'fieldvalues':
        json.dumps(grouped, default=dthandler),
        'change':
        True,
        'selected_fields':
        selected_fields,
        'is_popup':
        False,
        'save_as':
        False,
        'has_delete_permission':
        False,
        'has_add_permission':
        False,
        'has_change_permission':
        True,
        'opts':
        modeladmin.model._meta,
        'app_label':
        modeladmin.model._meta.app_label,
        # 'action': 'mass_update',
        # 'select_across': request.POST.get('select_across')=='1',
        'media':
        mark_safe(media),
        'selection':
        queryset
    }
    if django.VERSION[:2] > (1, 7):
        ctx.update(modeladmin.admin_site.each_context(request))
    else:
        ctx.update(modeladmin.admin_site.each_context())

    if django.VERSION[:2] > (1, 8):
        return render(request, tpl, context=ctx)
    else:
        return render_to_response(tpl, RequestContext(request, ctx))
예제 #9
0
    def cb_changeform_view(self, request, *args, **kwargs):
        """
        Like a change view in the admin.
        """
        view_class = kwargs.get('view_class')
        add = kwargs.get('add', True)
        obj = kwargs.get('original', None)
        object_id = kwargs.get('object_id', None)
        title = kwargs.get('title', None)

        if hasattr(view_class, 'form_class'):
            form = view_class.form_class()
        else:
            form = None
        formsets = []
        opts = self.model._meta
        TO_FIELD_VAR = False
        IS_POPUP_VAR = False
        change = not True
        view_on_site_url = None
        form_url = ''
        app_label = opts.app_label
        if form is not None:
            adminForm = helpers.AdminForm(form,
                                          formsets, {},
                                          None,
                                          model_admin=self)
            media = self.media + adminForm.media
            admin_error_list = helpers.AdminErrorList(form, formsets)
        else:
            adminForm = None
            media = self.media
            admin_error_list = None
        to_field = request.POST.get(TO_FIELD_VAR,
                                    request.GET.get(TO_FIELD_VAR))
        inline_formsets = None

        # From ``changeform_view``
        if title is None:
            title = (_('Bulk add %s') if add else _('Bulk change %s')
                     ) % force_text(opts.verbose_name_plural)
        context = dict(
            self.admin_site.each_context(request),
            title=title,
            adminform=adminForm,
            object_id=object_id,
            original=obj,
            is_popup=(IS_POPUP_VAR in request.POST
                      or IS_POPUP_VAR in request.GET),
            to_field=to_field,
            media=media,
            inline_admin_formsets=inline_formsets,
            errors=admin_error_list,
            preserved_filters=self.get_preserved_filters(request),
        )
        # From ``render_change_form``
        context.update({
            'add':
            add,
            'change':
            change,
            'has_add_permission':
            self.has_add_permission(request),
            'has_change_permission':
            self.has_change_permission(request, obj),
            'has_delete_permission':
            self.has_delete_permission(request, obj),
            'has_file_field':
            True,  # FIXME - this should check if form or formsets have a FileField,
            'has_absolute_url':
            view_on_site_url is not None,
            'absolute_url':
            view_on_site_url,
            'form_url':
            form_url,
            'opts':
            opts,
            'content_type_id':
            get_content_type_for_model(self.model).pk,
            'save_as':
            self.save_as,
            'save_on_top':
            self.save_on_top,
            'to_field_var':
            TO_FIELD_VAR,
            'is_popup_var':
            IS_POPUP_VAR,
            'app_label':
            app_label,
            'media':
            self.media,
        })

        original_get_context_data = view_class.get_context_data

        def _monkey_patch_get_context_data(instance, *args, **kwargs):
            data = original_get_context_data(instance, *args, **kwargs)
            data.update(context)
            return data

        view_class.get_context_data = _monkey_patch_get_context_data
        return view_class.as_view()(request)
예제 #10
0
파일: views.py 프로젝트: komsihon/Project4
    def post(self, request, *args, **kwargs):
        service = get_service_instance()
        config = service.config
        item_id = kwargs.get('item_id', request.POST.get('item_id'))
        item_admin = self.get_item_admin()
        ModelForm = item_admin.get_form(request)
        if item_id:
            item = get_object_or_404(Item, pk=item_id)
            form = ModelForm(request.POST, instance=item)
        else:
            form = ModelForm(request.POST)
        if form.is_valid():
            name = request.POST.get('name')
            category_id = request.POST.get('category')
            brand = request.POST.get('brand')
            reference = request.POST.get('reference')
            has_background_image = request.POST.get('has_background_image') if request.POST.get('has_background_image') else False
            original_id = request.POST.get('original_id')
            wholesale_price = request.POST.get('wholesale_price')
            try:
                retail_price = request.POST.get('retail_price')
            except:
                retail_price = 0
            max_price = request.POST.get('max_price')
            summary = request.POST.get('summary')
            description = request.POST.get('description')
            badge_text = request.POST.get('badge_text')
            size = request.POST.get('size')
            weight = request.POST.get('weight')
            stock = request.POST.get('stock')
            unit_of_measurement = request.POST.get('unit_of_measurement')
            min_order = request.POST.get('min_order')
            if not min_order:
                min_order = 1
            visible = request.POST.get('visible')
            photos_ids = request.POST.get('photos_ids')
            photos_ids_list = photos_ids.strip(',').split(',') if photos_ids else []
            category = ItemCategory.objects.get(pk=category_id)
            if retail_price and retail_price < wholesale_price:
                error = _("Retail price cannot be smaller than wholesale price.")
                context = self.get_context_data(**kwargs)
                context['error'] = error
                return render(request, self.template_name, context)
            if item_id:
                item = get_object_or_404(Item, pk=item_id)
                if getattr(settings, 'IS_PROVIDER', False):
                    if item.is_retailed:
                        error = _("Items already imported by some retailers. Delete and start again.")
                        context = self.get_context_data(**kwargs)
                        context['error'] = error
                        return render(request, self.template_name, context)

                item.on_sale = False
                if item.category != category:
                    item.category.items_count -= 1
                    item.category.save()
            else:
                if not config.is_pro_version and config.max_products == Item.objects.filter(in_trash=False).count():
                    error = _("Items cannot be added because the limit of %d items is reached." % config.max_products)
                    context = self.get_context_data(**kwargs)
                    context['error'] = error
                    return render(request, self.template_name, context)
                category.items_count = category.item_set.all().count() + 1
                item = Item(units_sold_history=[0])
            # if item.id is not None and item.provider != operator:
            #     return HttpResponseForbidden("You don't have permission to access this resource.")
            item.name = name
            item.slug = slugify(name)
            item.brand = brand
            item.summary = summary
            item.description = description
            item.badge_text = badge_text
            item.category = category
            item.reference = reference
            item.original_id = original_id
            item.size = size
            item.weight = weight
            item.has_background_image = has_background_image
            item.min_order = min_order
            item.unit_of_measurement = unit_of_measurement
            item.tags = item.slug.replace('-', ' ')
            try:
                item.stock = int(stock.strip())
            except:
                item.stock = 0
            if getattr(settings, 'IS_PROVIDER', False):
                item.wholesale_price = wholesale_price
                if max_price:
                    item.max_price = float(max_price.strip())
            item.photos = []
            if len(photos_ids_list) == 0:
                item.visible = False  # Items without photo are hidden
            else:
                item.visible = True if visible else False  # Items with photo has visibility chosen by user
                for photo_id in photos_ids_list:
                    if photo_id:
                        try:
                            photo = Photo.objects.get(pk=photo_id)
                            item.photos.append(photo)
                        except:
                            pass
            if retail_price:
                item.retail_price = retail_price
            item.provider = service
            item.save()
            category.save()
            if item_id:
                next_url = reverse('items:change_item', args=(item_id, ))
                messages.success(request, _("Items %s successfully updated." % item.name))
            else:
                next_url = reverse('items:item_list')
                messages.success(request, _("Items %s successfully created." % item.name))
            mark_duplicates(item)
            next_url = append_auth_tokens(next_url, request)
            return HttpResponseRedirect(next_url)
        else:
            context = self.get_context_data(**kwargs)
            admin_form = helpers.AdminForm(form, list(item_admin.get_fieldsets(self.request)),
                                           item_admin.get_prepopulated_fields(self.request),
                                           item_admin.get_readonly_fields(self.request))
            context['model_admin_form'] = admin_form
            messages.error(request, _("Items was not created. One ore more fields were invalid."))
            return render(request, self.template_name, context)
예제 #11
0
def graph_queryset(modeladmin, request, queryset):
    MForm = graph_form_factory(modeladmin.model)

    graph_type = table = None
    extra = '{}'
    try:
        adminaction_requested.send(sender=modeladmin.model,
                                   action='graph_queryset',
                                   request=request,
                                   queryset=queryset,
                                   modeladmin=modeladmin)
    except ActionInterrupted as e:
        messages.error(request, str(e))
        return

    if 'apply' in request.POST:
        form = MForm(request.POST)
        if form.is_valid():
            try:
                adminaction_start.send(sender=modeladmin.model,
                                       action='graph_queryset',
                                       request=request,
                                       queryset=queryset,
                                       modeladmin=modeladmin,
                                       form=form)
            except ActionInterrupted as e:
                messages.error(request, str(e))
                return
            try:
                x = form.cleaned_data['axes_x']
                #            y = form.cleaned_data['axes_y']
                graph_type = form.cleaned_data['graph_type']

                field, model, direct, m2m = modeladmin.model._meta.get_field_by_name(
                    x)
                cc = queryset.values_list(x).annotate(Count(x)).order_by()
                if isinstance(field, ForeignKey):
                    data_labels = []
                    for value, cnt in cc:
                        data_labels.append(
                            str(field.rel.to.objects.get(pk=value)))
                elif isinstance(field, BooleanField):
                    data_labels = [str(l) for l, v in cc]
                elif hasattr(modeladmin.model, 'get_%s_display' % field.name):
                    data_labels = []
                    for value, cnt in cc:
                        data_labels.append(
                            force_unicode(dict(field.flatchoices).get(
                                value, value),
                                          strings_only=True))
                else:
                    data_labels = [str(l) for l, v in cc]
                data = [v for l, v in cc]

                if graph_type == 'BarChart':
                    table = [[10, 20]]
                    extra = """{seriesDefaults:{renderer:$.jqplot.BarRenderer,
                                                rendererOptions: {fillToZero: true,
                                                                  barDirection: 'horizontal'},
                                                shadowAngle: -135,
                                               },
                                series:[%s],
                                axes: {yaxis: {renderer: $.jqplot.CategoryAxisRenderer,
                                                ticks: %s},
                                       xaxis: {pad: 1.05,
                                               tickOptions: {formatString: '%%d'}}
                                      }
                                }""" % (json.dumps(data_labels),
                                        json.dumps(data_labels))
                elif graph_type == 'PieChart':
                    table = [zip(data_labels, data)]
                    extra = """{seriesDefaults: {renderer: jQuery.jqplot.PieRenderer,
                                                rendererOptions: {fill: true,
                                                                    showDataLabels: true,
                                                                    sliceMargin: 4,
                                                                    lineWidth: 5}},
                             legend: {show: true, location: 'e'}}"""

            except Exception as e:
                messages.error(request,
                               'Unable to produce valid data: %s' % str(e))
            else:
                adminaction_end.send(sender=modeladmin.model,
                                     action='graph_queryset',
                                     request=request,
                                     queryset=queryset,
                                     modeladmin=modeladmin,
                                     form=form)
    elif request.method == 'POST':
        # total = queryset.all().count()
        initial = {
            helpers.ACTION_CHECKBOX_NAME:
            request.POST.getlist(helpers.ACTION_CHECKBOX_NAME),
            'select_across':
            request.POST.get('select_across', 0)
        }
        form = MForm(initial=initial)
    else:
        initial = {
            helpers.ACTION_CHECKBOX_NAME:
            request.POST.getlist(helpers.ACTION_CHECKBOX_NAME),
            'select_across':
            request.POST.get('select_across', 0)
        }
        form = MForm(initial=initial)

    adminForm = helpers.AdminForm(form,
                                  modeladmin.get_fieldsets(request), {}, [],
                                  model_admin=modeladmin)
    media = modeladmin.media + adminForm.media

    ctx = {
        'adminform': adminForm,
        'action': 'graph_queryset',
        'opts': modeladmin.model._meta,
        'title':
        u"Graph %s" % force_unicode(modeladmin.opts.verbose_name_plural),
        'app_label': queryset.model._meta.app_label,
        'media': media,
        'extra': extra,
        'as_json': json.dumps(table),
        'graph_type': graph_type
    }
    return render_to_response('adminactions/charts.html',
                              RequestContext(request, ctx))
예제 #12
0
    def change_view(self, request, object_id, form_url='', extra_context=None):
        """
        The 'change' admin view for this model.
        This follows closely the base implementation from Django 1.4's
        django.contrib.admin.options.ModelAdmin,
        with the explicitly marked modifications.
        """
        # pylint: disable-msg=C0103
        model = self.model
        opts = model._meta

        obj = self.get_object(request, unquote(object_id))

        if not self.has_change_permission(request, obj):
            raise PermissionDenied

        #### begin modification ####
        # make sure that the user has a full session length time for the current
        # edit activity
        request.session.set_expiry(settings.SESSION_COOKIE_AGE)
        #### end modification ####

        if obj is None:
            raise Http404(
                _('%(name)s object with primary key %(key)r does not exist.') %
                {
                    'name': force_unicode(opts.verbose_name),
                    'key': escape(object_id)
                })

        if request.method == 'POST' and "_saveasnew" in request.POST:
            return self.add_view(
                request,
                form_url=reverse('admin:%s_%s_add' %
                                 (opts.app_label, opts.module_name),
                                 current_app=self.admin_site.name))

        ModelForm = self.get_form(request, obj)
        formsets = []
        inline_instances = self.get_inline_instances(request)
        if request.method == 'POST':
            form = ModelForm(request.POST, request.FILES, instance=obj)
            if form.is_valid():
                form_validated = True
                new_object = self.save_form(request, form, change=True)
            else:
                form_validated = False
                new_object = obj

            if form_validated:
                #### begin modification ####
                self.save_model(request, new_object, form, True)
                #### end modification ####

                change_message = self.construct_change_message(
                    request, form, formsets)
                self.log_change(request, new_object, change_message)
                return self.response_change(request, new_object)

        else:
            form = ModelForm(instance=obj)

        #### begin modification ####
        media = self.media or []
        #### end modification ####
        inline_admin_formsets = []

        #### begin modification ####
        adminForm = helpers.AdminForm(form,
                                      self.get_fieldsets(request, obj),
                                      self.get_prepopulated_fields(
                                          request, obj),
                                      self.get_readonly_fields(request, obj),
                                      model_admin=self)
        media = media + adminForm.media
        #### end modification ####

        context = {
            'title': _('Change %s') % force_unicode(opts.verbose_name),
            'adminform': adminForm,
            'object_id': object_id,
            'original': obj,
            'is_popup': "_popup" in request.REQUEST or \
                        "_popup_o2m" in request.REQUEST,
            'media': media,
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            'app_label': opts.app_label,
            'kb_link': settings.KNOWLEDGE_BASE_URL,
            'comp_name': _('%s') % force_unicode(opts.verbose_name),
        }
        context.update(extra_context or {})
        return self.render_change_form(request,
                                       context,
                                       change=True,
                                       obj=obj,
                                       form_url=form_url)
예제 #13
0
    def history_form_view(self, request, object_id, version_id):
        original_opts = self.model._meta
        model = getattr(
            self.model,
            self.model._meta.simple_history_manager_attribute).model
        obj = get_object_or_404(model, **{
            original_opts.pk.attname: object_id,
            'history_id': version_id,
        }).instance
        obj._state.adding = False

        if not self.has_change_permission(request, obj):
            raise PermissionDenied

        formsets = []
        form_class = self.get_form(request, obj)
        if request.method == 'POST':
            form = form_class(request.POST, request.FILES, instance=obj)
            if form.is_valid():
                new_object = self.save_form(request, form, change=True)
                self.save_model(request, new_object, form, change=True)
                form.save_m2m()

                self.log_change(request, new_object,
                                self.construct_change_message(
                                    request, form, formsets))
                return self.response_change(request, new_object)

        else:
            form = form_class(instance=obj)

        admin_form = helpers.AdminForm(
            form,
            self.get_fieldsets(request, obj),
            self.prepopulated_fields,
            self.get_readonly_fields(request, obj),
            model_admin=self,
        )

        try:
            model_name = original_opts.model_name
        except AttributeError:  # Django < 1.7
            model_name = original_opts.module_name
        url_triplet = self.admin_site.name, original_opts.app_label, model_name
        context = {
            'title': _('Revert %s') % force_text(obj),
            'adminform': admin_form,
            'object_id': object_id,
            'original': obj,
            'is_popup': False,
            'media': mark_safe(self.media + admin_form.media),
            'errors': helpers.AdminErrorList(form, formsets),
            'app_label': model._meta.app_label,
            'original_opts': original_opts,
            'changelist_url': reverse('%s:%s_%s_changelist' % url_triplet),
            'change_url': reverse('%s:%s_%s_change' % url_triplet,
                                  args=(obj.pk,)),
            'history_url': reverse('%s:%s_%s_history' % url_triplet,
                                   args=(obj.pk,)),
            # Context variables copied from render_change_form
            'add': False,
            'change': True,
            'has_add_permission': self.has_add_permission(request),
            'has_change_permission': self.has_change_permission(request, obj),
            'has_delete_permission': self.has_delete_permission(request, obj),
            'has_file_field': True,
            'has_absolute_url': False,
            'form_url': '',
            'opts': model._meta,
            'content_type_id': ContentType.objects.get_for_model(
                self.model).id,
            'save_as': self.save_as,
            'save_on_top': self.save_on_top,
            'root_path': getattr(self.admin_site, 'root_path', None),
        }
        return render(request, template_name=self.object_history_form_template,
                      dictionary=context, current_app=self.admin_site.name)
예제 #14
0
    def _match_view(self, request, object_id, extra_context=None):
        """
        The 'match list' view for this model.
        """
        from django.contrib.admin.views.main import ERROR_FLAG

        if self.match_parent_model is None:
            match_parent_sitemodel = self
        else:
            match_parent_sitemodel = self.admin_site._registry[
                self.match_parent_model]

        match_child_sitemodel = self.admin_site._registry[
            self.match_child_model]

        opts = match_child_sitemodel.model._meta

        # opts = self.model._meta
        app_label = opts.app_label
        if not self.has_permission(request, 'match'):
            raise PermissionDenied

        match_list_display = self.match_list_display
        match_list_display_links = match_child_sitemodel.get_list_display_links(
            request, match_list_display)
        match_list_filter = match_child_sitemodel.get_list_filter(request)
        match_top_filters = match_child_sitemodel.get_top_filters(request)
        match_date_hierarchy = self.match_date_hierarchy
        match_list_search_fields = self.match_list_search_fields
        match_list_select_related = self.match_list_select_related
        match_list_per_page = self.match_list_per_page
        match_list_max_show_all = self.match_list_max_show_all
        match_list_editable = self.match_list_editable

        to_field = request.POST.get(TO_FIELD_VAR,
                                    request.GET.get(TO_FIELD_VAR))

        obj = self.get_object(request, unquote(object_id), to_field)

        if not self.has_permission(request, 'match', obj):
            raise PermissionDenied

        if obj is None:
            return self._get_obj_does_not_exist_redirect(
                request, opts, object_id)

        MatchList = self.get_matchlist(request)
        try:
            cl = MatchList(request, match_list_display,
                           match_list_display_links, match_list_filter,
                           match_top_filters, match_date_hierarchy,
                           match_list_search_fields, match_list_select_related,
                           match_list_per_page, match_list_max_show_all,
                           match_list_editable, match_parent_sitemodel,
                           object_id, match_child_sitemodel)
        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 SimpleTemplateResponse('admin/invalid_setup.html', {
                    'title': _('Database error'),
                })
            return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1')

        # If we're allowing changelist editing, we need to construct a formset
        # for the changelist given all the fields to be edited. Then we'll
        # use the formset to validate/process POSTed data.
        formset = cl.formset = None

        # Handle POSTed bulk-edit data.
        if request.method == 'POST' and '_save' in request.POST:
            FormSet = self.get_matchlist_formset(request)
            formset = cl.formset = FormSet(request.POST,
                                           request.FILES,
                                           queryset=self.get_queryset(request))
            if formset.is_valid():
                matches = self.build_matches(formset.forms)
                try:
                    self.save_matches(obj, matches)
                    msg = "Matched successfully."
                    self.message_user(request, msg, messages.SUCCESS)
                except ValidationError as ex:
                    for message in ex.messages:
                        self.message_user(request, message, messages.ERROR)

            return HttpResponseRedirect(request.get_full_path())

        # Handle GET -- construct a formset for display.
        elif cl.list_editable:
            FormSet = self.get_matchlist_formset(request)
            formset = cl.formset = FormSet(queryset=cl.result_list)

        ModelForm = self.get_form(request, obj)

        form = ModelForm(instance=obj)
        formsets, inline_instances = self._create_formsets(request,
                                                           obj,
                                                           change=True)

        adminForm = helpers.AdminForm(
            form,
            list(self.get_match_parent_fieldsets(request, obj)),
            self.get_prepopulated_fields(request, obj),
            self.get_match_parent_readonly_fields(request, obj),
            model_admin=self)
        media = self.media + adminForm.media

        # Build the list of media to be used by the formset.
        if formset:
            media += self.media + formset.media
        else:
            media += self.media

        action_form = None

        selection_note_all = ungettext('%(total_count)s selected',
                                       'All %(total_count)s selected',
                                       cl.result_count)

        ModelForm = self.get_form(request, obj)
        form = ModelForm(instance=obj)
        formsets, inline_instances = self._create_formsets(request,
                                                           obj,
                                                           change=True)

        context = dict(
            self.admin_site.each_context(request),
            title=_('Change %s') % force_text(opts.verbose_name),
            adminform=adminForm,
            change=True,
            object_id=object_id,
            original=obj,
            save_as=False,
            change_actions=False,
            show_save=False,
            show_save_and_continue=False,
            has_add_permission=False,
            has_change_permission=True,
            has_delete_permission=False,
            is_popup=(IS_POPUP_VAR in request.POST
                      or IS_POPUP_VAR in request.GET),
            to_field=to_field,
            media=media,
            inline_admin_formsets=[],
            errors=helpers.AdminErrorList(form, formsets),
            preserved_filters=self.get_preserved_filters(request),
            module_name=force_text(opts.verbose_name_plural),
            selection_note=_('0 of %(cnt)s selected') %
            {'cnt': len(cl.result_list)},
            selection_note_all=selection_note_all %
            {'total_count': cl.result_count},
            cl=cl,
            opts=cl.opts,
            action_form=action_form,
            actions_on_top=self.actions_on_top,
            actions_on_bottom=self.actions_on_bottom,
            actions_selection_counter=self.actions_selection_counter,
        )
        context.update(self.get_model_extra_context(request))
        context.update(extra_context or {})

        request.current_app = self.admin_site.name

        return TemplateResponse(request, 'finance/match.html', context)
예제 #15
0
def base_export(
    modeladmin,
    request,
    queryset,
    title,
    impl,  # noqa
    name,
    action_short_description,
    template,
    form_class,
):
    """
        export a queryset to csv file
    """
    opts = modeladmin.model._meta
    perm = "{0}.{1}".format(
        opts.app_label, get_permission_codename('adminactions_export', opts))
    if not request.user.has_perm(perm):
        messages.error(
            request, _('Sorry you do not have rights to execute this action'))
        return

    try:
        adminaction_requested.send(sender=modeladmin.model,
                                   action=name,
                                   request=request,
                                   queryset=queryset,
                                   modeladmin=modeladmin)
    except ActionInterrupted as e:
        messages.error(request, str(e))
        return

    cols = [(f.name, f.verbose_name) for f in queryset.model._meta.fields +
            queryset.model._meta.many_to_many]
    initial = {
        '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME),
        'select_across': request.POST.get('select_across') == '1',
        'action': get_action(request),
        'columns': [x for x, v in cols]
    }
    if initial["action"] == "export_as_csv":
        initial.update(
            getattr(settings, "ADMINACTIONS_CSV_OPTIONS_DEFAULT", {}))

    if 'apply' in request.POST:
        form = form_class(request.POST)
        form.fields['columns'].choices = cols
        if form.is_valid():
            try:
                adminaction_start.send(sender=modeladmin.model,
                                       action=name,
                                       request=request,
                                       queryset=queryset,
                                       modeladmin=modeladmin,
                                       form=form)
            except ActionInterrupted as e:
                messages.error(request, str(e))
                return

            if hasattr(modeladmin, 'get_%s_filename' % name):
                filename = modeladmin.get_export_as_csv_filename(
                    request, queryset)
            else:
                filename = None
            try:
                response = impl(queryset,
                                fields=form.cleaned_data['columns'],
                                header=form.cleaned_data.get('header', False),
                                filename=filename,
                                options=form.cleaned_data)
            except Exception as e:
                messages.error(request, "Error: (%s)" % str(e))
            else:
                adminaction_end.send(sender=modeladmin.model,
                                     action=name,
                                     request=request,
                                     queryset=queryset,
                                     modeladmin=modeladmin,
                                     form=form)
                return response
    else:
        form = form_class(initial=initial)
        form.fields['columns'].choices = cols

    adminForm = helpers.AdminForm(form,
                                  modeladmin.get_fieldsets(request), {}, [],
                                  model_admin=modeladmin)
    media = modeladmin.media + adminForm.media
    # tpl = 'adminactions/export_csv.html'
    ctx = {
        'adminform': adminForm,
        'change': True,
        'action_short_description': action_short_description,
        'title': title,
        'is_popup': False,
        'save_as': False,
        'has_delete_permission': False,
        'has_add_permission': False,
        'has_change_permission': True,
        'queryset': queryset,
        'opts': queryset.model._meta,
        'app_label': queryset.model._meta.app_label,
        'media': mark_safe(media)
    }
    ctx.update(modeladmin.admin_site.each_context(request))
    return render(request, template, ctx)
예제 #16
0
def merge(modeladmin, request, queryset):
    """
    Merge two model instances. Move all foreign keys.

    """

    def raw_widget(field, **kwargs):
        """ force all fields as not required"""
        kwargs['widget'] = TextInput({'class': 'raw-value', 'readonly': 'readonly'})
        kwargs['widget'] = TextInput({'class': 'raw-value', 'size': '30'})
        return field.formfield(**kwargs)

        # Allows to specified a custom Form in the ModelAdmin

    #    MForm = getattr(modeladmin, 'merge_form', MergeForm)
    merge_form = getattr(modeladmin, 'merge_form', MergeForm)
    MForm = modelform_factory(modeladmin.model, form=merge_form, formfield_callback=raw_widget)
    OForm = modelform_factory(modeladmin.model, formfield_callback=raw_widget)
    tpl = 'adminactions/merge.html'

    ctx = {
        '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME),
        'select_across': request.POST.get('select_across') == '1',
        'action': request.POST.get('action'),
        'fields': [f for f in queryset.model._meta.fields if not f.primary_key and f.editable],
        'app_label': queryset.model._meta.app_label,
        'result': '',
        'opts': queryset.model._meta}

    if 'preview' in request.POST:
        master = queryset.get(pk=request.POST.get('master_pk'))
        original = clone_instance(master)
        other = queryset.get(pk=request.POST.get('other_pk'))
        formset = formset_factory(OForm)(initial=[model_to_dict(master), model_to_dict(other)])
        with transaction.commit_manually():
            form = MForm(request.POST, instance=master)
            other.delete()
            form_is_valid = form.is_valid()
            transaction.rollback()
        if form_is_valid:
            ctx.update({'original': original})
            tpl = 'adminactions/merge_preview.html'
    elif 'apply' in request.POST:
        master = queryset.get(pk=request.POST.get('master_pk'))
        other = queryset.get(pk=request.POST.get('other_pk'))
        formset = formset_factory(OForm)(initial=[model_to_dict(master), model_to_dict(other)])
        with transaction.commit_manually():
            form = MForm(request.POST, instance=master)
            other.delete()
            if form.is_valid():
                form.save()
                transaction.commit()
                return HttpResponseRedirect(request.path)
            else:
                messages.error(request, form.errors)
                transaction.rollback()
    else:
        try:
            master, other = queryset.all()
        except ValueError:
            messages.error(request, _('Please select exactly 2 records'))
            return

        initial = {'_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME),
                   'select_across': 0,
                   'generic': MergeForm.GEN_IGNORE,
                   'dependencies': MergeForm.DEP_MOVE,
                   'action': 'merge',
                   'master_pk': master.pk,
                   'other_pk': other.pk}
        formset = formset_factory(OForm)(initial=[model_to_dict(master), model_to_dict(other)])
        form = MForm(initial=initial, instance=master)

    adminForm = helpers.AdminForm(form, modeladmin.get_fieldsets(request), {}, [], model_admin=modeladmin)
    media = modeladmin.media + adminForm.media
    ctx.update({'adminform': adminForm,
                'formset': formset,
                'media': mark_safe(media),
                'master': master,
                'other': other})
    return render_to_response(tpl, RequestContext(request, ctx))
예제 #17
0
def export_delete_tree(modeladmin, request, queryset):  # noqa
    """
    Export as fixture selected queryset and all the records that belong to.
    That mean that dump what will be deleted if the queryset was deleted
    """
    opts = modeladmin.model._meta
    perm = "{0}.{1}".format(
        opts.app_label, get_permission_codename('adminactions_export', opts))
    if not request.user.has_perm(perm):
        messages.error(
            request, _('Sorry you do not have rights to execute this action'))
        return
    try:
        adminaction_requested.send(sender=modeladmin.model,
                                   action='export_delete_tree',
                                   request=request,
                                   queryset=queryset,
                                   modeladmin=modeladmin)
    except ActionInterrupted as e:
        messages.error(request, str(e))
        return

    initial = {
        '_selected_action': request.POST.getlist(helpers.ACTION_CHECKBOX_NAME),
        'select_across': request.POST.get('select_across') == '1',
        'action': get_action(request),
        'serializer': 'json',
        'indent': 4
    }

    if 'apply' in request.POST:
        form = FixtureOptions(request.POST)
        if form.is_valid():
            try:
                adminaction_start.send(sender=modeladmin.model,
                                       action='export_delete_tree',
                                       request=request,
                                       queryset=queryset,
                                       modeladmin=modeladmin,
                                       form=form)
            except ActionInterrupted as e:
                messages.error(request, str(e))
                return
            try:
                collect_related = form.cleaned_data.get('add_foreign_keys')
                using = router.db_for_write(modeladmin.model)

                c = Collector(using)
                c.collect(queryset, collect_related=collect_related)
                data = []
                for model, instances in list(c.data.items()):
                    data.extend(instances)
                adminaction_end.send(sender=modeladmin.model,
                                     action='export_delete_tree',
                                     request=request,
                                     queryset=queryset,
                                     modeladmin=modeladmin,
                                     form=form)
                if hasattr(modeladmin, 'get_export_delete_tree_filename'):
                    filename = modeladmin.get_export_delete_tree_filename(
                        request, queryset)
                else:
                    filename = None
                return _dump_qs(form, queryset, data, filename)
            except AttributeError as e:
                messages.error(request, str(e))
                return HttpResponseRedirect(request.path)
    else:
        form = FixtureOptions(initial=initial)

    adminForm = helpers.AdminForm(form,
                                  modeladmin.get_fieldsets(request), {},
                                  model_admin=modeladmin)
    media = modeladmin.media + adminForm.media
    tpl = 'adminactions/export_fixture.html'
    ctx = {
        'adminform':
        adminForm,
        'change':
        True,
        'action_short_description':
        export_delete_tree.short_description,
        'title':
        u"%s (%s)" % (
            export_delete_tree.short_description.capitalize(),
            modeladmin.opts.verbose_name_plural,
        ),
        'is_popup':
        False,
        'save_as':
        False,
        'has_delete_permission':
        False,
        'has_add_permission':
        False,
        'has_change_permission':
        True,
        'queryset':
        queryset,
        'opts':
        queryset.model._meta,
        'app_label':
        queryset.model._meta.app_label,
        'media':
        mark_safe(media)
    }
    ctx.update(modeladmin.admin_site.each_context(request))
    return render(request, tpl, ctx)
예제 #18
0
    def view_view(self, request, object_id, extra_context=None):
        "The 'View' admin view for this model."

        obj = self.get_object(request, unquote(object_id))
        if self.has_change_permission(request, obj):
            request.feed_upload_status.update_with_object(obj, fail_silently=True)

        model = self.model
        opts = model._meta

        try:
            obj = self.queryset(request).get(pk=unquote(object_id))
        except model.DoesNotExist:
            # Don't raise Http404 just yet, because we haven't checked
            # permissions yet. We don't want an unauthenticated user to be able
            # to determine whether a given object exists.
            obj = None

        #if not self.has_change_permission(request, obj):
        #    raise PermissionDenied

        if obj is None:
            raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_unicode(opts.verbose_name), 'key': escape(object_id)})

        if request.method == 'POST' and request.POST.has_key("_saveasnew"):
            return self.add_view(request, form_url='../add/')

        ModelForm = self.get_form(request, obj)
        formsets = []

        form = ModelForm(instance=obj)

        prefixes = {}
        for FormSet in self.get_view_formsets(request, obj):
            prefix = FormSet.get_default_prefix()
            prefixes[prefix] = prefixes.get(prefix, 0) + 1
            if prefixes[prefix] != 1:
                prefix = "%s-%s" % (prefix, prefixes[prefix])
            formset = FormSet(instance=obj, prefix=prefix)
            formsets.append(formset)

        adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields)
        media = self.media + adminForm.media

        inline_admin_formsets = []
        for inline, formset in zip(self.view_inline_instances, formsets):
            fieldsets = list(inline.get_fieldsets(request, obj))
            inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets)
            inline_admin_formsets.append(inline_admin_formset)
            media = media + inline_admin_formset.media

        registry = []
        for r in self.admin_site._registry:
            registry.append(r._meta.verbose_name.lower())

        context = {
            'title': _('View %s') % force_unicode(opts.verbose_name),
            'adminform': adminForm,
            'object_id': object_id,
            'original': obj,
            'cloneable': obj.cloneable(),
            'is_popup': request.REQUEST.has_key('_popup'),
            'tabbed': self.tabbed,
            'tab_name': self.tab_name,
            'media': mark_safe(media),
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            'root_path': reverse('admin:index'),
            'app_label': opts.app_label,
            'registry': registry,
        }

        context.update(extra_context or {})
        return self.render_view_view(request, context, obj=obj)
예제 #19
0
    def mass_change_view(self,
                         request,
                         comma_separated_object_ids,
                         extra_context=None):
        """The 'mass change' admin view for this model."""
        global new_object
        model = self.model
        opts = model._meta
        general_error = None

        # Allow model to hide some fields for mass admin
        exclude_fields = getattr(self.admin_obj, "massadmin_exclude", ())
        queryset = getattr(self.admin_obj, "massadmin_queryset",
                           self.get_queryset)(request)

        object_ids = comma_separated_object_ids.split(',')
        object_id = object_ids[0]

        try:
            obj = queryset.get(pk=unquote(object_id))
        except model.DoesNotExist:
            obj = None

        # TODO It's necessary to check permission and existence for all object
        if not self.has_change_permission(request, obj):
            raise PermissionDenied

        if obj is None:
            raise Http404(
                _('%(name)s object with primary key %(key)r does not exist.') %
                {
                    'name': force_text(opts.verbose_name),
                    'key': escape(object_id)
                })

        ModelForm = self.get_form(request, obj)
        formsets = []
        errors, errors_list = None, None
        mass_changes_fields = request.POST.getlist("_mass_change")
        if request.method == 'POST':
            # commit only when all forms are valid
            try:
                with transaction.atomic():
                    objects_count = 0
                    changed_count = 0
                    objects = queryset.filter(pk__in=object_ids)
                    for obj in objects:
                        objects_count += 1
                        form = ModelForm(request.POST,
                                         request.FILES,
                                         instance=obj)

                        exclude = []
                        for fieldname, field in list(form.fields.items()):
                            if fieldname not in mass_changes_fields:
                                exclude.append(fieldname)

                        for exclude_fieldname in exclude:
                            del form.fields[exclude_fieldname]

                        if form.is_valid():
                            form_validated = True
                            new_object = self.save_form(request,
                                                        form,
                                                        change=True)
                        else:
                            form_validated = False
                            new_object = obj
                        prefixes = {}
                        for FormSet in get_formsets(self, request, new_object):
                            prefix = FormSet.get_default_prefix()
                            prefixes[prefix] = prefixes.get(prefix, 0) + 1
                            if prefixes[prefix] != 1:
                                prefix = "%s-%s" % (prefix, prefixes[prefix])
                            if prefix in mass_changes_fields:
                                formset = FormSet(request.POST,
                                                  request.FILES,
                                                  instance=new_object,
                                                  prefix=prefix)
                                formsets.append(formset)

                        if all_valid(formsets) and form_validated:
                            # self.admin_obj.save_model(request, new_object, form, change=True)
                            self.save_model(request,
                                            new_object,
                                            form,
                                            change=True)
                            form.save_m2m()
                            for formset in formsets:
                                self.save_formset(request,
                                                  form,
                                                  formset,
                                                  change=True)

                            change_message = self.construct_change_message(
                                request, form, formsets)
                            self.log_change(request, new_object,
                                            change_message)
                            changed_count += 1

                    if changed_count == objects_count:
                        return self.response_change(request, new_object)
                    else:
                        errors = form.errors
                        errors_list = helpers.AdminErrorList(form, formsets)
                        # Raise error for rollback transaction in atomic block
                        raise ValidationError("Not all forms is correct")

            except:
                general_error = sys.exc_info()[1]

        form = ModelForm(instance=obj)
        form._errors = errors
        prefixes = {}
        for FormSet in get_formsets(self, request, obj):
            prefix = FormSet.get_default_prefix()
            prefixes[prefix] = prefixes.get(prefix, 0) + 1
            if prefixes[prefix] != 1:
                prefix = "%s-%s" % (prefix, prefixes[prefix])
            formset = FormSet(instance=obj, prefix=prefix)
            formsets.append(formset)

        adminForm = helpers.AdminForm(form,
                                      self.get_fieldsets(request, obj),
                                      self.prepopulated_fields,
                                      self.get_readonly_fields(request, obj),
                                      model_admin=self.admin_obj)
        media = self.media + adminForm.media

        # We don't want the user trying to mass change unique fields!
        unique_fields = []
        try:  # Django >= 1.9
            fields = model._meta.get_fields()
        except:
            fields = model._meta.get_all_field_names()
        for field_name in fields:
            try:
                field = model._meta.get_field(field_name)
                if field.unique:
                    unique_fields.append(field_name)
            except:
                pass

        # Buggy! Use at your own risk
        #inline_admin_formsets = []
        # for inline, formset in zip(self.inline_instances, formsets):
        #    fieldsets = list(inline.get_fieldsets(request, obj))
        #    inline_admin_formset = helpers.InlineAdminFormSet(inline, formset, fieldsets)
        #    inline_admin_formsets.append(inline_admin_formset)
        #    media = media + inline_admin_formset.media

        context = {
            **self.admin_site.each_context(request),
            'title':
            _('Change %s') % force_text(opts.verbose_name),
            'adminform':
            adminForm,
            'object_id':
            object_id,
            'original':
            obj,
            'unique_fields':
            unique_fields,
            'exclude_fields':
            exclude_fields,
            'is_popup':
            '_popup' in request.GET or '_popup' in request.POST,
            'media':
            mark_safe(media),
            #'inline_admin_formsets': inline_admin_formsets,
            'errors':
            errors_list,
            'general_error':
            general_error,
            'app_label':
            opts.app_label,
            'object_ids':
            comma_separated_object_ids,
            'mass_changes_fields':
            mass_changes_fields,
        }
        context.update(extra_context or {})
        return self.render_mass_change_form(request,
                                            context,
                                            change=True,
                                            obj=obj)
예제 #20
0
    def history_form_view(self,
                          request,
                          object_id,
                          version_id,
                          extra_context=None):
        request.current_app = self.admin_site.name
        original_opts = self.model._meta
        model = getattr(
            self.model,
            self.model._meta.simple_history_manager_attribute).model
        obj = get_object_or_404(
            model, **{
                original_opts.pk.attname: object_id,
                "history_id": version_id
            }).instance
        obj._state.adding = False

        if not self.has_change_permission(request, obj):
            raise PermissionDenied

        if SIMPLE_HISTORY_EDIT:
            change_history = True
        else:
            change_history = False

        if "_change_history" in request.POST and SIMPLE_HISTORY_EDIT:
            history = utils.get_history_manager_for_model(obj)
            obj = history.get(pk=version_id).instance

        formsets = []
        form_class = self.get_form(request, obj)
        if request.method == "POST":
            form = form_class(request.POST, request.FILES, instance=obj)
            if form.is_valid():
                new_object = self.save_form(request, form, change=True)
                self.save_model(request, new_object, form, change=True)
                form.save_m2m()

                self.log_change(
                    request,
                    new_object,
                    self.construct_change_message(request, form, formsets),
                )
                return self.response_change(request, new_object)

        else:
            form = form_class(instance=obj)

        admin_form = helpers.AdminForm(
            form,
            self.get_fieldsets(request, obj),
            self.prepopulated_fields,
            self.get_readonly_fields(request, obj),
            model_admin=self,
        )

        model_name = original_opts.model_name
        url_triplet = self.admin_site.name, original_opts.app_label, model_name
        context = {
            "title":
            self.history_form_view_title(obj),
            "adminform":
            admin_form,
            "object_id":
            object_id,
            "original":
            obj,
            "is_popup":
            False,
            "media":
            mark_safe(self.media + admin_form.media),
            "errors":
            helpers.AdminErrorList(form, formsets),
            "app_label":
            original_opts.app_label,
            "original_opts":
            original_opts,
            "changelist_url":
            reverse("%s:%s_%s_changelist" % url_triplet),
            "change_url":
            reverse("%s:%s_%s_change" % url_triplet, args=(obj.pk, )),
            "history_url":
            reverse("%s:%s_%s_history" % url_triplet, args=(obj.pk, )),
            "change_history":
            change_history,
            "revert_disabled":
            self.revert_disabled,
            # Context variables copied from render_change_form
            "add":
            False,
            "change":
            True,
            "has_add_permission":
            self.has_add_permission(request),
            "has_change_permission":
            self.has_change_permission(request, obj),
            "has_delete_permission":
            self.has_delete_permission(request, obj),
            "has_file_field":
            True,
            "has_absolute_url":
            False,
            "form_url":
            "",
            "opts":
            model._meta,
            "content_type_id":
            self.content_type_model_cls.objects.get_for_model(self.model).id,
            "save_as":
            self.save_as,
            "save_on_top":
            self.save_on_top,
            "root_path":
            getattr(self.admin_site, "root_path", None),
        }
        context.update(self.admin_site.each_context(request))
        context.update(extra_context or {})
        extra_kwargs = {}
        return self.render_history_view(request,
                                        self.object_history_form_template,
                                        context, **extra_kwargs)
예제 #21
0
파일: admin.py 프로젝트: sjl/stoat
    def _django_change_view(self, request, object_id, extra_context=None):
        "The 'change' admin view for this model."
        model = self.model
        opts = model._meta

        obj = self.get_object(request, unquote(object_id))
        previous_template = obj.template  # STOAT: Save previous template

        if not self.has_change_permission(request, obj):
            raise PermissionDenied

        if obj is None:
            raise Http404(
                _('%(name)s object with primary key %(key)r does not exist.') %
                {
                    'name': force_unicode(opts.verbose_name),
                    'key': escape(object_id)
                })

        if request.method == 'POST' and "_saveasnew" in request.POST:
            return self.add_view(request, form_url='../add/')

        ModelForm = self.get_form(request, obj)
        formsets = []
        if request.method == 'POST':
            form = ModelForm(request.POST, request.FILES, instance=obj)
            if form.is_valid():
                form_validated = True
                new_object = self.save_form(request, form, change=True)
            else:
                form_validated = False
                new_object = obj
            prefixes = {}
            if previous_template == new_object.template:  # STOAT: Template check
                for FormSet, inline in zip(
                        self.get_formsets(request, new_object),
                        self._create_inlines(obj)):  # STOAT: _create_inlines
                    prefix = FormSet.get_default_prefix()
                    prefixes[prefix] = prefixes.get(prefix, 0) + 1
                    if prefixes[prefix] != 1:
                        prefix = "%s-%s" % (prefix, prefixes[prefix])
                    formset = FormSet(request.POST,
                                      request.FILES,
                                      instance=new_object,
                                      prefix=prefix,
                                      queryset=inline.queryset(request))

                    formsets.append(formset)

            if all_valid(formsets) and form_validated:
                self.save_model(request, new_object, form, change=True)
                form.save_m2m()
                for formset in formsets:
                    self.save_formset(request, form, formset, change=True)

                change_message = self.construct_change_message(
                    request, form, formsets)
                self.log_change(request, new_object, change_message)
                return self.response_change(request, new_object)

        else:
            form = ModelForm(instance=obj)
            prefixes = {}
            for FormSet, inline in zip(
                    self.get_formsets(request, obj),
                    self._create_inlines(obj)):  # STOAT: _create_inlines
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(instance=obj,
                                  prefix=prefix,
                                  queryset=inline.queryset(request))
                formsets.append(formset)

        adminForm = helpers.AdminForm(form,
                                      self.get_fieldsets(request, obj),
                                      self.prepopulated_fields,
                                      self.get_readonly_fields(request, obj),
                                      model_admin=self)
        media = self.media + adminForm.media

        inline_admin_formsets = []
        for inline, formset in zip(self._create_inlines(obj),
                                   formsets):  # STOAT: _create_inlines
            fieldsets = list(inline.get_fieldsets(request, obj))
            readonly = list(inline.get_readonly_fields(request, obj))
            inline_admin_formset = helpers.InlineAdminFormSet(inline,
                                                              formset,
                                                              fieldsets,
                                                              readonly,
                                                              model_admin=self)
            inline_admin_formsets.append(inline_admin_formset)
            media = media + inline_admin_formset.media

        media = media + extra_context.pop('media')  # STOAT
        context = {
            'title': _('Change %s') % force_unicode(opts.verbose_name),
            'adminform': adminForm,
            'object_id': object_id,
            'original': obj,
            'is_popup': "_popup" in request.REQUEST,
            'media': mark_safe(media),
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            'root_path': self.admin_site.root_path,
            'app_label': opts.app_label,
        }
        context.update(extra_context or {})
        return self.render_change_form(request, context, change=True, obj=obj)
예제 #22
0
    def history_form_view(self, request, object_id, version_id):
        request.current_app = self.admin_site.name
        original_opts = self.model._meta
        model = getattr(
            self.model,
            self.model._meta.simple_history_manager_attribute).model
        historical_obj = get_object_or_404(
            model, **{
                original_opts.pk.attname: object_id,
                'history_id': version_id,
            })
        obj = historical_obj.instance
        obj._state.adding = False

        if not self.has_change_permission(request, obj):
            raise PermissionDenied

        if SIMPLE_HISTORY_EDIT:
            change_history = True
        else:
            change_history = False

        if '_change_history' in request.POST and SIMPLE_HISTORY_EDIT:
            obj = obj.history.get(pk=version_id).instance

        formsets = []
        form_class = self.get_form(request, obj)
        if request.method == 'POST':
            form = form_class(request.POST, request.FILES, instance=obj)
            if form.is_valid():
                new_object = self.save_form(request, form, change=True)
                self.save_model(request, new_object, form, change=True)
                form.save_m2m()

                self.log_change(
                    request, new_object,
                    self.construct_change_message(request, form, formsets))
                return self.response_change(request, new_object)

        else:
            form = form_class(instance=obj)

        admin_form = helpers.AdminForm(
            form,
            self.get_fieldsets(request, obj),
            self.prepopulated_fields,
            self.get_readonly_fields(request, obj),
            model_admin=self,
        )

        model_name = original_opts.model_name
        url_triplet = self.admin_site.name, original_opts.app_label, model_name

        inline_instances = self.get_inline_instances(request, obj)
        prefixes = {}
        formset = []

        historical_date = historical_obj.history_date
        adjusted_historical_date = historical_date + datetime.timedelta(
            seconds=5)
        for FormSet, inline in self.get_admin_formsets_with_inline(*[request]):
            prefix = FormSet.get_default_prefix()
            prefixes[prefix] = prefixes.get(prefix, 0) + 1
            if prefixes[prefix] != 1 or not prefix:
                prefix = "%s-%s" % (prefix, prefixes[prefix])

            inline_qs = inline.get_queryset(request)
            inline_ids = inline_qs.values_list('id', flat=True)
            history_inline_model = inline_qs.first().history.model
            historical_ids = history_inline_model.objects\
                                    .filter(id__in=inline_ids, history_date__lte=adjusted_historical_date)\
                                    .order_by('-history_date')[:inline_qs.count()]\
                                    .values_list('history_id', flat=True)
            historical_queryset = history_inline_model.objects.filter(
                history_id__in=historical_ids)

            formset_params = {
                'instance': obj,
                'prefix': prefix,
                'queryset': historical_queryset,
            }
            if request.method == 'POST':
                formset_params.update({
                    'data':
                    request.POST.copy(),
                    'files':
                    request.FILES,
                    'save_as_new':
                    '_saveasnew' in request.POST
                })
            formset.append(FormSet(**formset_params))

        inline_formsets = self.get_admin_inline_formsets(
            request, formset, inline_instances, obj)
        context = {
            'title':
            _('Revert %s') % force_text(obj),
            'adminform':
            admin_form,
            'object_id':
            object_id,
            'original':
            obj,
            'is_popup':
            False,
            'media':
            mark_safe(self.media + admin_form.media),
            'errors':
            helpers.AdminErrorList(form, formsets),
            'app_label':
            original_opts.app_label,
            'original_opts':
            original_opts,
            'changelist_url':
            reverse('%s:%s_%s_changelist' % url_triplet),
            'change_url':
            reverse('%s:%s_%s_change' % url_triplet, args=(obj.pk, )),
            'history_url':
            reverse('%s:%s_%s_history' % url_triplet, args=(obj.pk, )),
            'change_history':
            change_history,
            'inline_admin_formsets':
            inline_formsets,
            # Context variables copied from render_change_form
            'add':
            False,
            'change':
            True,
            'has_add_permission':
            self.has_add_permission(request),
            'has_change_permission':
            self.has_change_permission(request, obj),
            'has_delete_permission':
            self.has_delete_permission(request, obj),
            'has_file_field':
            True,
            'has_absolute_url':
            False,
            'form_url':
            '',
            'opts':
            model._meta,
            'content_type_id':
            ContentType.objects.get_for_model(self.model).id,
            'save_as':
            self.save_as,
            'save_on_top':
            self.save_on_top,
            'root_path':
            getattr(self.admin_site, 'root_path', None),
        }
        extra_kwargs = {}
        if get_complete_version() < (1, 8):
            extra_kwargs['current_app'] = request.current_app
        return render(request, self.object_history_form_template, context,
                      **extra_kwargs)
예제 #23
0
    def change_view(self, request, object_id, form_url='', extra_context=None):
        "The 'change' admin view for this model."
        model = self.model
        opts = model._meta

        obj = self.get_object(request, unquote(object_id))

        if not self.has_change_permission(request, obj):
            raise PermissionDenied

        if obj is None:
            raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_text(opts.verbose_name), 'key': escape(object_id)})

        if request.method == 'POST' and "_saveasnew" in request.POST:
            return self.add_view(request, form_url=reverse('admin:%s_%s_add' %
                                                           (opts.app_label, opts.module_name),
                current_app=self.admin_site.name))

        ModelForm = self.get_form(request, obj)
        formsets = []
        inline_instances = self.get_inline_instances(request, obj)
        if request.method == 'POST':
            form = ModelForm(request.POST, request.FILES, instance=obj)
            if form.is_valid():
                form_validated = True
                new_object = self.save_form(request, form, change=True)
            else:
                form_validated = False
                new_object = obj
            prefixes = {}
            for FormSet, inline in self.get_formsets_with_inlines(request, new_object):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1 or not prefix:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(request.POST, request.FILES,
                    instance=new_object, prefix=prefix,
                    queryset=inline.get_queryset(request))
                formsets.append(formset)
                if hasattr(inline, 'inlines') and inline.inlines:
                    self.add_nested_inline_formsets(request, inline, formset)

            if self.all_valid_with_nesting(formsets) and form_validated:
                self.save_model(request, new_object, form, True)
                self.save_related(request, form, formsets, True)
                change_message = self.construct_change_message(request, form, formsets)
                self.log_change(request, new_object, change_message)
                return self.response_change(request, new_object)

        else:
            form = ModelForm(instance=obj)
            prefixes = {}
            for FormSet, inline in self.get_formsets_with_inlines(request, obj):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1 or not prefix:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(instance=obj, prefix=prefix,
                    queryset=inline.get_queryset(request))
                formsets.append(formset)
                if hasattr(inline, 'inlines') and inline.inlines:
                    self.add_nested_inline_formsets(request, inline, formset)

        adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj),
            self.get_prepopulated_fields(request, obj),
            self.get_readonly_fields(request, obj),
            model_admin=self)
        media = self.media + adminForm.media

        inline_admin_formsets = []
        for inline, formset in zip(inline_instances, formsets):
            fieldsets = list(inline.get_fieldsets(request, obj))
            readonly = list(inline.get_readonly_fields(request, obj))
            prepopulated = dict(inline.get_prepopulated_fields(request, obj))
            inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
                fieldsets, prepopulated, readonly, model_admin=self)
            inline_admin_formsets.append(inline_admin_formset)
            media = media + inline_admin_formset.media
            if hasattr(inline, 'inlines') and inline.inlines:
                other_media = self.wrap_nested_inline_formsets(request, inline, formset)
                if other_media is not None:
                    media += other_media

        context = {
            'title': _('Change %s') % force_text(opts.verbose_name),
            'adminform': adminForm,
            'object_id': object_id,
            'original': obj,
            'is_popup': "_popup" in request.GET,
            'media': media,
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            'app_label': opts.app_label,
            }
        context.update(self.admin_site.each_context(request))
        context.update(extra_context or {})
        return self.render_change_form(request, context, change=True, obj=obj, form_url=form_url)
예제 #24
0
    def _changeform_view(self, request, object_id, form_url, extra_context):
        add = object_id is None

        model = self.model
        opts = model._meta

        if add:
            if not self.has_add_permission(request):
                raise PermissionDenied
            obj = None

        else:
            obj = self.get_object(request, unquote(object_id))

            if request.method == 'POST':
                if not self.has_change_permission(request, obj):
                    raise PermissionDenied
            else:
                if not self.has_view_or_change_permission(request, obj):
                    raise PermissionDenied

            if obj is None:
                return self._get_obj_does_not_exist_redirect(
                    request, opts, object_id)

        formsets = []
        model_form = self.get_form(request, obj=obj, change=not add)
        if request.method == 'POST':
            form = model_form(request.POST, request.FILES, instance=obj)
            form_validated = form.is_valid()
            if form_validated:
                new_object = self.save_form(request, form, change=not add)
            else:
                new_object = form.instance
            formsets, inline_instances = self._create_formsets(request,
                                                               new_object,
                                                               change=not add)
            formset_inline_tuples = zip(formsets,
                                        self.get_inline_instances(request))
            formset_inline_tuples = _remove_blank_reverse_inlines(
                new_object, formset_inline_tuples)
            formsets = [t[0] for t in formset_inline_tuples]
            if form_validated and not formsets:
                self._save_object(request, new_object, form, formsets, add)
                return self.response_add(request, new_object)
            elif form_validated and all_valid(formsets):
                # Here is the modified code.
                for formset, inline in formset_inline_tuples:
                    if not isinstance(inline, ReverseInlineModelAdmin):
                        continue
                    # The idea or this piece is coming from https://stackoverflow.com/questions/50910152/inline-formset-returns-empty-list-on-save.
                    # Without this, formset.save() was returning None for forms that
                    # haven't been modified
                    forms = [f for f in formset]
                    if not forms:
                        continue
                    obj = forms[0].save()
                    setattr(new_object, inline.parent_fk_name, obj)
                self._save_object(request, new_object, form, formsets, add)
                for formset in formsets:
                    self.save_formset(request, form, formset, change=not add)

                # self.log_addition(request, new_object)
                return self.response_add(request, new_object)
        else:
            # Prepare the dict of initial data from the request.
            # We have to special-case M2Ms as a list of comma-separated PKs.
            initial = dict(request.GET.items())
            for k in initial:
                try:
                    f = opts.get_field(k)
                except FieldDoesNotExist:
                    continue
                if isinstance(f, models.ManyToManyField):
                    initial[k] = initial[k].split(",")
            if add:
                form = model_form(initial=initial)
                prefixes = {}
                for FormSet, inline in self.get_formsets_with_inlines(request):
                    prefix = FormSet.get_default_prefix()
                    prefixes[prefix] = prefixes.get(prefix, 0) + 1
                    if prefixes[prefix] != 1:
                        prefix = "%s-%s" % (prefix, prefixes[prefix])
                    formset = FormSet(instance=self.model(), prefix=prefix)
                    formsets.append(formset)
            else:
                form = model_form(instance=obj)
                formsets, inline_instances = self._create_formsets(request,
                                                                   obj,
                                                                   change=True)

        readonly_fields = self.get_readonly_fields(request, obj)
        adminForm = helpers.AdminForm(form,
                                      list(self.get_fieldsets(request)),
                                      self.prepopulated_fields,
                                      readonly_fields=readonly_fields,
                                      model_admin=self)
        media = self.media + adminForm.media

        inline_admin_formsets = self.get_inline_formsets(
            request, formsets, self.get_inline_instances(request), obj)
        for inline_formset in inline_admin_formsets:
            media = media + inline_formset.media

        # Inherit the default context from admin_site
        context = self.admin_site.each_context(request)
        reverse_admin_context = {
            'title': _(
                ('Change %s', 'Add %s')[add]) % force_str(opts.verbose_name),
            'adminform': adminForm,
            # 'is_popup': '_popup' in request.REQUEST,
            'is_popup': False,
            'object_id': object_id,
            'original': obj,
            'media': mark_safe(media),
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            # 'root_path': self.admin_site.root_path,
            'app_label': opts.app_label,
        }
        context.update(reverse_admin_context)
        context.update(extra_context or {})
        return self.render_change_form(
            request,
            context,
            form_url=form_url,
            add=add,
            change=not add,
            obj=obj,
        )
예제 #25
0
 def render_revision_form(self, request, obj, version, context, revert=False, recover=False):
     """Renders the object revision form."""
     model = self.model
     opts = model._meta
     object_id = obj.pk
     # Generate the model form.
     ModelForm = self.get_form(request, obj)
     formsets = []
     if request.method == "POST":
         # This section is copied directly from the model admin change view
         # method.  Maybe one day there will be a hook for doing this better.
         form = ModelForm(request.POST, request.FILES, instance=obj, initial=self.get_revision_form_data(request, obj, version))
         if form.is_valid():
             form_validated = True
             new_object = self.save_form(request, form, change=True)
             # HACK: If the value of a file field is None, remove the file from the model.
             for field in new_object._meta.fields:
                 if isinstance(field, models.FileField) and field.name in form.cleaned_data and form.cleaned_data[field.name] is None:
                     setattr(new_object, field.name, None)
         else:
             form_validated = False
             new_object = obj
         prefixes = {}
         for FormSet, inline in zip(self.get_formsets(request, new_object),
                                    self.get_inline_instances(request)):
             prefix = FormSet.get_default_prefix()
             prefixes[prefix] = prefixes.get(prefix, 0) + 1
             if prefixes[prefix] != 1:
                 prefix = "%s-%s" % (prefix, prefixes[prefix])
             formset = FormSet(request.POST, request.FILES,
                               instance=new_object, prefix=prefix,
                               queryset=inline.queryset(request))
             self._hack_inline_formset_initial(FormSet, formset, obj, version, revert, recover)
             # Add this hacked formset to the form.
             formsets.append(formset)
         if all_valid(formsets) and form_validated:
             self.save_model(request, new_object, form, change=True)
             form.save_m2m()
             for formset in formsets:
                 # HACK: If the value of a file field is None, remove the file from the model.
                 related_objects = formset.save(commit=False)
                 for related_obj, related_form in zip(related_objects, formset.saved_forms):
                     for field in related_obj._meta.fields:
                         if isinstance(field, models.FileField) and field.name in related_form.cleaned_data and related_form.cleaned_data[field.name] is None:
                             setattr(related_obj, field.name, None)
                     related_obj.save()
                 formset.save_m2m()
             change_message = _(u"Reverted to previous version, saved on %(datetime)s") % {"datetime": format(version.revision.date_created, _('DATETIME_FORMAT'))}
             self.log_change(request, new_object, change_message)
             self.message_user(request, _(u'The %(model)s "%(name)s" was reverted successfully. You may edit it again below.') % {"model": force_unicode(opts.verbose_name), "name": unicode(obj)})
             # Redirect to the model change form.
             if revert:
                 return HttpResponseRedirect("../../")
             elif recover:
                 return HttpResponseRedirect("../../%s/" % quote(object_id))
             else:
                 assert False
     else:
         # This is a mutated version of the code in the standard model admin
         # change_view.  Once again, a hook for this kind of functionality
         # would be nice.  Unfortunately, it results in doubling the number
         # of queries required to construct the formets.
         form = ModelForm(instance=obj, initial=self.get_revision_form_data(request, obj, version))
         prefixes = {}
         for FormSet, inline in zip(self.get_formsets(request, obj), self.get_inline_instances(request)):
             # This code is standard for creating the formset.
             prefix = FormSet.get_default_prefix()
             prefixes[prefix] = prefixes.get(prefix, 0) + 1
             if prefixes[prefix] != 1:
                 prefix = "%s-%s" % (prefix, prefixes[prefix])
             formset = FormSet(instance=obj, prefix=prefix,
                               queryset=inline.queryset(request))
             self._hack_inline_formset_initial(FormSet, formset, obj, version, revert, recover)
             # Add this hacked formset to the form.
             formsets.append(formset)
     # Generate admin form helper.
     adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj),
         self.prepopulated_fields, self.get_readonly_fields(request, obj),
         model_admin=self)
     media = self.media + adminForm.media
     # Generate formset helpers.
     inline_admin_formsets = []
     for inline, formset in zip(self.get_inline_instances(request), formsets):
         fieldsets = list(inline.get_fieldsets(request, obj))
         readonly = list(inline.get_readonly_fields(request, obj))
         prepopulated = inline.get_prepopulated_fields(request, obj)
         inline_admin_formset = helpers.InlineAdminFormSet(inline, formset,
             fieldsets, prepopulated, readonly, model_admin=self)
         inline_admin_formsets.append(inline_admin_formset)
         media = media + inline_admin_formset.media
     # Generate the context.
     context.update({"adminform": adminForm,
                     "object_id": object_id,
                     "original": obj,
                     "is_popup": False,
                     "media": mark_safe(media),
                     "inline_admin_formsets": inline_admin_formsets,
                     "errors": helpers.AdminErrorList(form, formsets),
                     "app_label": opts.app_label,
                     "add": False,
                     "change": True,
                     "revert": revert,
                     "recover": recover,
                     "has_add_permission": self.has_add_permission(request),
                     "has_change_permission": self.has_change_permission(request, obj),
                     "has_delete_permission": self.has_delete_permission(request, obj),
                     "has_file_field": True,
                     "has_absolute_url": False,
                     "ordered_objects": opts.get_ordered_objects(),
                     "form_url": mark_safe(request.path),
                     "opts": opts,
                     "content_type_id": ContentType.objects.get_for_model(self.model).id,
                     "save_as": False,
                     "save_on_top": self.save_on_top,
                     "changelist_url": reverse("%s:%s_%s_changelist" % (self.admin_site.name, opts.app_label, opts.module_name)),
                     "change_url": reverse("%s:%s_%s_change" % (self.admin_site.name, opts.app_label, opts.module_name), args=(quote(obj.pk),)),
                     "history_url": reverse("%s:%s_%s_history" % (self.admin_site.name, opts.app_label, opts.module_name), args=(quote(obj.pk),)),
                     "recoverlist_url": reverse("%s:%s_%s_recoverlist" % (self.admin_site.name, opts.app_label, opts.module_name))})
     # Render the form.
     if revert:
         form_template = self.revision_form_template or self._get_template_list("revision_form.html")
     elif recover:
         form_template = self.recover_form_template or self._get_template_list("recover_form.html")
     else:
         assert False
     return render_to_response(form_template, context, template.RequestContext(request))
예제 #26
0
    def add_view(self, request, form_url='', extra_context=None):
        "The 'add' admin view for this model."
        model = self.model
        opts = model._meta
        if not self.has_add_permission(request):
            raise PermissionDenied

        model_form = self.get_form(request)
        formsets = []
        if request.method == 'POST':
            form = model_form(request.POST, request.FILES)
            if form.is_valid():
                form_validated = True
                new_object = self.save_form(request, form, change=False)
            else:
                form_validated = False
                new_object = self.model()
            prefixes = {}
            for FormSet, inline in self.get_formsets_with_inlines(request):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(data=request.POST,
                                  files=request.FILES,
                                  instance=new_object,
                                  save_as_new="_saveasnew" in request.POST,
                                  prefix=prefix)
                formsets.append(formset)
            if all_valid(formsets) and form_validated:
                # Here is the modified code.
                for formset, inline in zip(formsets,
                                           self.get_inline_instances(request)):
                    if not isinstance(inline, ReverseInlineModelAdmin):
                        continue
                    formsetresults = formset.save()
                    #make sure that we have some results from formset.save()
                    #could be empty if the formset is unchanged (with all default value)

                    #if not empty, we create a new object from the formset data
                    if (len(formsetresults) > 0):
                        obj = formsetresults[0]
                        setattr(new_object, inline.parent_fk_name, obj)

                    #if it is empty, we create a new object with all default value
                    else:
                        field = next((f for f in new_object._meta.fields
                                      if f.name == formset.parent_fk_name),
                                     None)
                        #create the related model with all default value
                        obj = field.related_model.objects.create()
                        setattr(new_object, inline.parent_fk_name, obj)

                self.save_model(request, new_object, form, change=False)
                form.save_m2m()
                for formset in formsets:
                    self.save_formset(request, form, formset, change=False)

                # self.log_addition(request, new_object)
                return self.response_add(request, new_object)
        else:
            # Prepare the dict of initial data from the request.
            # We have to special-case M2Ms as a list of comma-separated PKs.
            initial = dict(request.GET.items())
            for k in initial:
                try:
                    f = opts.get_field(k)
                except models.FieldDoesNotExist:
                    continue
                if isinstance(f, models.ManyToManyField):
                    initial[k] = initial[k].split(",")
            form = model_form(initial=initial)
            prefixes = {}
            for FormSet, inline in self.get_formsets_with_inlines(request):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(instance=self.model(), prefix=prefix)
                formsets.append(formset)

        adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)),
                                      self.prepopulated_fields)
        media = self.media + adminForm.media

        inline_admin_formsets = []
        for inline, formset in zip(self.get_inline_instances(request),
                                   formsets):
            fieldsets = list(inline.get_fieldsets(request))
            inline_admin_formset = helpers.InlineAdminFormSet(
                inline, formset, fieldsets)
            inline_admin_formsets.append(inline_admin_formset)
            media = media + inline_admin_formset.media

        context = {
            'title': _('Add %s') % force_text(opts.verbose_name),
            'adminform': adminForm,
            # 'is_popup': '_popup' in request.REQUEST,
            'is_popup': False,
            'show_delete': False,
            'media': mark_safe(media),
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            # 'root_path': self.admin_site.root_path,
            'app_label': opts.app_label,
        }
        context.update(extra_context or {})
        return self.render_change_form(request,
                                       context,
                                       form_url=form_url,
                                       add=True)
예제 #27
0
    def changeform_view(self,
                        request,
                        object_id=None,
                        form_url='',
                        extra_context=None):

        to_field = request.POST.get(TO_FIELD_VAR,
                                    request.GET.get(TO_FIELD_VAR))
        if to_field and not self.to_field_allowed(request, to_field):
            raise DisallowedModelAdminToField(
                "The field %s cannot be referenced." % to_field)

        model = self.model
        opts = model._meta

        if request.method == 'POST' and '_saveasnew' in request.POST:
            object_id = None

        add = object_id is None

        if add:
            if not self.has_add_permission(request):
                raise PermissionDenied
            obj = None

        else:
            obj = self.get_object(request, unquote(object_id), to_field)

            if not self.has_change_permission(request, obj):
                raise PermissionDenied

            if obj is None:
                raise Http404(
                    _('%(name)s object with primary key %(key)r does not exist.'
                      ) % {
                          'name': force_text(opts.verbose_name),
                          'key': escape(object_id)
                      })

        ModelForm = self.get_form(request, obj)
        if request.method == 'POST':
            form = ModelForm(request.POST, request.FILES, instance=obj)
            if form.is_valid():
                form_validated = True
                new_object = self.save_form(request, form, change=not add)
            else:
                form_validated = False
                new_object = form.instance
            formsets, inline_instances = self._create_formsets(request,
                                                               new_object,
                                                               change=not add)
            if all_valid(formsets) and form_validated:
                self.save_model(request, new_object, form, not add)
                self.save_related(request, form, formsets, not add)
                change_message = self.construct_change_message(
                    request, form, formsets, add)
                if add:
                    self.log_addition(request, new_object, change_message)
                    return self.response_add(request, new_object)
                else:
                    self.log_change(request, new_object, change_message)
                    return self.response_change(request, new_object)
            else:
                form_validated = False
        else:
            if add:
                initial = self.get_changeform_initial_data(request)
                form = ModelForm(initial=initial)
                formsets, inline_instances = self._create_formsets(
                    request, form.instance, change=False)
            else:
                form = ModelForm(instance=obj)
                formsets, inline_instances = self._create_formsets(request,
                                                                   obj,
                                                                   change=True)

        adminForm = helpers.AdminForm(form,
                                      list(self.get_fieldsets(request, obj)),
                                      self.get_prepopulated_fields(
                                          request, obj),
                                      self.get_readonly_fields(request, obj),
                                      model_admin=self)
        media = self.media + adminForm.media

        inline_formsets = self.get_inline_formsets(request, formsets,
                                                   inline_instances, obj)
        for inline_formset in inline_formsets:
            media = media + inline_formset.media

        context = dict(
            self.admin_site.each_context(request),
            title=(_('Add %s') if add else _('Change %s')) %
            force_text(opts.verbose_name),
            adminform=adminForm,
            object_id=object_id,
            original=obj,
            is_popup=(IS_POPUP_VAR in request.POST
                      or IS_POPUP_VAR in request.GET),
            to_field=to_field,
            media=media,
            inline_admin_formsets=inline_formsets,
            errors=helpers.AdminErrorList(form, formsets),
            preserved_filters=self.get_preserved_filters(request),
        )

        # Hide the "Save" and "Save and continue" buttons if "Save as New" was
        # previously chosen to prevent the interface from getting confusing.
        if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST:
            context['show_save'] = False
            context['show_save_and_continue'] = False
            # Use the change template instead of the add template.
            add = False

        context.update(extra_context or {})

        return self.render_change_form(request,
                                       context,
                                       add=add,
                                       change=not add,
                                       obj=obj,
                                       form_url=form_url)
예제 #28
0
    def add_view(self, request, form_url='', extra_context={}):
        "The 'add' admin view for this model."
        #copied from django/contrib/admin/options.py:924 at version 1.4.0
        model = self.model
        opts = model._meta

        if not self.has_add_permission(request):
            raise PermissionDenied

        ModelForm = self.get_form(request)
        formsets = []
        inline_instances = self.get_inline_instances(request)
        if request.method == 'POST':
            form = ModelForm(request.POST, request.FILES)
            if form.is_valid():
                new_object = self.save_form(request, form, change=False)
                form_validated = True
            else:
                form_validated = False
                new_object = self.model()
            prefixes = {}
            for FormSet, inline in zip(self.get_formsets(request), inline_instances):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1 or not prefix:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(data=request.POST, files=request.FILES,
                                  instance=new_object,
                                  save_as_new="_saveasnew" in request.POST,
                                  prefix=prefix, queryset=inline.get_queryset(request))
                formsets.append(formset)
                if hasattr(inline, 'inlines') and inline.inlines:
                    self.add_recursive_inline_formsets(request, inline, formset)
            if self.all_valid(formsets) and form_validated:
                self.save_model(request, new_object, form, False)
                self.save_related(request, form, formsets, False)
                self.log_addition(request, new_object)
                return self.response_add(request, new_object)
        else:
            # Prepare the dict of initial data from the request.
            # We have to special-case M2Ms as a list of comma-separated PKs.
            initial = dict(request.GET.items())
            for k in initial:
                try:
                    f = opts.get_field(k)
                except FieldDoesNotExist:
                    continue
                if isinstance(f, ManyToManyField):
                    initial[k] = initial[k].split(",")
            form = ModelForm(initial=initial)
            prefixes = {}
            for FormSet, inline in zip(self.get_formsets(request), inline_instances):
                prefix = FormSet.get_default_prefix()
                prefixes[prefix] = prefixes.get(prefix, 0) + 1
                if prefixes[prefix] != 1 or not prefix:
                    prefix = "%s-%s" % (prefix, prefixes[prefix])
                formset = FormSet(instance=self.model(), prefix=prefix,
                                  queryset=inline.get_queryset(request))
                formsets.append(formset)
                if hasattr(inline, 'inlines') and hasattr(self, 'add_recursive_inline_formsets'):
                    self.add_recursive_inline_formsets(request, inline, formset)

        adminForm = helpers.AdminForm(form, list(
            self.get_fieldsets(request)),
            self.get_prepopulated_fields(request),
            self.get_readonly_fields(request),
            model_admin=self)
        media = self.media + adminForm.media

        inline_admin_formsets = []
        for inline, formset in zip(inline_instances, formsets):
            fieldsets = list(inline.get_fieldsets(request))
            readonly = list(inline.get_readonly_fields(request))
            prepopulated = dict(inline.get_prepopulated_fields(request))
            inline_admin_formset = helpers.InlineAdminFormSet(
                inline, formset, fieldsets, prepopulated,
                readonly, model_admin=self)
            inline_admin_formsets.append(inline_admin_formset)
            media = media + inline_admin_formset.media
            if hasattr(inline, 'inlines'):
                media = media + self.wrap_recursive_inline_formsets(request, inline, formset)

        context = {
            'title': _('Add %s') % force_unicode(opts.verbose_name),
            'adminform': adminForm,
            'is_popup': IS_POPUP_VAR in request.REQUEST,
            'show_delete': False,
            'media': media,
            'inline_admin_formsets': inline_admin_formsets,
            'errors': helpers.AdminErrorList(form, formsets),
            'app_label': opts.app_label,
            'preserved_filters': self.get_preserved_filters(request),

        }
        context.update(extra_context or {})
        return self.render_change_form(request, context, form_url=form_url, add=True)