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

Issue with adding rows with generated field #1779

Closed
uncountablereals opened this issue Mar 29, 2024 · 6 comments
Closed

Issue with adding rows with generated field #1779

uncountablereals opened this issue Mar 29, 2024 · 6 comments
Labels

Comments

@uncountablereals
Copy link

uncountablereals commented Mar 29, 2024

Describe the bug
Import of rows via django admin breaks when I have a generated column, but works with that field commented out.

To Reproduce
Steps to reproduce the behavior:

Import of rows for a model with a generated field.

Versions (please complete the following information):

  • Django Import Export: [e.g. 1.2, 2.0]
  • django 5.0
  • import export 3.3.7

Expected behavior
Import of rows for a table.

The import works fine when I have no generated column, but breaks when the table has a generated column

class OperationsExportShipments(models.Model):
    shipment_id = models.CharField(primary_key=True)
    <details removed>
    # cost = models.GeneratedField(
    #     expression=RawSQL('COALESCE(quote_cost, reconciled_cost)',[]),
    #     db_column='cost',
    #     output_field=models.DecimalField(max_digits=10, decimal_places=2),
    #     db_persist=True,
    # )

Import of my spreadsheet works fine with the cost generated field commented out, but breaks when it is present

Screenshots
I can DM these but as it's company code and data I cannot post here.

Additional context
Add any other context about the problem here.

@matthewhegarty
Copy link
Contributor

Thanks for raising. I couldn't reproduce with the example app. I created a test branch here.

I added this code to the Book model:

image

I ran the new migrations and then tried to import with the attached file. The import worked fine for me.

books_with_generatedfield.csv

Is it possible you can reproduce using the branch and example file? Or perhaps you can give me clearer steps to reproduce?

@uncountablereals
Copy link
Author

uncountablereals commented Mar 30, 2024

Slightly adjusted tables below

class OperationsExportShipments(models.Model):
    shipment_id = models.CharField(primary_key=True)
    shipment_status = models.ForeignKey(OperationsExportShipmentsStatuses, models.DO_NOTHING, db_column='shipment_status')
    checked_in = models.BooleanField()
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    fba_shipment = models.OneToOneField(FbaShipments, models.DO_NOTHING, db_column='fba_shipment',null=True,blank=True)
    walmart_shipment = models.OneToOneField(WalmartShipments, models.DO_NOTHING, db_column='walmart_shipment',null=True,blank=True)
    shipment_carrier = models.ForeignKey(WarehouseCarriers, models.DO_NOTHING, db_column='shipment_carrier',null=True,blank=True)
    mock_generated_column =   models.GeneratedField(
        expression=RawSQL("1", []),
        output_field=models.IntegerField(),
        db_persist=True
    )

    
    class Meta:
        managed = True
        db_table = 'operations_export_shipments'
        
        #contraint that exactly one of fba_shipment or walmart_shipment must be set
        constraints = [
            models.CheckConstraint(
                check=(
                    (Q(fba_shipment__isnull=False) & Q(walmart_shipment__isnull=True)) |
                    (Q(fba_shipment__isnull=True) & Q(walmart_shipment__isnull=False))
                ),
                name='check_fba_walmart_shipment_exclusivity'
            ),
            #constraint that checked_in can only be True if shipment_status is 'ARRIVED'
            models.CheckConstraint(
                check=(
                    Q(checked_in=False) | 
                    (Q(checked_in=True) & Q(shipment_status='ARRIVED'))
                ),
                name='check_checked_in_with_status_arrived'
            )
        ]

class OperationsExportShipmentsResource(resources.ModelResource):
    class Meta:
        model = OperationsExportShipments
        fields = (
            "fba_shipment","walmart_shipment",
            "shipment_status",
            "checked_in"
        )

    def before_import_row(self, row, **kwargs):
        """
        Override this method to add logic before saving an instance.
        Use this to determine if a row corresponds to an FBA shipment or Walmart shipment and handle accordingly.
        """
        row["shipment_status"] = row["shipment_status"].upper().replace(" ","_")
        if not row["fba_shipment"]:
            row["fba_shipment"] = None
        if not row["walmart_shipment"]:
            row["walmart_shipment"] = None

        if row["checked_in"].lower().strip() == "yes":
            row["checked_in"] = True
        elif row["checked_in"].lower().strip() == "no":
            row["checked_in"] = False
        else:
            row["checked_in"] = None
        print(row)
        super().before_import_row(row, **kwargs)



    def get_instance(self, instance_loader, row):
        """
        Override to custom handle identifying existing instances.
        """
        # print(row)
        # self.Meta.model.objects.get(fba_shipment=row['fba_shipment'],
                                           # walmart_shipment=row['walmart_shipment'])
        print("stage 2")
        try:

            return self.Meta.model.objects.get(fba_shipment=row['fba_shipment'],
                                                walmart_shipment=row['walmart_shipment'])
        except self.Meta.model.DoesNotExist:
            print("no instance foudn!")
            return None        

When I upload a csv with a new row on this, I get the following error:

Line number: 6 - Save with update_fields did not affect any rows.

Traceback (most recent call last):
File .../.venv/lib/python3.10/site-packages/import_export/resources.py", line 817, in import_row
self.save_instance(instance, new, using_transactions, dry_run)
File ".../.venv/lib/python3.10/site-packages/import_export/resources.py", line 528, in save_instance
instance.save()
File "...models.py", line 598, in save
super().save(*args, **kwargs)
File .../django/db/models/base.py", line 814, in save
self.save_base(
File  .../django/db/models/base.py", line 901, in save_base
updated = self._save_table(
File ...django/db/models/base.py", line 1034, in _save_table
raise DatabaseError("Save with update_fields did not affect any rows.")
django.db.utils.DatabaseError: Save with update_fields did not affect any rows.

So the updated rows were fine with the import, but there was an issue with the new row.

Now I comment out the generated column

class OperationsExportShipments(models.Model):
    shipment_id = models.CharField(primary_key=True)
    shipment_status = models.ForeignKey(OperationsExportShipmentsStatuses, models.DO_NOTHING, db_column='shipment_status')
    checked_in = models.BooleanField()
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    fba_shipment = models.OneToOneField(FbaShipments, models.DO_NOTHING, db_column='fba_shipment',null=True,blank=True)
    walmart_shipment = models.OneToOneField(WalmartShipments, models.DO_NOTHING, db_column='walmart_shipment',null=True,blank=True)
    shipment_carrier = models.ForeignKey(WarehouseCarriers, models.DO_NOTHING, db_column='shipment_carrier',null=True,blank=True)
    # mock_generated_column =   models.GeneratedField(
    #     expression=RawSQL("1", []),
    #     output_field=models.IntegerField(),
    #     db_persist=True
    # )

And the upload is fine

image

@matthewhegarty
Copy link
Contributor

Thanks - I can reproduce when uploading a new row.

@matthewhegarty
Copy link
Contributor

Have raised as Django issue

@sarahboyce
Copy link

Confirmed this is an issue in Django 5.0 rather than django-import-export. A fix for this will be part of the 5.0.5 release expected May 6th 👍 thank you both

@matthewhegarty
Copy link
Contributor

Thanks @sarahboyce for the update and fix.

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

No branches or pull requests

3 participants