Python 扩展django导入导出的导入表单,为每个导入行指定固定值

Python 扩展django导入导出的导入表单,为每个导入行指定固定值,python,django,django-forms,django-admin,django-import-export,Python,Django,Django Forms,Django Admin,Django Import Export,我正在使用django导入导出1.0.1,并在django 2.1.1中进行管理集成。我有两种型号 from django.db import models class Sector(models.Model): code = models.CharField(max_length=30, primary_key=True) class Location(models.Model): code = models.CharField(max_length=30, primary

我正在使用django导入导出1.0.1,并在django 2.1.1中进行管理集成。我有两种型号

from django.db import models

class Sector(models.Model):
    code = models.CharField(max_length=30, primary_key=True)

class Location(models.Model):
    code = models.CharField(max_length=30, primary_key=True)
    sector = ForeignKey(Sector, on_delete=models.CASCADE, related_name='locations')
使用模型资源可以很好地导入/导出它们

from import_export import resources
from import_export.fields import Field
from import_export.widgets import ForeignKeyWidget

class SectorResource(resources.ModelResource):
    code = Field(attribute='code', column_name='Sector')
    class Meta:
        model = Sector
        import_id_fields = ('code',)

class LocationResource(resources.ModelResource):
    code = Field(attribute='code', column_name='Location')
    sector = Field(attribute='sector', column_name='Sector',
                   widget=ForeignKeyWidget(Sector, 'code'))
    class Meta:
        model = Location
        import_id_fields = ('code',)
导入/导出操作可以通过以下方式集成到管理中:

from django.contrib import admin
from import_export.admin import ImportExportModelAdmin

class SectorAdmin(ImportExportModelAdmin):
    resource_class = SectorResource

class LocationAdmin(ImportExportModelAdmin):
    resource_class = LocationResource

admin.site.register(Sector, SectorAdmin)
admin.site.register(Location, LocationAdmin)
原因™, 我希望更改此设置,以便可以导入不包含部门列的位置电子表格;每个导入行的扇区值应取自admin中ImportForm上的额外字段

确实可以通过覆盖ModelAdmin上的import_操作来添加这样的字段,如中所述。下一步,即对所有导入的行使用此值,这里缺少了,我还没有弄清楚如何执行此操作。

EDIT2:通过使用会话解决。有一个get\u confirm\u import\u表单钩子在这里仍然会很有帮助,但是更好的方法是让现有的confirimportform从初始导入表单中携带所有提交的字段和值

编辑:对不起,我以为我已经搞定了,但我自己的代码并没有我想象的那么好。这并不能解决在confirImportForm中传递扇区表单字段的问题,这是完成导入所必需的。目前正在寻找一种解决方案,它不涉及将整个import_操作粘贴到ImportMixin子类中。有一个get\u confirm\u import\u form钩子在这里会有很大帮助

我还在为自己制定解决方案,当我有了解决方案,我也会更新这个

不要覆盖导入操作。这是一个非常复杂的方法,你不想复制它。更重要的是,正如我今天发现的:有更简单的方法可以做到这一点

首先,如您所述,为位置创建一个自定义导入表单,允许用户选择一个扇区:

在资源API中,有一个before_import_row钩子,每行调用一次。因此,在LocationResource类中实现它,并使用它添加扇区列:

注意:此代码使用Django会话将扇区值从导入表单传送到导入确认屏幕。如果不使用会话,则需要找到另一种方法

这就是获取额外数据所需的全部内容,它适用于干运行预览和实际导入

请注意,默认ModelResource中不存在self.request-我们必须通过为LocationResource提供自定义构造函数来安装它:

def __init__(self, request=None):
    super()
    self.request = request
不要担心自己的要求会继续存在。每个LocationResource实例不会在单个请求之外保持不变

请求通常不会传递给ModelResource构造函数,因此我们需要将其添加到该调用的kwargs dict中。幸运的是,Django导入/导出有一个专用的钩子。在LocationAdmin中重写ImportExportModelAdmin的get_resource_kwargs方法:


这就是您所需要的。

我尝试了您的答案,但不幸的是,resources.ModelResource类没有属性请求。你是从哪里得到这个课程的?请看下面的第2/3节,答案行以self.request不存在开始。。。
def before_import_row(self, row, **kwargs):
    sector = self.request.POST.get('sector', None)
    if contract:
        self.request.session['import_context_sector'] = sector
    else:
        # if this raises a KeyError, we want to know about it.
        # It means that we got to a point of importing data without
        # contract context, and we don't want to continue.
        try:
            sector = self.request.session['import_context_sector']
        except KeyError as e:
            raise Exception("Sector context failure on row import, " +
                                 f"check resources.py for more info: {e}")
    row['sector'] = sector
def __init__(self, request=None):
    super()
    self.request = request
def get_resource_kwargs(self, request, *args, **kwargs):
    rk = super().get_resource_kwargs(request, *args, **kwargs)
    rk['request'] = request
    return rk