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 Employee
with a OneToOneField
to Django's Auth
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.
My Model class is:
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)
This is my Admin class:
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
This is my Form class:
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.')
The CreateEmployee
method is defined as:
@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
I am getting an exception in the form's except block with the error: IntegrityError: (1048, "Column 'user_id' cannot be null")
In the traceback, I can see that the exception is being raised in the super(EmployeeForm, self).save(*args, **kwargs)
line. I am assuming the super method is trying to save an instance.
The complete traceback is:
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")
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.
What am I doing wrong here? Is there an alternative way to achieve what I want?
TIA.
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:
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.')
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.