Home > Net >  django-import-export update profile if email exists
django-import-export update profile if email exists

Time:11-26

I have this unique field on my Profile model:

email = models.EmailField(max_length=200, unique=True)

and I have this ProfileResource:

class ProfileResource(resources.ModelResource):

    # associated_issuer = fields.Field(attribute='add_associated_issuer', widget=ManyToManyWidget(Issuer, field='name'), column_name='Associated Issuer')
    email = fields.Field(attribute='email', 
        widget=CharWidget(), 
        column_name='email')

    class Meta:
        model = Profile
        clean_model_instances = True
        import_id_fields = ('id', 'email')

    def before_import_row(self, row, row_number=None, **kwargs):
        try:
            self.email = row["email"] 
        except Exception as e:
            self.email = ""

        try:
            if row["id"] == '':
                row["id"] = None
                self.id = row["id"] 
        except Exception as e:
            self.id = None

        try:
           self.firstname = row["firstname"] 
        except Exception as e:
            self.firstname = ""

        try:
           self.lastname = row["lastname"]
        except Exception as e:
            self.lastname = ""

Now when I try to do an import from a file, I receive this error:

enter image description here

I need to be able to do an update_or_create method, but where do I add that code? I tried doing it on an after_import_instance but it did not work.

I also tried on import_row like this:

def import_row(self, row, instance_loader, using_transactions=True, dry_run=False, **kwargs):
    try:
        Profile.objects.update_or_create(email=self.email)
    except Exception as e:
        print(e, file=sys.stderr)

but it produced this error:

Exception Value: 'NoneType' object has no attribute 'import_type'

Any insights on a fix would be appreciated.

CodePudding user response:

#try this 

email = models.EmailField(max_length=200, unique=True, null=True)

        try:
            self.email = row["email"] 
        except Exception as e:
            self.email = None

unique=True also block duplicated "", but null is not blocked.

CodePudding user response:

Notice that you have this line on your ProfileResource

import_id_fields = ('id', 'email')

This means that the import will look at each row in your import file, and attempt to load any Profile instances which match both id and email.

Therefore if you only need to update email, then simply remove this from the list of import_id_fields. By doing that, the logic will uniquely identify instances based solely on id, and then new records will be created if they don't exist, and any existing records will be updated (which will include updating the email address).

This is how import-export is supposed to work and no further logic is required.

If email is the "unique field" which matches your existing instances, then this should be the only field in import_id_fields. There cannot be two Profile instances with the same email, because unique=True, therefore you can use email as the import_id_field. However it will not be possible to update the Profile email using import-export (although you could introduce a field called new_email and have logic to update the Profile that way, but that is a separate topic).

I don't know why you are seeing the 'email already exists' error - possibly something else is going on, and it could be the logic in before_import_row() which is causing the problem, probably due to the fact that a row is being created with empty string as the email.

btw - you shouldn't need any of the logic in before_import_row() - import-export should handle this for you, and by overriding you might be introducing further bugs.

The best advice for using import-export is to set breakpoints in your IDE, and then step through during an import and you can see exactly what is happening. This will save you a lot of time in the long run.

In summary, use either id or email in import_id_fields and it should work.

  • Related