如何在 django-import-export 中使用 ForeignKeywidget 解决 MultipleObjectsReturned

Posted

技术标签:

【中文标题】如何在 django-import-export 中使用 ForeignKeywidget 解决 MultipleObjectsReturned【英文标题】:How to solve MultipleObjectsReturned with ForeignKeywidget in django-import-export 【发布时间】:2021-07-07 00:15:19 【问题描述】:

我有一个资源可以帮助我将数据导入我的模型,但它不起作用。我已经尝试了所有我能做的选择,但没有成功。 这是资源。

class ImportStudentsResource(resources.ModelResource):
    klass = fields.Field(attribute = 'class',column_name='class',widget= ForeignKeyWidget(Klass,'name'))
    stream = fields.Field(attribute = 'stream',column_name='stream',widget=ForeignKeyWidget(Stream,'name'))
    gender = fields.Field(attribute = 'gender',column_name='gender', widget=ForeignKeyWidget(Gender, 'name'))
    school = fields.Field(attribute = 'school',column_name='school', widget=ForeignKeyWidget(School, 'name'))
    class Meta:
        model = Students
        fields = ('school','adm','name','kcpe','klass','stream','gender','notes')
        import_id_fields = ('adm',)
        import_order = ('school','adm','name','kcpe','klass','stream','gender','notes')

这是通过资源导入模型的数据

这是回溯。

Traceback (most recent call last):
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\django\views\generic\base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\django\views\generic\base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "D:\Python\Django\Links Online Exams\Links_Online_Results\students\views.py", line 52, in post
    result = resource.import_data(data_set, dry_run=True, collect_failed_rows=True, raise_errors=True)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\import_export\resources.py", line 741, in import_data
    return self.import_data_inner(dataset, dry_run, raise_errors, using_transactions, collect_failed_rows, **kwargs)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\import_export\resources.py", line 788, in import_data_inner
    raise row_result.errors[-1].error
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\import_export\resources.py", line 658, in import_row
    self.import_obj(instance, row, dry_run)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\import_export\resources.py", line 512, in import_obj
    self.import_field(field, obj, data)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\import_export\resources.py", line 495, in import_field
    field.save(obj, data, is_m2m)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\import_export\fields.py", line 110, in save
    cleaned = self.clean(data)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\import_export\fields.py", line 66, in clean
    value = self.widget.clean(value, row=data)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\import_export\widgets.py", line 396, in clean
    return self.get_queryset(value, row, *args, **kwargs).get(**self.field: val)
  File "D:\Python\Django\Links Online Exams\env\lib\site-packages\django\db\models\query.py", line 433, in get
    raise self.model.MultipleObjectsReturned(
students.models.Klass.MultipleObjectsReturned: get() returned more than one Klass -- it returned 2!

None 值的可能原因

class StudentsForm(forms.ModelForm):
    class Meta:
        model = Students
        fields = ("school","name","adm",'klass',"stream","kcpe","gender","notes")
        widgets = 
            'school':forms.TextInput(attrs="class":'form-control','value':'','id':'identifier','type':'hidden'),
            'name':forms.TextInput(attrs="class":'form-control'),
        

    def __init__(self, school, *args, **kwargs):
        super(StudentsForm, self).__init__(*args, **kwargs)
        self.fields['klass'] = forms.ModelChoiceField(
            queryset=Klass.objects.filter(school=school),label='Class')
        self.fields['stream'].queryset = Stream.objects.none()
        if 'klass' in self.data:
            try:
                klass = int(self.data.get('klass'))
                self.fields['stream'].queryset = Stream.objects.filter(klass_id=klass).order_by('name')
            except (ValueError, TypeError):
                pass  # invalid input from the client; ignore and fallback to empty City queryset
        elif self.instance.pk:
            self.fields['stream'].queryset = self.instance.klass.stream_set.order_by('name')

【问题讨论】:

【参考方案1】:

您违反了ForeignKey 类(klass)(以及流)行的约束

Jaq / class 2
Lucy / class 2
# only 1 can have 2 as its a ForeignKey
# same error will happen in stream row 4 Eagle 2 Hawk

你应该在Foreignkey 中使用ManyToMany 字段

文档:https://docs.djangoproject.com/en/3.2/ref/models/fields/#manytomanyfield

【讨论】:

感谢您的努力回答。字段现在实际导入,但在 klass 和流中都没有值...使用 klass__name = fields.Field(widget= ManyToManyWidget(Klass, field = 'name')) stream__name = fields.Field(widget=ManyToManyWidget(Stream, field = '名称')) 请查看我的评论并提供线索。 @nikola 不知道为什么你会得到 None 作为回报。你为什么还要使用多对多关系你是否设置了其他模块或者那些只是文本字段? 如果这是同样的问题,请您删除您的previous question 我认为我添加的表单详细信息导致了所有这些,但现在我不知道如何编辑表单以消除错误。 @nikola

以上是关于如何在 django-import-export 中使用 ForeignKeywidget 解决 MultipleObjectsReturned的主要内容,如果未能解决你的问题,请参考以下文章

使用 django-import-export 在 django 迁移中的外键

使用 django-import-export 导出并显示相关对象的详细名称

Django-Import-Export插件关于外键的处理

django插件之django-import-export

xadmin引入django-import-export导入功能

Django 导入 Excel 端点