提问人:Σταύρος Καρακέπελης 提问时间:11/14/2023 更新时间:11/14/2023 访问量:38
Django - 更新数据库条目(如果存在)或插入将两个表组合在一起的新条目(模型)
Django - Update database entry if it exists or insert new entry combining two tables together (models)
问:
我有一个应用程序,可以将两个 excel 文件合并为一个(来自学生的数据和来自他们学科成绩的数据)。因此,一张桌子给学生,一张桌子给成绩。这是我 models.py 的样子:
models.py
class Students(models.Model):
study_program = models.CharField(max_length=40, blank=True, null=True)
registration_number = models.IntegerField(blank=True, null=True)
id_number_1 = models.FloatField(blank=True, null=True)
name = models.CharField(max_length=100, null=True)
surname = models.CharField(max_length=100)
nationality = models.CharField(max_length=10)
.
.
(many more columns here)
.
def __str__(self):
return self.name + ' ' + self.surname
class StudentGrades(models.Model):
student = models.ForeignKey(Students, default=None, on_delete=models.CASCADE)
subject = models.CharField(max_length=40) # Μάθημα (Subject)
subject_code = models.CharField(max_length=20, ) # Κωδ. μαθ. (Subject Code)
student_class = models.CharField(max_length=40, ) # Τμήμα Τάξης (Class)
.
.
(many more columns here)
.
def __str__(self):
return self.subject + ' ' + self.student.name + ' ' + self.student.surname
连接这两者的主键是学生的注册号。每个学生都有一个唯一的注册号。在 views.py 我创建了两个函数(每个表一个),用于将 excel 文件的内容保存到数据库中。以下是 views.py:
views.py
此功能将学生记录保存到数据库中。如果学生所在行的注册号匹配,则会更新记录,否则会将其作为新记录插入。
def update_or_create_student(df):
try:
df = df[0]
except:
return redirect('/dashboard/upload/students')
for i in range(len(df)):
AM = df.iloc[i]['ΑΜ']
if Students.objects.filter(registration_number=AM).exists():
print('updated..')
Students.objects.filter(registration_number=AM).update(
study_program=df.iloc[i]['ΠΣ'],
registration_number=df.iloc[i]['ΑΜ'],
id_number_1=df.iloc[i]['Ακ. Ταυτότητα'],
name=df.iloc[i]['Όνομα'],
surname=df.iloc[i]['Επώνυμο'],
.
.
.
)
else:
print('created..')
Students(
study_program=df.iloc[i]['ΠΣ'],
registration_number=df.iloc[i]['ΑΜ'],
.
.
.
).save()
这个函数现在对学生的成绩做同样的事情。
def updated_or_create_grades(df):
try:
df = df[0]
except:
return redirect('/dashboard/upload/grades')
student_id = None
for i in range(len(df)):
reg_no = df.iloc[i]["AM"]
if Students.objects.filter(registration_number=reg_no).exists():
student_id = Students.objects.get(registration_number=reg_no)
if StudentGrades.objects.filter(registration_number=df.iloc[i]["AM"]).exists():
print('updated..')
StudentGrades.objects.filter(student=student_id).update(
subject_code=df.iloc[i]['Κωδ. μαθ.'],
subject_of_academic_year=df.iloc[i]['Μάθημα Ακ. Έτους'],
student_class=df.iloc[i]['Τμήμα Τάξης'],
.
.
.
else:
print('created..')
StudentGrades(
student=student_id,
subject_code=df.iloc[i]['Κωδ. μαθ.'],
subject_of_academic_year=df.iloc[i]['Μάθημα Ακ. Έτους'],
student_class=df.iloc[i]['Τμήμα Τάξης'],
.
.
.
).save()
这就是问题所在。仅当关系为 1:1(一个学生有一个科目/年级)时,这才有效。这是该应用程序的原始功能。但是,我想扩展它并包括许多科目/年级(因此 1:N,每个学生都参加了多个科目)。无需创建第三个模型/表格,因为每个新等级的 excel 文件都具有完全相同的列格式。
我想修改代码,以包含学生参加的所有科目的所有成绩的记录。每个主题都有一个代码,所以我想按注册号和主题代码进行过滤,但我无法在我的函数中实现它。我认为没有必要对第一个函数进行任何修改,只需在updated_or_create_grades函数中进行修改。如果有任何帮助,这是主题代码的表中的列:
subject_code = models.CharField(max_length=20, )
如果我尝试按原样插入它,它只会保留学生的最新记录,因为它会检查他的注册号并更新它,因此会丢失先前科目/年级的记录。例如,如果我上传了 10 个不同的 excel 文件(10 个不同的年级),并且学生参加了所有 10 个,数据库将只保留最新的科目记录并丢弃其余的。
答:
我认为您的代码仅限制了第一个元素的 df。输入 df 可能包含所有等级信息,但您只切片和获取第一个元素?
df = df[0]
评论