自定义Excel导入功能

例:

def import_data_from_excel(conf, filename, fk_name=None, fk_value=None, is_exchange=False):

    def valid_date(d):
        try:
            xlrd.xldate.xldate_as_datetime(d, 0)
            return True
        except:
            return False

    def check_field_with_input(field, i):
        t = type(field)

        choices = field.__dict__["choices"]
        if choices:
            for key, value in choices:
                if value == i.strip():
                    return True
            if field.__dict__["null"] is True and type(i) == unicode and not i.strip():
                return True
            return False

        if t in [IntegerField, FloatField, ForeignKey]:
            return type(i) in [float, int]

        if t in [CharField, TextField]:
            return type(i) == unicode

        if field.__dict__["null"] is True and type(i) == unicode and not i.strip():
            return True

        if t == DateField:
            return valid_date(i)

        return False

    # 检查attributes, primary_keys, defaults 定义的数据列在表里面
    def check_conf(c):
        obj = create_instance(c)
        attrs = c["attributes"].keys() + c.get("primary_keys", [])
        if c.get("defaults", None):
            attrs = attrs + c["defaults"].keys()
        for k in attrs:
            if not hasattr(obj, k):
                print "{} has no attr '{}', please check.".format(c["class_name"], k)
                return False

        if fk_name:
            if not hasattr(obj, fk_name):
                print "{} has no foreign key '{}', please check.".format(c["class_name"], fk_name)
                return False

        return True

    def check_excel_input(c, sheet):
        rows_len, cols_len = sheet.nrows, sheet.ncols
        class_name = get_class(c)
        for r in range(1, rows_len):
            r_data = sheet.row_values(r)
            for k, v in c["attributes"].items():
                if v > cols_len:
                    return STRING_EXCEL_CONFIGURATION_EXCEEDS.format(cols_len, k, v)
                if not check_field_with_input(class_name._meta.get_field(k), r_data[v]):
                    return STRING_EXCEL_LINE_INPUT_ERROR.format(r + 1, v, r_data[v])
        return "success"

    def do_excel_input(c, sheet):
        item = get_class(c)
        rows_len, cols_len = sheet.nrows, sheet.ncols
        default_values = c.get("defaults", None)
        for r in range(1, rows_len):
            r_data = sheet.row_values(r)
            pks = conf.get("primary_keys", None)
            if pks:
                filter_dict = {}
                for pk in pks:
                    field = item._meta.get_field(pk)
                    choices = field.__dict__["choices"]
                    if choices:
                        for key, value in choices:
                            if value == r_data[conf["attributes"][pk]]:
                                filter_dict[pk] = key
                    else:
                        filter_dict[pk] = r_data[conf["attributes"][pk]]
                if fk_name and fk_value:
                    filter_dict[fk_name] = fk_value
                rs = get_class(c).objects.filter(**filter_dict)
                d = rs[0] if len(rs) > 0 else create_instance(c)
            else:
                d = create_instance(c)
            for k, v in conf["attributes"].items():
                if type(r_data[v]) == unicode and not str(r_data[v].strip()):
                    continue
                field = d._meta.get_field(k)
                if type(field) == DateField:
                    d.__setattr__(k, xlrd.xldate.xldate_as_datetime(r_data[v], 0))
                elif field.__dict__["choices"]:
                    for key, value in field.__dict__["choices"]:
                        if value == r_data[v].strip():
                            d.__setattr__(k, key)
                else:
                    d.__setattr__(k, r_data[v])
                if fk_name and fk_value:
                    d.__setattr__(fk_name, fk_value)
                    # 此操作只用来对采购和发行的节目进行换片操作
                    if is_exchange and hasattr(d, "status"):
                        d.__setattr__("status", 3)

            if default_values:
                for k, v in default_values.items():  # 对默认值的处理,对应若干历史财务数据
                    d.__setattr__(k, v)
            d.save()

    if not check_conf(conf):
        return STRING_IMPORT_CONFIGURATION_ERROR

    sheet_index = conf.get("excel_sheet", 0)
    # print "System will import {} sheet".format(sheet_index)
    try:
        import_sheet = xlrd.open_workbook(filename).sheet_by_index(int(sheet_index))
    except:
        return STRING_EXCEL_OPEN_ERROR

    try:
        check_input = check_excel_input(conf, import_sheet)
        if not check_input == "success":
            return check_input

        do_excel_input(conf, import_sheet)
        return STRING_EXCEL_IMPORT_SUCCESS
    except Exception as e:
        print e
        return STRING_EXCEL_GET_RECORDS_ERROR
ProductItemExcelImportConfig = {
    "module_name": "Product.models",
    "class_name": "ProductItem",
    "attributes": {
        "sn": 0,                # 序号
        "name": 1,              # 节目名称
        "type": 2,              # 类别
        "theme": 3,             # 类型
        "episodes": 4,          # 集数
        "episodes_time": 5,     # 单集时长
        "total_time": 6,        # 总时长
        "clarity": 7,           # 分辨率
        "play_time": 8,         # 播出时间
        "play_app": 9,          # 播出平台
        "production_time": 10,  # 出品年代
        "area": 11,             # 制片地区
        "actor": 12,            # 主演
        "writers": 13,          # 编剧
        "director": 14,         # 导演
        "plots": 15,            # 剧情介绍
        "authorized_time": 16,  # 授权开始日期
        "authorized_end_time": 17,   # 授权结束日期
        "authorized_way": 18,   # 授权方式
        "authorized_area": 19,  # 授权权利
        "publish_licence": 20,  # 发行许可证
        "make_company": 21,     # 制作机构
        "up_copyright": 22,     # 上游版权方
        "copy_chain": 23,       # 版权链
        "site_limit": 24,       # 站点限制
        "item_status": 25,      # 节目状态
        "remark": 27,           # 备注
    },
    "primary_keys": ["name", "authorized_area", "up_copyright"],
    "defaults": {
        "item_source": '2',  # 标示从Excel数据导入
    },

}
# 导入可销售节目
def import_product_items(request):
    try:
        path = get_upload_file_path()
        if request.method == 'POST':
            file_obj = request.FILES.get('file')
            # 判断选择文件
            if file_obj:
                filename = os.path.join(path, file_obj.name)
                file_type = str(os.path.splitext(filename)[1])
                # 判断文件类型
                if file_type in [".xls", ".xlsx"]:
                    # 判断文件是否重名或者是否已经存在
                    if os.path.exists(filename):
                        filename = filename + time.strftime(".%Y%m%d%H%M%S", time.localtime())
                        # 把上传过来的文件保存
                    excel_file = open(filename, 'wb+')
                    for file_data in file_obj.chunks():
                        excel_file.write(file_data)
                    excel_file.close()
                    r_url = ""
                    res = import_data_from_excel(ProductItemExcelImportConfig, filename)
                    result = {"statue": "success", "data": res}
                    return JsonResponse(result)
                else:
                    result = {"statue": "error", "data": "文件格式不对,必须是 xls或xlsx"}
                    return JsonResponse(result)
            else:
                result = {"statue": "error", "data": "你没有选择文件呢!!!"}
                return JsonResponse(result)
        result = {"statue": "error", "data": "你没有选择文件呢!!!"}
        return JsonResponse(result)
    except Exception as e:
        return render(request, 'error.html', locals())

猜你喜欢

转载自blog.csdn.net/qq_42336556/article/details/85259728