Ric*_*ing 2 python django django-forms django-admin django-import-export
I am using django-import-export 1.0.1 with admin integration in Django 2.1.1. I have two models
\n\nfrom django.db import models\n\nclass Sector(models.Model):\n code = models.CharField(max_length=30, primary_key=True)\n\nclass Location(models.Model):\n code = models.CharField(max_length=30, primary_key=True)\n sector = ForeignKey(Sector, on_delete=models.CASCADE, related_name=\'locations\')\nRun Code Online (Sandbox Code Playgroud)\n\n并且可以使用模型资源很好地导入/导出它们
\n\nfrom import_export import resources\nfrom import_export.fields import Field\nfrom import_export.widgets import ForeignKeyWidget\n\nclass SectorResource(resources.ModelResource):\n code = Field(attribute=\'code\', column_name=\'Sector\')\n class Meta:\n model = Sector\n import_id_fields = (\'code\',)\n\nclass LocationResource(resources.ModelResource):\n code = Field(attribute=\'code\', column_name=\'Location\')\n sector = Field(attribute=\'sector\', column_name=\'Sector\',\n widget=ForeignKeyWidget(Sector, \'code\'))\n class Meta:\n model = Location\n import_id_fields = (\'code\',)\nRun Code Online (Sandbox Code Playgroud)\n\n导入/导出操作可以通过以下方式集成到管理中
\n\nfrom django.contrib import admin\nfrom import_export.admin import ImportExportModelAdmin\n\nclass SectorAdmin(ImportExportModelAdmin):\n resource_class = SectorResource\n\nclass LocationAdmin(ImportExportModelAdmin):\n resource_class = LocationResource\n\nadmin.site.register(Sector, SectorAdmin)\nadmin.site.register(Location, LocationAdmin)\nRun Code Online (Sandbox Code Playgroud)\n\n由于Reasons\xe2\x84\xa2,我想更改此设置,以便可以导入不包含扇区列的Locations电子表格;(对于每个导入的行)的值sector应该从额外的字段中获取ImportForm in the admin.
确实可以通过覆盖扩展 django import_export 的管理导入表单中所述的方式import_action来添加这样的字段ModelAdmin. The next step, to use this value for all imported rows, is missing there, and I have not been able to figure out how to do it.
编辑(2):通过使用会话解决。拥有一个get_confirm_import_form钩子在这里仍然很有帮助,但更好的是让现有的ConfirmImportForm进位跨越初始导入表单中所有提交的字段和值。
编辑:抱歉,我以为我已经解决了这个问题,但我自己的代码并没有像我想象的那样工作。这并不能解决sector在 中传递表单字段的问题ConfirmImportForm,而这是完成导入所必需的。目前正在寻找一种不涉及将整个粘贴import_action()到ImportMixin子类中的解决方案。在这里有一个get_confirm_import_form()钩子会有很大帮助。
仍在为自己寻找解决方案,当我有了解决方案时,我也会更新它。
不要覆盖import_action. 这是一个非常复杂的方法,您不想重复。更重要的是,正如我今天发现的:有更简单的方法可以做到这一点。
首先(正如您所提到的),创建一个自定义导入表单,Location允许用户选择Sector:
class LocationImportForm(ImportForm):
sector = forms.ModelChoiceField(required=True, queryset=Sector.objects.all())
Run Code Online (Sandbox Code Playgroud)
在资源 API 中,有一个before_import_row()每行调用一次的钩子。因此,在您的类中实现它LocationResource,并使用它来添加Sector列:
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
Run Code Online (Sandbox Code Playgroud)
(注意:此代码使用 Django 会话将导入表单中的值传送sector到导入确认屏幕。如果您不使用会话,则需要找到另一种方法来执行此操作。)
这就是获取额外数据所需的全部内容,它适用于试运行预览和实际导入。
请注意,self.request默认情况下不存在ModelResource- 我们必须通过提供LocationResource自定义构造函数来安装它:
def __init__(self, request=None):
super()
self.request = request
Run Code Online (Sandbox Code Playgroud)
(不用担心会self.request留下来。每个LocationResource实例不会持续超过一个请求。)
通常request不会传递给ModelResource构造函数,因此我们需要将其添加到该调用的 kwargs 字典中。幸运的是,Django Import/Export 有一个专用的钩子。重写ImportExportModelAdmin的get_resource_kwargs方法LocationAdmin:
def get_resource_kwargs(self, request, *args, **kwargs):
rk = super().get_resource_kwargs(request, *args, **kwargs)
rk['request'] = request
return rk
Run Code Online (Sandbox Code Playgroud)
这就是您所需要的。
| 归档时间: |
|
| 查看次数: |
3807 次 |
| 最近记录: |