Beispiel #1
0
 def post(self, request, *args, **kwargs):
     key = utils.make_template_fragment_key(
         f'{self.request.user.id}.{self.model_name}.list'
     )
     cache.delete(key)
     data = request.POST.copy()
     clean_data = dict(
         list_display=data.getlist('list_display'),
         list_only_date=data.get('list_only_date', 1)
     )
     content = json.dumps(clean_data)
     config = Configure.objects.filter(
         content_type=get_content_type_for_model(self.model),
         onidc_id=self.onidc_id, creator=self.request.user, mark='list'
     ).order_by('-pk')
     if config.exists():
         config = config.update(content=content)
     else:
         config = Configure.objects.create(
             content_type=get_content_type_for_model(self.model),
             onidc_id=self.onidc_id, creator=self.request.user,
             mark='list', content=content
         )
     redirect_to = reverse_lazy('idcops:list', args=[self.model_name])
     messages.success(request, f"您的{self.verbose_name}自定义列表配置完成")
     return HttpResponseRedirect(redirect_to)
Beispiel #2
0
def release(request, queryset):
    action = sys._getframe().f_code.co_name
    action_name = "释放机柜"
    rack_ids = [id for id in queryset.values_list('id', flat=True)]
    # fix: unknown your action: The QuerySet value
    if Online.objects.filter(rack_id__in=rack_ids).exists():
        mesg = "选择的机柜中仍有在线设备,无法释放"
        return mesg

    queryset = queryset.filter(actived=True)
    if request.POST.get('post'):
        for obj in queryset:
            o = copy.deepcopy(obj)
            if obj.client and obj.client.onlinenum() == 0:
                verb = f"客户 {force_text(obj.client)} 没有在线设备, 是否终止"
                log_action(user_id=request.user.pk,
                           content_type_id=get_content_type_for_model(
                               obj, True).pk,
                           object_id=obj.pk,
                           action_flag="系统通知",
                           message=verb,
                           content=verb)
            obj.actived = False
            obj.client = None
            obj.cpower = 0
            obj.style = None
            obj.status = None
            obj.expiry_date = None
            obj.operator = request.user
            obj.tags.clear()

            if obj.jnum() != 0:
                verb = f"机柜 {force_text(obj)} 还有跳线存在, 请回收"
                log_action(user_id=request.user.pk,
                           content_type_id=get_content_type_for_model(
                               obj, True).pk,
                           object_id=obj.pk,
                           action_flag="系统通知",
                           message=verb,
                           content=verb)

            obj.save()
            diffs = diff_dict(serialize_object(o), serialize_object(obj))
            log_action(user_id=request.user.pk,
                       content_type_id=get_content_type_for_model(obj,
                                                                  True).pk,
                       object_id=obj.pk,
                       action_flag=action_name,
                       message=json.dumps(list(diffs.keys())),
                       content=json.dumps(diffs),
                       related_client=get_related_client_name(o))
        return None
    context = construct_context(request, queryset, action, action_name)
    return TemplateResponse(request, 'base/base_confirmation.html', context)
Beispiel #3
0
def removeup(request, queryset):
    action = sys._getframe().f_code.co_name
    action_name = "取消下架"
    exclude = queryset.filter(rack__actived=False)
    if exclude.exists():
        mesg = "有设备所在机柜未使用, 无法取消下架"
        return mesg

    if request.POST.get('post'):
        for obj in queryset:
            o = copy.deepcopy(obj)
            obj.actived = True
            obj.status = 'online'
            obj.operator = request.user
            lastunits = copy.deepcopy(obj.units.all())
            lastpdus = copy.deepcopy(obj.pdus.all())
            ucan_recovery = False not in [u.actived for u in lastunits]
            pcan_recovery = False not in [p.actived for p in lastpdus]
            if ucan_recovery:
                obj.units.all().update(actived=False, operator=obj.operator)
            else:
                verb = f"无法恢复 {force_text(obj)} 的U位"
                log_action(user_id=request.user.pk,
                           content_type_id=get_content_type_for_model(
                               obj, True).pk,
                           object_id=obj.pk,
                           action_flag="系统通知",
                           message=verb,
                           content=verb)
                obj.units.clear()
            if pcan_recovery:
                obj.pdus.all().update(actived=False, operator=obj.operator)
            else:
                obj.pdus.clear()
            obj.save()
            diffs = diff_dict(serialize_object(o), serialize_object(obj))
            message = json.dumps(list(diffs.keys()))
            old_units = [force_text(u) for u in lastunits]
            old_pdus = [force_text(p) for p in lastpdus]
            diffs.update({'last_units': old_units, 'last_pdus': old_pdus})
            content = json.dumps(diffs)
            log_action(user_id=request.user.pk,
                       content_type_id=get_content_type_for_model(obj,
                                                                  True).pk,
                       object_id=obj.pk,
                       action_flag=action_name,
                       message=message,
                       content=content)
        return None
    context = construct_context(request, queryset, action, action_name)
    return TemplateResponse(request, 'base/base_confirmation.html', context)
Beispiel #4
0
 def post(self, request, *args, **kwargs):
     form_class = self.get_form_class()
     form = self.get_form(form_class)
     if form.is_valid():
         excel = form.cleaned_data['excel']
         FilePath = getattr(settings, 'MEDIA_ROOT', '../logs')
         name, lnk, ext = excel.name.rpartition('.')
         endfix = '-' + str(int(time.time()))
         FileName = os.path.join(FilePath, name + endfix + lnk + ext)
         with open(FileName, 'wb+') as destination:
             for chunk in excel.chunks():
                 destination.write(chunk)
         error, warning, success, total = import_online(
             FileName, request.user.onidc_id
         )
         message = "共导入{}条:成功{}条,失败{}条".format(
             total, len(success), len(error)
         )
         _content = {}
         _content['error'] = error
         _content['warning'] = warning
         _content['success'] = success
         content = json.dumps(_content, ensure_ascii=False)
         Syslog.objects.create(
             creator_id=request.user.pk, onidc_id=self.onidc_id,
             content_type_id=get_content_type_for_model(Online, True).pk,
             action_flag="导入设备", object_desc="-",
             message=message, content=content
         )
         messages.info(request, "导入完成,请查看日志记录!")
         return self.form_valid(form)
     else:
         return self.form_invalid(form)
Beispiel #5
0
 def form_valid(self, form):
     form.instance.creator = self.request.user
     if 'onidc' not in form.cleaned_data:
         form.instance.onidc = self.request.user.onidc
     created = None
     if 'created' in form.cleaned_data:
         created = form.cleaned_data.get('created')
     response = super(NewModelView, self).form_valid(form)
     log_action(user_id=self.request.user.pk,
                content_type_id=get_content_type_for_model(
                    self.object, True).pk,
                object_id=self.object.pk,
                created=created,
                action_flag="新增")
     if self.model_name == 'online':
         verify = Thread(target=device_post_save, args=(self.object.pk, ))
         verify.start()
     if self.request.is_ajax():
         data = {
             'message': "Successfully submitted form data.",
             'data': form.cleaned_data
         }
         return JsonResponse(data)
     else:
         return response
Beispiel #6
0
 def form_valid(self, form):
     form.instance.operator = self.request.user
     if 'onidc' not in form.cleaned_data:
         form.instance.onidc = self.request.user.onidc
     d1 = form.initial
     message = json.dumps(form.changed_data)
     response = super(EditModelView, self).form_valid(form)
     d2 = model_to_dict(construct_instance(form, self.object))
     diffs = diff_dict(make_dict(d1), make_dict(d2))
     content = json.dumps(diffs)
     log_action(user_id=self.request.user.pk,
                content_type_id=get_content_type_for_model(
                    self.object, True).pk,
                object_id=self.object.pk,
                action_flag="修改",
                message=message,
                content=content)
     if self.model_name == 'online':
         verify = Thread(target=device_post_save, args=(self.object.pk, ))
         verify.start()
     if self.request.is_ajax():
         data = {
             'message': "Successfully submitted form data.",
             'data': form.cleaned_data
         }
         return JsonResponse(data)
     else:
         return response
Beispiel #7
0
def renewal(request, queryset):
    action = sys._getframe().f_code.co_name
    action_name = "机柜续期"
    queryset = queryset.filter(actived=True)
    if request.POST.get('post') and request.POST.getlist('items'):

        def construct_item(index):
            obj = queryset.get(pk=int(index))
            expiry_date = request.POST.get(f'expiry_date-{index}')
            return obj, expiry_date

        for item in request.POST.getlist('items'):
            obj, expiry_date = construct_item(item)
            try:
                expiry_date = timezone.datetime.strptime(
                    expiry_date, '%Y-%m-%d').date()
            except BaseException:
                expiry_date = None
            o = copy.deepcopy(obj)
            obj.operator = request.user
            obj.expiry_date = expiry_date
            obj.save()
            diffs = diff_dict(serialize_object(o), serialize_object(obj))
            log_action(user_id=request.user.pk,
                       content_type_id=get_content_type_for_model(obj,
                                                                  True).pk,
                       object_id=obj.pk,
                       action_flag=action_name,
                       message=json.dumps(list(diffs.keys())),
                       content=json.dumps(diffs))
        return None

    context = construct_context(request, queryset, action, action_name)
    return TemplateResponse(request, 'rack/renewal.html', context)
Beispiel #8
0
def reoutbound(request, queryset):
    action = sys._getframe().f_code.co_name
    action_name = "取消出库"
    queryset = queryset.filter(actived=False)
    if not queryset.exists():
        return "查无结果"

    if request.POST.get('post'):
        for obj in queryset:
            o = copy.deepcopy(obj)
            obj.actived = True
            obj.save()
            diffs = diff_dict(model_to_dict(o), model_to_dict(obj))
            log_action(
                user_id=request.user.pk,
                content_type_id=get_content_type_for_model(obj, True).pk,
                object_id=obj.pk,
                action_flag=action_name,
                message=json.dumps(list(diffs.keys())),
                content=json.dumps(diffs)
            )
        return None

    context = construct_context(request, queryset, action, action_name)
    return TemplateResponse(request, 'base/base_confirmation.html', context)
Beispiel #9
0
def delete(request, queryset):
    model = queryset.model
    opts = model._meta
    action = sys._getframe().f_code.co_name
    action_name = "删除"

    modeladmin = admin.site._registry.get(model)
    # queryset = queryset.filter(actived=False)
    if not modeladmin.has_delete_permission(request):
        raise PermissionDenied
    # using = router.db_for_write(modeladmin.model)

    deletable_objects, model_count, perms_needed, protected = \
        get_deleted_objects(queryset, request, modeladmin.admin_site)

    if request.POST.get('post') and not protected:
        if perms_needed:
            raise PermissionDenied
        if queryset.count():
            for obj in queryset:
                log_action(
                    user_id=request.user.pk,
                    content_type_id=get_content_type_for_model(obj, True).pk,
                    object_id=obj.pk,
                    action_flag="删除"
                )
            if not SOFT_DELETE:
                queryset.delete()
            else:
                queryset.update(deleted=True, actived=False)
        return None

    if len(queryset) == 1:
        objects_name = force_text(opts.verbose_name)
    else:
        objects_name = force_text(opts.verbose_name_plural)

    meta, menus = construct_model_meta(request, model, action_name)

    context = dict(
        objects_name=objects_name,
        deletable_objects=[deletable_objects],
        model_count=dict(model_count).items(),
        queryset=queryset,
        perms_lacking=perms_needed,
        protected=protected,
        opts=opts,
        meta=meta,
        action=action,
        action_name=action_name,
        menus=menus,
    )

    request.current_app = modeladmin.admin_site.name

    return TemplateResponse(request, 'base/delete_confirmation.html', context)
Beispiel #10
0
 def user_config(self, data):
     newd = dict(list_display=data.getlist('list_display'),
                 list_only_date=data.get('list_only_date', 1))
     content = json.dumps(newd)
     config = Configure.objects.filter(
         content_type=get_content_type_for_model(self.model),
         onidc_id=self.onidc_id,
         creator=self.request.user,
         mark='list').order_by('-pk')
     if config.exists():
         config = config.update(content=content)
     else:
         config = Configure.objects.create(
             content_type=get_content_type_for_model(self.model),
             onidc_id=self.onidc_id,
             creator=self.request.user,
             mark='list',
             content=content)
     return config
Beispiel #11
0
def distribution(request, queryset):
    action = sys._getframe().f_code.co_name
    action_name = "分配机柜"
    queryset = queryset.filter(actived=False)
    onidc_id = request.user.onidc.id
    options = Option.objects.filter(actived=True)
    clients = shared_queryset(Client.objects.filter(actived=True), onidc_id)
    status = shared_queryset(options.filter(flag='Rack-Status'), onidc_id)
    styles = shared_queryset(options.filter(flag='Rack-Style'), onidc_id)
    if request.POST.get('post') and request.POST.getlist('items'):

        def construct_item(index):
            obj = queryset.get(pk=int(index))
            try:
                client = int(request.POST.get('client-' + str(index)))
            except BaseException:
                client = 0
            status = int(request.POST.get(f'status-{index}'))
            style = int(request.POST.get(f'style-{index}'))
            expiry_date = request.POST.get(f'expiry_date-{index}')
            cpower = request.POST.get(f'cpower-{index}')
            comment = request.POST.get((f'comment-{index}'), None)
            return obj, client, status, style, expiry_date, cpower, comment

        for item in request.POST.getlist('items'):
            obj, client, status, style, expiry_date, cpower, _ = construct_item(
                item)
            try:
                expiry_date = timezone.datetime.strptime(
                    expiry_date, '%Y-%m-%d').date()
            except BaseException:
                expiry_date = None
            o = copy.deepcopy(obj)
            if client != 0:
                obj.client_id = client
            obj.status_id = status
            obj.style_id = style
            obj.cpower = cpower
            obj.expiry_date = expiry_date
            obj.actived = True
            obj.save()
            diffs = diff_dict(serialize_object(o), serialize_object(obj))
            log_action(user_id=request.user.pk,
                       content_type_id=get_content_type_for_model(obj,
                                                                  True).pk,
                       object_id=obj.pk,
                       action_flag=action_name,
                       message=json.dumps(list(diffs.keys())),
                       content=json.dumps(diffs))
        return None

    context = construct_context(request, queryset, action, action_name)
    _extra = dict(clients=clients, status=status, styles=styles)
    context.update(_extra)
    return TemplateResponse(request, 'rack/distribution.html', context)
Beispiel #12
0
 def user_config(self, data):
     newd = dict(
         list_display=data.getlist('list_display'),
         list_only_date=data.get('list_only_date', 1)
     )
     content = json.dumps(newd)
     config = Configure.objects.filter(
         content_type=get_content_type_for_model(self.model),
         onidc_id=self.onidc_id, creator=self.request.user,
         mark='list').order_by('-pk')
     if config.exists():
         config = config.update(content=content)
     else:
         config = Configure.objects.create(
             content_type=get_content_type_for_model(self.model),
             onidc_id=self.onidc_id, creator=self.request.user,
             mark='list', content=content)
     key = utils.make_template_fragment_key("{}.{}.{}".format(
         self.request.user.id, self.model_name, 'list'))
     cache.delete(key)
     return config
Beispiel #13
0
def get_user_config(user, mark, model):
    content_type = get_content_type_for_model(model)
    configs = Configure.objects.filter(
        creator=user, mark=mark, content_type=content_type).order_by('-pk')
    if configs.exists():
        config = configs.first().content
        try:
            return json.loads(config)
        except BaseException:
            return None
    else:
        return None
Beispiel #14
0
def release(request, queryset):
    action = sys._getframe().f_code.co_name
    action_name = "释放机柜"
    if Online.objects.filter(rack=queryset).exists():
        mesg = "选择的机柜中仍有在线设备,无法释放"
        return mesg

    queryset = queryset.filter(actived=True)
    if request.POST.get('post'):
        for obj in queryset:
            o = copy.deepcopy(obj)
            if obj.client and obj.client.onlinenum() == 0:
                verb = "客户 {} 没有在线设备, 是否终止".format(force_text(obj.client))
                notify_user.send(
                    request.user,
                    recipient=request.user,
                    target=obj,
                    verb=verb,
                )

            obj.actived = False
            obj.client = None
            obj.cpower = 0
            obj.style = None
            obj.status = None
            obj.operator = request.user
            obj.tags.clear()

            if obj.jnum() != 0:
                verb = "机柜 {} 还有跳线存在, 请回收".format(force_text(obj))
                notify_user.send(
                    request.user,
                    recipient=request.user,
                    target=obj,
                    verb=verb,
                )

            obj.save()
            from idcops.lib.tasks import get_related_client_name
            diffs = diff_dict(model_to_dict(o), model_to_dict(obj))
            log_action(user_id=request.user.pk,
                       content_type_id=get_content_type_for_model(obj,
                                                                  True).pk,
                       object_id=obj.pk,
                       action_flag=action_name,
                       message=json.dumps(list(diffs.keys())),
                       content=json.dumps(diffs),
                       related_client=get_related_client_name(o))
        return None
    context = construct_context(request, queryset, action, action_name)
    return TemplateResponse(request, 'base/base_confirmation.html', context)
Beispiel #15
0
def initial_user_configuration(instance, created, **kwargs):
    if created:
        models = apps.get_app_config('idcops').get_models()
        exclude = ['onidc', 'deleted', 'mark', 'id', 'password']
        configures = []
        for model in models:
            fds = [f for f in fields_for_model(model) if f not in exclude]
            _fields = getattr(model._meta, 'list_display', fds)
            fields = _fields if isinstance(_fields, list) else fds
            content = {'list_only_date': 1, 'list_display': fields}
            config = dict(
                onidc=instance.onidc,
                creator=instance,
                mark='list',
                content_type=get_content_type_for_model(model),
                content=json.dumps(content),
            )
            configures.append(Configure(**config))
        Configure.objects.bulk_create(configures)
Beispiel #16
0
def cancel_reclaim(request, queryset):
    action = sys._getframe().f_code.co_name
    action_name = "取消回收"
    if request.POST.get('post'):
        for obj in queryset:
            o = copy.deepcopy(obj)
            obj.actived = True
            obj.save()
            diffs = diff_dict(serialize_object(o), serialize_object(obj))
            log_action(user_id=request.user.pk,
                       content_type_id=get_content_type_for_model(obj,
                                                                  True).pk,
                       object_id=obj.pk,
                       action_flag=action_name,
                       message=json.dumps(list(diffs.keys())),
                       content=json.dumps(diffs))
        return None
    context = construct_context(request, queryset, action, action_name)
    return TemplateResponse(request, 'base/base_confirmation.html', context)
Beispiel #17
0
def movedown(request, queryset):
    action = sys._getframe().f_code.co_name
    action_name = "下架"
    if request.POST.get('post'):
        for obj in queryset:
            o = copy.deepcopy(obj)
            obj.actived = False
            obj.status = 'offline'
            obj.operator = request.user
            obj.units.all().update(actived=True, operator=obj.operator)
            obj.pdus.all().update(actived=True, operator=obj.operator)
            obj.save()
            diffs = diff_dict(model_to_dict(o), model_to_dict(obj))
            log_action(user_id=request.user.pk,
                       content_type_id=get_content_type_for_model(obj,
                                                                  True).pk,
                       object_id=obj.pk,
                       action_flag=action_name,
                       message=json.dumps(list(diffs.keys())),
                       content=json.dumps(diffs))
        return None
    context = construct_context(request, queryset, action, action_name)
    return TemplateResponse(request, 'base/base_confirmation.html', context)
Beispiel #18
0
def import_online(path, onidc_id):
    fileds = [
        'name', 'creator', 'rack', 'client', 'created', 'onidc', 'sn', 'model',
        'ipaddr', 'style', 'units', 'pdus', 'tags'
    ]
    workbook = xlrd.open_workbook(path)
    sheets = workbook.sheet_names()
    worksheet = workbook.sheet_by_name(sheets[0])
    # 设置导入错误日志记录到一个字典中
    handler_error = []
    handler_warning = []
    handler_success = []
    index = 0
    headers = None
    for index, row in enumerate(worksheet.get_rows(), 1):
        header = index
        if header == 1:
            # 跳过表头
            continue
        if header == 2:
            # 获取字段名称
            headers = [h.value for h in row]
            continue
        data = dict(zip(headers, [k.value for k in row]))
        raw = {k: data.get(k) for k in fileds}
        try:
            created = datetime.strptime(data.get('created'), '%Y-%m-%d')
        except BaseException:
            created = datetime.now().date().strftime('%Y-%m-%d')
        raw.update(**dict(created=created, sn=force_text(data.get('sn'))))
        verify = Device.objects.filter(name=raw.get('name'))
        if verify.exists():
            msg = "第{}行:{}设备已存在".format(index, raw.get('name'))
            handler_error.append(msg)
            continue
        else:
            style = get_or_create_style(raw.get('style'), onidc_id)
            creator = get_creator(raw.get('creator'))
            # 获取机柜信息
            rack, err = get_rack(raw.get('rack'), onidc_id)
            if not rack:
                msg = "第{}行:{}".format(index, err)
                handler_error.append(msg)
                continue
            # 获取客户信息
            client, err = get_or_create_client(raw.get('client'), onidc_id)
            if not client:
                msg = "第{}行:{}".format(index, err)
                handler_error.append(msg)
                continue
            # 实例化在线设备
            instance = Online(created=created,
                              style=style,
                              creator=creator,
                              rack=rack,
                              client=client,
                              name=raw.get('name'),
                              sn=raw.get('sn'),
                              ipaddr=raw.get('ipaddr'),
                              model=raw.get('model'),
                              onidc_id=onidc_id)
            instance.save()
            # 保存U位
            units, err = clean_units(raw.get('units'), rack.pk)
            if units:
                for u in units:
                    instance.units.add(u)
                units.update(actived=False)
                instance.save()
            else:
                msg = "第{}行:{}".format(index, err)
                handler_error.append(msg)
                # U位不对,删除本实例
                instance.delete()
                continue
            handler_success.append(instance.name)
            log_action(user_id=creator.pk,
                       content_type_id=get_content_type_for_model(
                           instance, True).pk,
                       object_id=instance.pk,
                       action_flag="新增",
                       created=instance.created)
            # 保存PDU
            pdus, err = clean_pdus(raw.get('pdus'), rack.pk)
            if pdus:
                for p in pdus:
                    instance.pdus.add(p)
                pdus.update(actived=False)
                instance.save()
            else:
                msg = "第{}行:{}".format(index, err)
                handler_warning.append(msg)
                # fix: pdus is none, no callback device_post_save function
                # continue
            # 保存TAGS
            tags = clean_tags(raw.get('tags'), onidc_id, creator.pk)
            if tags:
                for t in tags:
                    instance.tags.add(t)
                instance.save()
            device_post_save(instance.pk)
    total = (index - 2)
    return handler_error, handler_warning, handler_success, total
Beispiel #19
0
def outbound(request, queryset):
    action = sys._getframe().f_code.co_name
    action_name = "出库"
    queryset = queryset.filter(actived=True)
    if not queryset.exists():
        return "选择无结果"

    total = queryset.aggregate(Sum('amount'))
    if request.POST.get('post') and request.POST.getlist('items'):

        def construct_item(index):
            obj = queryset.get(pk=int(index))
            out_amount = int(request.POST.get('count-' + str(index)))
            out_serials = request.POST.getlist('sn-' + str(index))
            copy_needed = True
            if int(out_amount) == obj.amount:
                copy_needed = False
            comment = request.POST.get(('comment-' + index), None)
            return obj, copy_needed, out_serials, out_amount, comment

        for item in request.POST.getlist('items'):
            obj, _copy, out_serials, out_amount, comment = construct_item(item)
            o = copy.deepcopy(obj)
            if _copy:
                hold = [
                    s for s in obj.serials.split(',') if s not in out_serials
                ]
                obj.amount -= out_amount
                obj.serials = ','.join(hold)
                new_obj = copy.deepcopy(obj)
                new_obj.pk = None
                new_obj.amount = out_amount
                new_obj.serials = ','.join(out_serials)
                new_obj.actived = False
                new_obj.creator = request.user
                new_obj.created = timezone.datetime.now()
                new_obj.operator = None
                new_obj.parent = obj
                new_obj.save()
                comment_obj = new_obj
            else:
                obj.actived = False
                obj.operator = request.user
                comment_obj = obj
            obj.save()
            if comment:
                Comment.objects.create(object_repr=comment_obj,
                                       content=comment,
                                       creator=request.user,
                                       onidc=obj.onidc)
            diffs = diff_dict(model_to_dict(o), model_to_dict(obj))
            log_action(user_id=request.user.pk,
                       content_type_id=get_content_type_for_model(obj,
                                                                  True).pk,
                       object_id=comment_obj.pk,
                       action_flag=action_name,
                       message=json.dumps(list(diffs.keys())),
                       content=json.dumps(diffs))
        return None
    context = construct_context(request, queryset, action, action_name)
    _extra = dict(total=total)
    context.update(_extra)
    return TemplateResponse(request, 'base/items_out.html', context)