我正在处理一个学校管理项目,想要上传一个 CSV 文件并通过覆盖当前数据或在数据库中更新它来保存它。但它没有被添加到数据库中。另外,我喜欢添加更多字段,所以如果可能的话,使用动态(即通过循环),所以我以后不必更改它。 models.py
class Student(models.Model):
registration_number = models.CharField(max_length=200, unique=True)
firstname = models.CharField(max_length=200)
surname = models.CharField(max_length=200)
date_of_birth = models.DateField(default=timezone.now)
current_class = models.ForeignKey(StudentClass, on_delete=models.SET_NULL, blank=True, null=True)
date_of_admission = models.DateField(default=timezone.now)
parent_mobile_number = models.CharField(max_length=15)
address = models.TextField()
class StudentBulkUpload(models.Model):
date_uploaded = models.DateTimeField(auto_now=True)
csv_file = models.FileField(upload_to='students/bulkupload/')
forms.py
class StudentBulkUploadForm(forms.ModelForm):
class Meta:
model = StudentBulkUpload
fields = ("csv_file",)
views.py
def uploadcsv(request):
if request.method == 'GET':
form = StudentBulkUploadForm()
return render(request, 'students/students_upload.html', {'form':form})
# If not GET method then proceed
try:
form = StudentBulkUploadForm(data=request.POST, files=request.FILES)
if form.is_valid():
csv_file = form.cleaned_data['csv_file']
if not csv_file.name.endswith('.csv'):
messages.error(request, 'File is not CSV type')
return redirect('students:student-upload')
# If file is too large
if csv_file.multiple_chunks():
messages.error(request, 'Uploaded file is too big (%.2f MB)' %(csv_file.size(1000*1000),))
return redirect('students:student-upload')
file_data = csv_file.read().decode('utf-8')
lines = file_data.split('\n')
# loop over the lines and save them in db. If error, store as string and then display
for line in lines:
fields = line.split(',')
data_dict = {}
print(data_dict)
try:
form = StudentBulkUploadForm(data_dict)
if form.is_valid():
form.save()
else:
logging.getLogger('error_logger').error(form.errors.as_json())
except Exception as e:
logging.getLogger('error_logger').error(form.errors.as_json())
pass
except Exception as e:
logging.getLogger('error_logger').error('Unable to upload file. ' + repr(e))
messages.error(request, 'Unable to upload file. ' + repr(e))
return redirect('students:student-upload')
student_upload.html
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-success" value="Submit">
</form>
最佳答案
是否有必要通过表单传递数据并将其保存到db。否则,您可以简单地创建模型的对象并将字典传递给它并保存。
我认为你应该(简而言之):
StudentBulkUpload()
上传并保存文件Student()
的实例并将字典传递给它并保存 StudentClass()
获取对象使用 get()
相应地与存储在 csv 中的值 您可以通过两种方式保存学生详细信息,我认为:
new_student = Student()
new_student.registration_number = fields[0]
new_student.firstname = fields[1]
# like so for other fields
new_student.save()
# create a dictionary `new_student_details` containing values of a student
new_student = Student()
new_student.__dict__.update(new_student_details)
new_student.save()
创建一个函数来读取 csv 文件并保存学生详细信息
import csv
def save_new_students_from_csv(file_path):
# do try catch accordingly
# open csv file, read lines
with open(file_path, 'r') as fp:
students = csv.reader(fp, delimiter=',')
row = 0
for student in students:
if row==0:
headers = student
row = row + 1
else:
# create a dictionary of student details
new_student_details = {}
for i in range(len(headers)):
new_student_details[headers[i]] = student[i]
# for the foreign key field current_class in Student you should get the object first and reassign the value to the key
new_student_details['current_class'] = StudentClass.objects.get() # get the record according to value which is stored in db and csv file
# create an instance of Student model
new_student = Student()
new_student.__dict__.update(new_student_details)
new_student.save()
row = row + 1
fp.close()
您的代码应该如下所示:
def uploadcsv(request):
if request.method == 'GET':
form = StudentBulkUploadForm()
return render(request, 'students/students_upload.html', {'form':form})
# If not GET method then proceed
try:
form = StudentBulkUploadForm(data=request.POST, files=request.FILES)
if form.is_valid():
csv_file = form.cleaned_data['csv_file']
if not csv_file.name.endswith('.csv'):
messages.error(request, 'File is not CSV type')
return redirect('students:student-upload')
# If file is too large
if csv_file.multiple_chunks():
messages.error(request, 'Uploaded file is too big (%.2f MB)' %(csv_file.size(1000*1000),))
return redirect('students:student-upload')
# save and upload file
form.save()
# get the path of the file saved in the server
file_path = os.path.join(BASE_DIR, form.csv_file.url)
# a function to read the file contents and save the student details
save_new_students_from_csv(file_path)
# do try catch if necessary
except Exception as e:
logging.getLogger('error_logger').error('Unable to upload file. ' + repr(e))
messages.error(request, 'Unable to upload file. ' + repr(e))
return redirect('students:student-upload')
注意: csv 文件需要遵循正确的格式。您可以保存 Student()
反正你喜欢。无论如何,文件需要上传和阅读。逐行Student()
必须得救。这只是一个结构。随意进行必要的更改,因为我已经删除了您的大部分代码
关于python - 使用表单上传csv文件django,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62912039/