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
相关产品推荐
相关产品推荐

