Django默认管理后台开发的一些技巧总结(二)

2023-11-17 13:50:07 浏览数 (2)

前言

上一篇文章分享了后台列表的自定义按钮,并通过按钮做一些操作。本文分享自定义上传文件页面,接收文件后并处理的过程。

过程

用到了simpleui的自定义左侧导航功能。修改项目总的setting.py

setting.py

自定义左侧导航

代码语言:javascript复制
SIMPLEUI_CONFIG = {
      # 是否使用系统默认菜单,自定义菜单时建议关闭。
     'system_keep': False,

      # 用于菜单排序和过滤, 不填此字段为默认排序和全部显示。空列表[] 为全部不显示.
     'menu_display': ['综合', '用户'],

     # 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时刷新展示菜单内容。
     # 一般建议关闭。
     'dynamic': False,
     'menus': [
        {
             'app': 'auth',
             'name': '用户',
             'icon': 'fas fa-user-shield',
             'models': [
                {
                 'name': '用户列表',
                 'icon': 'fa fa-user',
                 'url': 'auth/user/'
                },
                {
                     'name': '用户组',
                     'icon': 'fa fa-th-list',
                     'url': 'auth/group/'
                }
            ]
        },

        {
             'name': '综合',
             'icon': 'fa fa-desktop',
             'models': [
                {
                 'name': '卡片管理',
                 'url': '/adm/general/virtualcard/',
                 'icon': 'fa fa-cog'
                },
                {
                 'name': '账单上传',
                 'url': '/record/upfrecord/',
                 'icon': 'fa fa-file-import'
                },
            ]
        },
    ]
 }

路由

修改项目模块目录下的url.py

代码语言:javascript复制
from django.conf.urls import url
from record import views

urlpatterns = [
    url(r'^upfrecord/$', views.up_fundrecord_by_csv, name='record'),     #文件上传
]

处理

处理函数在views.py内定义,同样只允许管理员使用此接口。采用事物保证数据一致性。

代码语言:javascript复制
@user_passes_test(lambda u: u.is_superuser)
@login_required
@transaction.atomic
def up_fundrecord_by_csv(request):
    """
    卡片流水记录处理函数
    """
    #未录入卡片
    not_import_vcards = []

    #处理条数
    suc=0
    repeat=0
    fail=0

    if request.method == 'POST':
        form = MyForm(request.POST, request.FILES)

        if form.is_valid():
            # 处理上传的文件
            uploaded_file = request.FILES['csvfile']
            if uploaded_file.name.endswith('.csv'):
                csv_data = uploaded_file.read().decode('utf-8')
                lines = csv_data.splitlines()
                reader = csv.reader(lines)

                #跳过表头
                next(reader)

                #遍历处理
                for row in reader:
                    #transid
                    vcard = VirtualCard.objects.filter(card_transid=row[0]).first()

                    if vcard:
                        #消费类型
                        if row[2] == 'Authorization(Purchase)':
                            record_type = 4
                        else:
                            record_type = 2

                        #时间
                        auth_at = row[7]
                        #金额
                        amount = Decimal(row[11])

                        datetime_obj = datetime.strptime(auth_at, '%Y-%m-%d %H:%M:%S')
                        timestamp = datetime_obj.timestamp()

                        unsign_str = str(amount) vcard.currency str(int(timestamp)) vcard.card_transid
                        md5str=common_utils_md5_sign_str(unsign_str)

                        #避免重复录入
                        fundrecord = FundRecord.objects.filter(record_md5=md5str).first()

                        if fundrecord:
                            repeat  = 1
                        else:
                            #新增卡片消费记录
                            try:
                                with transaction.atomic():
                                    #交易状态为成功
                                    if row[3] == 'Success':
                                        #卡片流水记录
                                        fund_record = FundRecord.objects.create(
                                            card=vcard,
                                            record_md5=md5str,
                                            record_type=record_type,
                                            amount=amount,
                                            pos_currency=row[8],
                                            pos_amount=row[9],
                                            auth_at=auth_at,
                                            status=1,
                                        )

                                        #修改卡片余额
                                        if int(record_type)==4:
                                            vcard.settlement_amount  = amount
                                            vcard.remaining_amount -= amount
                                        elif int(record_type)==2:
                                            vcard.settlement_amount -= amount
                                            vcard.remaining_amount   = amount
                                        vcard.save()

                                    else:
                                        fund_record = FundRecord.objects.create(
                                            card=vcard,
                                            record_md5=md5str,
                                            record_type=record_type,
                                            amount=amount,
                                            pos_currency=row[8],
                                            pos_amount=row[9],
                                            auth_at=auth_at,
                                            resmsg=row[5],
                                            status=2,
                                        )


                                    #记录处理成功
                                    suc  = 1

                            except Exception as e:
                                fail  = 1
                                logger.debug(e)

                    else:
                        not_import_vcards.append((row[0], row[1]))

            else:
                messages.error(request, '文件格式错误!')


        if fail > 0:
            messages.warning(request, '成功{}条,重复{}条,失败{}条'.format(suc,repeat,fail))
        else:
            messages.success(request, '成功{}条,重复{}条'.format(suc,repeat,fail))
    else:
        form = MyForm()

    content = {
        'title': '文件上传',
        'form': form,
        'not_import_vcards': list(set(not_import_vcards)),
        'suc': suc,
        'fail': fail,
    }

    return  render(request, 'admin/fundrecord_up.html', content)

模板文件

还有一个模板文件,用来接收csv格式的上传文件。

代码语言:javascript复制
{% extends 'admin/base_site.html' %}

{% block content %}

    {{ title }}
    
        {% csrf_token %}
        {{ form.as_p }}
        


        确定
    


{% if not_import_vcards %}




     未在系统内发现下列虚拟卡, 请处理后重新上传:

    
            {% for ncard in not_import_vcards %}
                
            {% endfor %}
        
        
            
                transid
                卡号
                操作
            
        
        
                    {{ ncard.0 }}
                    {{ ncard.1 }}
                    添加此卡
                
    

{% endif %}

{% endblock %}

0 人点赞