Django Admin导入CSV时ForeignKey字段NOT NULL约束失败问题
Django Admin导入含ForeignKey的CSV时触发NOT NULL约束错误(仅Admin面板出现)
在使用django-import-export库通过Django Admin面板导入CSV数据到项目时,导入含ForeignKey关联的Copy模型记录时,始终出现NOT NULL constraint failed: catalog_copy.book_id错误。该问题仅在Admin面板出现,通过Django Shell导入则完全正常。已确认CSV无问题,模型与资源文件也无异常,推测是Admin面板在实际导入前的逻辑出现异常。
点击“提交”按钮时就会触发错误,甚至无法进入“确认导入”步骤。
错误信息
每一行记录都触发如下错误:
Line number: 1 - NOT NULL constraint failed: catalog_copy.book_id Line number: 2 - NOT NULL constraint failed: catalog_copy.book_id ...
相关代码
models.py
from django.db import models from django.core.exceptions import ValidationError class Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=100) isbn = models.CharField(max_length=13) class Format(models.Model): name = models.CharField(max_length=100) class Copy(models.Model): book = models.ForeignKey(Book, related_name='copies', on_delete=models.CASCADE) format = models.ForeignKey(Format, related_name='copies', on_delete=models.CASCADE) location = models.CharField(max_length=100) is_available = models.BooleanField(default=True)
resources.py
from import_export import resources from .models import Copy class CopyResource(resources.ModelResource): class Meta: model = Copy fields = ('id', 'book', 'format', 'location', 'is_available') import_id_fields = ['id'] def before_import_row(self, row, **kwargs): book_title = row.get('Book Title') isbn = row.get('ISBN') author = row.get('Author') format_name = row.get('Format') book, created = Book.objects.get_or_create( title=book_title, defaults={'isbn': isbn, 'author': author} ) format, created = Format.objects.get_or_create( name=format_name ) row['book'] = book.pk row['format'] = format.pk
admin.py
from django.contrib import admin from import_export.admin import ImportExportModelAdmin from .models import Copy from .resources import CopyResource class CopyAdmin(ImportExportModelAdmin): resource_class = CopyResource admin.site.register(Copy, CopyAdmin)
Shell导入验证(成功)
已通过以下Shell命令成功导入CSV:
import tablib from catalog.resources import CopyResource with open('library_copies.csv', 'r', encoding='utf-8') as f: data = tablib.Dataset().load(f.read(), format='csv') resource = CopyResource() result = resource.import_data(data, dry_run=False) if result.has_errors(): print("Errors occurred during the import:") for error in result.base_errors: print(f"Base error: {error.error}") else: print("The import would proceed without errors.")
日志对比
对比Shell与Admin面板的日志,发现Admin面板未执行CopyResource中的逻辑,尽管面板显示使用的是CopyResource。
Shell日志片段
0.000) BEGIN; args=None; alias=default (0.000) SAVEPOINT "s8585724224_x6"; args=None; alias=default ... Before importing row... OrderedDict({'id': '1', 'Book Title': 'Thank You for My Service ', ...}) (0.000) SELECT "catalog_book"."id", ... FROM "catalog_book" WHERE "catalog_book"."title" = 'Thank You for My Service ' LIMIT 21; ...
Admin面板日志片段
(0.000) BEGIN; args=None; alias=default (0.000) SAVEPOINT "s6196490240_x1"; args=None; alias=default ... (0.000) INSERT INTO "catalog_copy" ("book_id", "format_id", ...) VALUES (NULL, NULL, '', 1) RETURNING "catalog_copy"."id"; ...
内容的提问来源于stack exchange,提问作者Billy Groble
相关产品推荐
相关产品推荐

