You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django import_export测试:POST数据后dataset为None的问题求助

问题

测试Django import_export的导入功能时,明明提供了正确的CSV文件,运行测试却提示“no dataset (None)”,导致self.assertIn('result', response.context)及后续断言全部失败。为什么资源类和import_data方法无法识别response = self.client.post(import_url, data=data)中传入的dataset?

测试代码

class ImportUserCase(TestCase):
    
    def setUp(self) -> None:
        self.admin = User.objects.create(login='admin', email='admin@example.com', password='password', is_staff=True, is_superuser=True)
        self.client = Client()
        self.client.force_login(self.admin)
        self.resource = UserImportResource()
    
    def test_import_action(self) -> None:
        import_url = '/admin/core/user/import/'
        process_url = '/admin/core/user/process_import/'
        
        input_format = '0'
        filename = 'users.csv'
        with open('users.csv', 'w') as f:
            writer = csv.writer(f)
            writer.writerow(UserImportResource.Meta.fields)
            # 原代码存在引号不匹配+参数格式错误,已修正
            writer.writerow(['test', 'test@gmail.com', 'test', 'test', 'test'])
        with open(filename, "rb") as f:
            data = {
                'input_format': input_format,
                'import_file': f,
            }
            response = self.client.post(import_url, data=data)
            self.assertEqual(response.status_code, 200)

            self.assertIn('result', response.context) 
            self.assertFalse(response.context['result'].has_errors())
            self.assertIn('confirm_form', response.context)
            confirm_form = response.context['confirm_form']

            data = confirm_form.initial
            # 原代码文件名断言不匹配,生成的是users.csv却断言books.csv
            self.assertEqual(data['original_file_name'], 'users.csv')
            response = self.client.post(process_url, data, follow=True)
            self.assertEqual(response.status_code, 200)

资源类代码

class UserImportResource(resources.ModelResource):
    class Meta:
        model = User
        instance_loader_class = UserLoader
        fields = ('login', 'email', 'first_name', 'last_name', 'gender')
        use_transactions = False

    def get_import_id_fields(self):
        return ['email']

    def get_import_fields(self):
        return [self.fields[f] for f in self.get_import_field_names()]

    def get_import_field_names(self):
        return ('login', 'email', 'first_name', 'last_name', 'gender')

    def before_import(self, dataset, using_transactions, dry_run, **kwargs):
        to_delete = []
        for idx, row in enumerate(dataset.dict):
            if not row['email'] or not row['email'].strip():
                to_delete.append(idx)
        for idx in sorted(to_delete, reverse=True):
            del dataset[idx]

    def before_import_row(self, row, **kwargs):
        if not row['email']:
            return
        row['email'] = row['email'].strip()

    def import_data(self, dataset, dry_run=False, raise_errors=False,
                    use_transactions=None, collect_failed_rows=False, **kwargs):
        print(f'dataset: {dataset}') # 输出None而非实际数据集
        result = self.get_result_class()()
        fns = self.get_import_field_names()

        # 原代码存在缩进错误+header变量未定义,导致逻辑异常
        # if header not in fns or header == 'id':
        #     err_msg = 'Error'
        #     result.append_base_error(self.get_error_result_class()(err_msg))
        #     return result

        user_logins_search = {str(row['login']).strip() for row in dataset.dict}
        available_login_map = {}
        for user_data in User.objects.filter(login__in=user_logins_search).values('login', 'email'):
            available_login_map[user_data['login']] = user_data['email']

        using_transactions = False if dry_run else True
        with atomic_if_using_transaction(using_transactions):
            return self.import_data_inner(dataset, dry_run, raise_errors, False, collect_failed_rows, **kwargs)

    def get_user_visible_fields(self):
        return self.get_import_fields()
问题排查与解决

1. 测试代码的低级错误

  • CSV写入格式错误:原代码中writer.writerow('test', 'test@gmail.com', 'test, 'test', 'test')有两个问题:一是引号不匹配('test,缺少闭合引号),二是writerow要求传入列表/元组而非零散参数,这会导致生成的CSV文件损坏,后端无法解析出有效dataset。
  • 文件名断言不匹配:测试生成的是users.csv,但断言写的是books.csv,不仅会导致断言失败,还可能干扰后续流程的文件校验逻辑。

2. 资源类import_data的代码逻辑错误

  • 未定义变量+缩进错误:原代码中if header not in fns or header == 'id':这段代码,header变量完全未定义,且缩进层级错误。执行到这里会直接抛出NameError,方法提前返回错误结果,后续代码无法正常处理dataset,最终导致传入的dataset被置为None。直接删除这段无意义的代码即可解决。

3. 验证CSV文件有效性

修复测试代码后,手动检查生成的users.csv内容是否符合预期:

login,email,first_name,last_name,gender
test,test@gmail.com,test,test,test

如果文件内容为空、格式错乱,后端解析时会无法生成dataset,自然会出现dataset: None的情况。

内容的提问来源于stack exchange,提问作者NSS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 13:50:01