简体   繁体   English

管理员中通过CSV批量导入Django完整性错误

[英]Django Integrity Error in Bulk Import via CSV in Admin

I am trying to implement a CSV Import in Django Admin and save bulk data corresponding to the CSV file's rows. 我正在尝试在Django Admin中实现CSV导入并保存与CSV文件行对应的批量数据。 I have a model Employee with a OneToOneField to Django's Auth model. 我有一个带有OneToOneField的模型Employee到Django的Auth模型。 I have written a custom Form that accepts a csv file. 我写了一个接受csv文件的自定义表单。 However, when I call the super().save() method, I get an Integrity Error. 但是,当我调用super()。save()方法时,我得到了一个完整性错误。

My Model class is: 我的Model类是:

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: 这是我的Admin类:

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: 这是我的Form类:

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: CreateEmployee方法定义为:

@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") 我在表单的例外情况下得到一个异常,其中包含错误: 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. 在回溯中,我可以看到异常是在super(EmployeeForm, self).save(*args, **kwargs)行中引发的。 I am assuming the super method is trying to save an instance. 我假设super方法正在尝试保存实例。

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. 我猜测ModelForm的save方法正在尝试保存实例,但我不希望这种情况发生,因为我创建了多个用户。

What am I doing wrong here? 我在这做错了什么? Is there an alternative way to achieve what I want? 有没有其他方法来实现我想要的?

TIA. TIA。

Since you're doing your own save, you don't need to call save on the Super form. 由于您正在进行自己的保存,因此无需在超级表单上调用save。 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: 通常,当您需要像这样填写外键字段时,使用commit = False来获取未保存模型的实例。但您可以执行以下任一操作:

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.')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM