Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Declaring a Resource Field changes the export order #1663

Closed
matthewhegarty opened this issue Oct 22, 2023 · 4 comments · Fixed by #1692
Closed

Declaring a Resource Field changes the export order #1663

matthewhegarty opened this issue Oct 22, 2023 · 4 comments · Fixed by #1692
Labels

Comments

@matthewhegarty
Copy link
Contributor

Describe the bug

If declaring a Field in a Resource, this causes the export order to change:

Without declaration:

Screenshot 2023-10-22 at 19 10 35

With declaration:

Screenshot 2023-10-22 at 19 10 17

To Reproduce

Declare a Field in Resource:

class BookResource(ModelResource):
    published = Field(attribute='published', column_name='published_date',
        widget=DateWidget(format='%d.%m.%Y'))

    class Meta:
        model = Book

Export the book.

Note this doesn't occur (i.e. order is preserved) if you use the widgets dict:

class BookResource(resources.ModelResource):

    class Meta:
        model = Book
        widgets = {
            'published': {'format': '%d.%m.%Y'},
        }

Versions (please complete the following information):

  • Django Import Export: 3.3.1
  • Python 3.11
  • Django 4.2

Expected behavior

Declaring Field should not affect the export order.

@cocorocho
Copy link
Contributor

Hello,

I looked into the issue and it seems to be caused by DeclarativeMetaclass. Since ModelDeclarativeMetaclass inherits DeclarativeMetaclass and declared fields are defined first by the parent model, ModelDeclarativeMetaclass appends model fields into the fields defined by DeclarativeMetaclass so the ordering is like:

Declared Fields + Model Fields.

My suggested solution is re construct new OrderedDict for resource.fields after extracting fields from model.

Current behavior

# Resource class already has declared fields so model fields are appended
new_class.fields.update(OrderedDict(field_list))

Suggested change

# Model fields are first then declared fields
new_class.fields = OrderedDict([
    *field_list,
    *new_class.fields.items()
])

Example

class BookResource(ModelResource):
    publish_date = fields.Field(
        attribute="publish_date",
        column_name="publish_date",
        widget=widgets.DateWidget("%d.%M.%Y")
    )

    class Meta:
        model = Book
        fields = ["id", "name", "publish_date"]

Screenshot 2023-11-22 101124

@matthewhegarty
Copy link
Contributor Author

Thanks for looking into it - it sounds like a decent solution.

@cocorocho
Copy link
Contributor

I was going to create a PR but should this be the intended behavior?

Basically, declared fields are going to be in the end. This is not going to preserve the actual model field order.

Example

class Book(Model):
    name = CharField()
    published = DateField()
    author = CharField()
    author_email = EmailField()


class BookResrouce(ModelResource):
    published = fields.Field(
        attribute="published",
        column_name="published_date",
        widgets.DateWidget("%d.%M.%Y")
    )

    class Meta:
        model = Book

# My solution's outcome
# id, name, author, author_email, published

# Or should it be
# id, name, published, author, author_email

@matthewhegarty
Copy link
Contributor Author

This is not going to preserve the actual model field order.

Do you know if it would be possible to do this, because that would be the best outcome.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants