Django Integrity Error in Bulk Import via CSV in Admin
<p>I am trying to implement a CSV Import in Django Admin and save bulk data corresponding to the CSV file's rows. I have a model <code>Employee</code> with a <code>OneToOneField</code> to Django's <code>Auth</code> model. I have written a custom Form that accepts a csv file. However, when I call the super().save() method, I get an Integrity Error.</p>

<p>My Model class is:</p>

<pre><code>class Employee(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    company = models.ForeignKey(Companies)
    department = models.ForeignKey(Departments)
    mobile = models.CharField(max_length=16, default="0", blank=True)
    gender = models.CharField(max_length=1, default="m", choices=GENDERS)
    image = models.ImageField(upload_to=getImageUploadPath, null=True, blank=True)
    designation = models.CharField(max_length=64)
    is_hod = models.BooleanField(default=False)
    is_director = models.BooleanField(default=False)
</code></pre>

<p>This is my Admin class:</p>

<pre><code>class EmployeeAdmin(admin.ModelAdmin):
    list_display = ('user', 'company', 'department', 'designation', 'is_hod', 'is_director')
    search_fields = ['user__email', 'user__first_name', 'user__last_name']
    form = EmployeeForm
</code></pre>

<p>This is my Form class:</p>

<pre><code>class EmployeeForm(forms.ModelForm):
    company = forms.ModelChoiceField(queryset=Companies.objects.all())
    file_to_import = forms.FileField()

    class Meta:
        model = Employee
        fields = ("company", "file_to_import")

    def save(self, commit=True, *args, **kwargs):
        try:
            company = self.cleaned_data['company']
            records = csv.reader(self.cleaned_data['file_to_import'])
            for line in records:
                # Get CSV Data.

                # Create new employee.
                employee = CreateEmployee(email, firstName, lastName, gender, '', company.id, dept[0].id, designation, 
                           isSuperuser, isHod, isDirector)
            super(EmployeeForm, self).save(*args, **kwargs)

        except Exception as e:
            traceback.print_exc()
            raise forms.ValidationError('Something went wrong.')
</code></pre>

<p>The <code>CreateEmployee</code> method is defined as:</p>

<pre><code>@transaction.atomic
def CreateEmployee(email='', firstName='', lastName='', gender='', mobile='',
    companyId='', departmentId='', designation='', isSuperuser=False, isHod=False, isDirector=False):
    try:
        user = User(
            username=email,
            email=email,
            first_name=firstName,
            last_name=lastName,
            is_superuser=isSuperuser,
            is_active=True)
        password = getPassword(firstName, lastName)
        user.set_password(password)
        user.save()

        company = Companies(id=companyId)
        dept = Departments(id=departmentId)

        employee = Employee(
            user=user,
            mobile=mobile,
            gender=gender,
            designation=designation,
            company=company,
            department=dept,
            is_hod=isHod,
            is_director=isDirector)
        employee.save()
        return employee
    except DatabaseError as e:
        raise e
    return None
</code></pre>

<p>I am getting an exception in the form's except block with the error: <code>IntegrityError: (1048, "Column 'user_id' cannot be null")</code></p>

<p>In the traceback, I can see that the exception is being raised in the <code>super(EmployeeForm, self).save(*args, **kwargs)</code> line. I am assuming the super method is trying to save an instance.</p>

<p>The complete traceback is:</p>

<pre><code>Traceback (most recent call last):
  File "/home/rachit/Projects/project/users/forms.py", line 81, in save
    super(EmployeeForm, self).save(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py", line 455, in save
    construct=False)
  -- lot of text --
IntegrityError: (1048, "Column 'user_id' cannot be null")
</code></pre>

<p>I am guessing the ModelForm's save method is trying to save an instance, but I don't want that to happen as I have created multiple users.</p>

<p>What am I doing wrong here? Is there an alternative way to achieve what I want?</p>

<p>TIA.</p>

<p>Since youâre doing your own save, you donât need to call save on the Super form.  Typically when you have foreign key fields that you need to fill in like this, you use commit=False to get an instance of the unsaved model., but you can do either of these:</p>

<pre><code>def save(self, commit=True, *args, **kwargs):
    try:
        company = self.cleaned_data['company']
        records = csv.reader(self.cleaned_data['file_to_import'])
        for line in records:
            # Get CSV Data.

            # Create new employee.
            employee = CreateEmployee(email, firstName, lastName, gender, '', company.id, dept[0].id, designation, 
                       isSuperuser, isHod, isDirector)
        # super(EmployeeForm, self).save(*args, **kwargs)
        # - or -
        super(EmployeeForm, self).save(commit=False)
        # updated based on additional comment
        return employee

    except Exception as e:
        traceback.print_exc()
        raise forms.ValidationError('Something went wrong.')
</code></pre>

python django csv