如何使用django import-export在admin中订购导入字段?

时间:2019-02-10 13:20:04

标签: python django django-import-export

我正在使用django import-export和ImportExportModelAdmin从管理界面将数据从文件导入数据库。

以下是我使用的模型资源:

class ImportedBetResource(resources.ModelResource):
    date = fields.Field(column_name='Date',
                         attribute='date',
                         widget=DateWidget(format="%d/%m/%Y"))
    time = fields.Field(column_name='Time',
                         attribute='time',
                         widget=TimeWidget(format="%H:%M"))
    sport = fields.Field(column_name='Sport',
                         attribute='sport',
                         widget=ForeignKeyWidget(Sport, 'name'))
    country = fields.Field(column_name='Country',
                           attribute='country',
                           widget=ForeignKeyWidget(Country, 'name'))
    bookie = fields.Field(column_name='Bookie',
                          attribute='bookie',
                          widget=ForeignKeyWidget(Bookie, 'name'))
    currency = fields.Field(column_name='Currency',
                            attribute='stake_currency',
                            widget=ForeignKeyWidget(Currency, 'name'))
    odds = fields.Field(column_name="Odds",
                        attribute="odds",
                        widget=DecimalWidget())
    status = fields.Field(column_name='Status',
                          attribute='status',
                          widget=ForeignKeyWidget(Status, 'name'))

    class Meta:
        model = Bet
        fields = ("id", "date", "time", "sport",
                  "country",
                  "competition", "home",
                  "visitor",
                  "bookie", "bet", "stake",
                  "currency",
                  "odds", "status")
        clean_model_instances = True


    @classmethod
    def field_from_django_field(self, field_name, django_field, readonly):
        """
        Returns a Resource Field instance for the given Django model field.
        """
        FieldWidget = self.widget_from_django_field(django_field)
        widget_kwargs = self.widget_kwargs_for_field(field_name)
        field = fields.Field(attribute=field_name, column_name=field_name.replace("__name", "").title(),
                             widget=FieldWidget(**widget_kwargs), readonly=readonly)
        return field

这是来自documentation的导入视图的屏幕截图:

enter image description here

您可以看到文本“此导入程序将导入以下字段”,后跟字段名称。

就我而言,显式定义的字段首先出现,例如:

country = fields.Field(column_name='Country',
                       attribute='country',
                       widget=ForeignKeyWidget(Country, 'name'))

,然后是class Meta fields中定义的其余字段:

 This importer will import the following fields: Date, Time, Sport, Country, Bookie, Currency, Odds, Status, Id, Competition, Home, Visitor, Bet, Stake

问题在于字段的顺序不符合文件中字段的顺序,并且数据变得混乱。

仅当文件中有错误时才会发生。

1 个答案:

答案 0 :(得分:2)

export_order是答案!

将export_order选项添加到资源的Meta字段中,如下所示:

class Meta:
        model = Bet
        fields = ("id", "date", "time", "sport",
                  "country",
                  "competition", "home",
                  "visitor",
                  "bookie", "bet", "stake",
                  "currency",
                  "odds", "status")
        clean_model_instances = True
        export_order = ["Date", "Time", "Sport", "Country", 
                       "Bookie", "Currency", "Odds", "Status", 
                       "Id", "Competition", "Home", "Visitor", 
                       "Bet", "Stake"]

或以您想要的任何首选顺序)和django-import-export将相应地导入您声明的字段!之所以可行,是因为get_fields()调用了export_order,而get_import_fields()和get_export_fields()又调用了该命令,从而影响了两个流程的整个工作流程。

def export_order = None
def get_fields(self, **kwargs):
        """
        Returns fields sorted according to
        :attr:`~import_export.resources.ResourceOptions.export_order`.
        """
        return [self.fields[f] for f in self.get_export_order()]

def get_import_fields(self):
        return self.get_fields()
def get_export_fields(self):
        return self.get_fields()

def import_obj(self, obj, data, dry_run):
        """
        Traverses every field in this Resource and calls
        :meth:`~import_export.resources.Resource.import_field`. If
        ``import_field()`` results in a ``ValueError`` being raised for
        one of more fields, those errors are captured and reraised as a single,
        multi-field ValidationError."""
        errors = {}
        for field in self.get_import_fields():
            if isinstance(field.widget, widgets.ManyToManyWidget):
                continue
            try:
                self.import_field(field, obj, data)
            except ValueError as e:
                errors[field.attribute] = ValidationError(
                    force_text(e), code="invalid")
        if errors:
            raise ValidationError(errors)

上面是import_export.resources.py的摘录。为了进一步说明,我还建议导入数据工作流documentation和import_export的resources的方法。

我希望这会有所帮助!