Как мне упорядочить поля импорта в админке, используя django import-export? - PullRequest
0 голосов
/ 10 февраля 2019

Я использую 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

Это скриншот вида импорта из документации :

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 голосов
/ 09 апреля 2019

export_order - это ответ!

Добавьте опцию export_order в мета-поле ваших ресурсов следующим образом:

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 импортирует указанные вами поля соответственно!Причина, по которой это работает, заключается в том, что export_order вызывается get_fields (), который, в свою очередь, вызывается 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 .Для дальнейшего разъяснения я бы также порекомендовал рабочий процесс импорта данных , документацию и методы для ресурсов import_export .

Надеюсь, это может помочь!

...