Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-formsdjango-excel

Saving many-to-many fields from the excel file in Django


I'm trying to save the student data from an excel file. I'm reading the excel file row-wise and mapping the data to the model fields. Now the problem is that there is a foreign key and a many-to-many field which I don't know how to save. Though I figured out the foreign key part but not able to solve the second part. Here are the files.

views.py

def fileUpload(request):
    if request.method=="POST":
        form= UserDataUploadView(request.POST, request.FILES)
        try:
            excel_file= request.FILES["excel_file"]
        except MultiValueDictKeyError: # In case the user uploads nothing
            return redirect('failure_page')
        # Checking the extension of the file
        if str(excel_file).endswith('.xls'):
            data=  xls_get(excel_file, column_limit=10)
        elif str(excel_file).endswith('.xlsx'):
            data=  xlsx_get(excel_file, column_limit=10)
        else:
            return redirect('failure_page')
        studentData= data["Sheet1"]
        print("Real Data", studentData)

        # reading the sheet row-wise
        a_list= studentData
        list_iterator= iter(a_list)
        next(list_iterator)
        for detail in list_iterator:
            # To find out empty cells
            for data in detail:
                if data==" ":
                    print('A field is empty')
                    return redirect('user_upload')
            print("DATA:  ", detail)
            user=User.objects.create(
                firstName    =   detail[6],
                lastName     =   detail[7],
                password     =   detail[8],
                username     =   detail[9],
            )
            # instance=user.save(commit=false)
            # Student.batch.add(detail[0])
            student=Student.objects.create(
                user         =   user,
                email        =   detail[1],
                rs_id        =   detail[2],
                dob          =   detail[3],
                address      =   detail[4],
                age          =   detail[5],
                )
            student.save()
        return render(request, 'classroom/admin/success_page.html', {'excel_data':studentData})
        # iterating over the rows and
            # getting value from each cell in row
        #     for row in worksheet.iter_rows():
        #         row_data= list()
        #         for cell in row:
        #             row_data.append(str(cell.value))
        #         excel_data.append(row_data)
        # return render(request, 'classroom/admin/excel.html', {'excel_data':excel_data})

    else:
        form=UserDataUploadView()

    return render(request, 'classroom/admin/fill_users.html', {
        'form':form,
        # 'excel_data':excel_data,
        })

models.py

class Subject(models.Model):
    school = models.CharField(max_length=50, null=True)
    name = models.CharField(max_length=30)
    color = models.CharField(max_length=7, default='#007bff')

    def __str__(self):
        return self.name

    def get_html_badge(self):
        name = escape(self.name)
        color = escape(self.color)
        html = '<span class="badge badge-primary" style="background-color: %s">%s</span>' % (color, name)
        return mark_safe(html)

class Batch(models.Model):
    name = models.CharField(max_length=30, unique=True)
    school = models.CharField(max_length=50)
    amount_of_fees = models.IntegerField(null=True)
    subjects = models.ManyToManyField(Subject)

    @property
    def students(self):
        return self.student_set.all()

    def __str__(self):
        return self.name

class Student(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, default=None)
    batch = models.ManyToManyField(Batch)
    email = models.EmailField(null=True)
    phone_number = models.CharField(max_length=10, null=True)
    dob = models.DateField(blank=True, null=True, help_text="Enter in the following format : YYYY-MM-DD")
    address = models.TextField(max_length=150, null=True)
    age = models.IntegerField(blank=True)
    image = models.ImageField(upload_to='profile_pictures', default='student_image.png', blank=True)

    rs_id = models.IntegerField(blank=True,default=0)

I don't know how to put the data for batch in the excel sheet. Kindly give insight for that too.


Solution

  • Assuming detail[0] is the name field for the Batch model, you would do:

         student_batch = Batch.objects.get(name=detail[0])    
         student=Student.objects.create(
                        user         =   user,
                        email        =   detail[1],
                        rs_id        =   detail[2],
                        dob          =   detail[3],
                        address      =   detail[4],
                        age          =   detail[5],
                        )
        student.batch.add(student_batch)
        student.save()
    

    You will also need to update your Batch field on the Student model to:

    batch = models.ManyToManyField(Batch, blank=True)