Django 模型在保存循环中生成数百个文件
Django model generates hundreds of files in a saving loop
我在 Ubuntu 18.04 上使用 Django 3.8.2,我在保存 Django 模型时生成了一个 PDF 文件,但是文件是无限循环生成的。
我有这个 django 模型:
class Fattura(models.Model):
ordine = models.ForeignKey(Ordine, on_delete=models.CASCADE, related_name="fatture", null=False)
pdf = models.FileField(upload_to='archivio/fatture/%Y/%m')
pdf
字段是在保存实例时根据相关“ordine”字段中包含的信息生成的,该字段是另一个模型的外键:
class Ordine(models.Model):
utente = models.ForeignKey(User, on_delete=models.CASCADE, related_name="ordini", null=False)
data = models.DateField(auto_now_add=True)
abbonamento = models.ForeignKey(Abbonamento, on_delete=models.PROTECT, null=False)
importo = models.DecimalField(max_digits = 5, decimal_places = 2, null=False)
我在 Fattura 模型的 save()
方法中声明了生成 PDF 的所有指令。我正在使用 Django 文档推荐的库:reportlab。这是自定义保存方法:
def save(self, *args, **kwargs):
self.count_save += 1 # I defined this attribute which I increment to understand what is actually looping
print("COUNT SAVE: " + str(self.count_save)) # it always grows, that's the save method being re-called
if self.pdf._file == None:
try:
buffer = io.BytesIO()
p = canvas.Canvas(buffer)
p.drawString(100,100, str(self.ordine))
p.showPage()
p.save()
buffer.seek(0)
utente = self.ordine.utente
num_questa_fattura = utente.ordini.count()
nome_file = "{}_{}-{}.pdf".format(
self.ordine.utente.first_name.lower(),
self.ordine.utente.last_name.lower(),
num_questa_fattura)
percorso = '{}/upload/archivio/fatture/{}/{}/{}'.format(
BASE_DIR, # from settings.py
self.ordine.data.year,
self.ordine.data.month,
nome_file)
file_temporaneo = NamedTemporaryFile(delete=True)
file_temporaneo.write(buffer.getbuffer())
file_temporaneo.flush()
temp_file = File(file_temporaneo, name = nome_file)
print(nome_file)
print(file_temporaneo)
print("--------------------- SAVE")
self.pdf.save(nome_file, file_temporaneo, save=True) # saving the field (EDIT: this was the problem, setting save to True resaves the whole model object, and it was creating an infinite loop)
file_temporaneo.close()
except:
raise ValidationError("Invoice could not be saved")
super().save(*args, **kwargs) # saving the object to the database
当我使用 Django 管理面板保存 Fattura 对象时,在我声明的文件夹内循环生成数百个 PDF 文件,但没有真正完成数据库保存。之后没有可用的 Django 模型对象,因此最终没有任何内容保存到数据库中,每次生成恰好 499 个文件。
我不确定是什么导致了这个循环,也许是 try
语句中的 pdf 字段保存方法?还是最后的super().save(*args, **kwargs)
?不过我无法删除它,否则如果 PDF 文件实际上与一个实例关联并且我正在更新另一个字段,则不会保存任何内容 ordine
这是我的日志的摘录
[Tue Nov 02 15:25:06.974768 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] COUNT SAVE: 262
[Tue Nov 02 15:25:07.010584 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] maria_rosselli-1.pdf
[Tue Nov 02 15:25:07.015778 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] <tempfile._TemporaryFileWrapper object at 0x7f7b07ac0390>
[Tue Nov 02 15:25:07.020944 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] --------------------- SAVE
[Tue Nov 02 15:25:07.124451 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] COUNT SAVE: 263
[Tue Nov 02 15:25:07.164934 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] maria_rosselli-1.pdf
[Tue Nov 02 15:25:07.170144 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] <tempfile._TemporaryFileWrapper object at 0x7f7b07ac0e48>
[Tue Nov 02 15:25:07.175250 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] --------------------- SAVE
[Tue Nov 02 15:25:07.253426 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] COUNT SAVE: 264
[Tue Nov 02 15:25:07.286589 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] maria_rosselli-1.pdf
[Tue Nov 02 15:25:07.291734 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] <tempfile._TemporaryFileWrapper object at 0x7f7b07ac0e10>
[Tue Nov 02 15:25:07.296894 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] --------------------- SAVE
保存pdf时需要设置save为False才能再次调用模型实例save方法:
self.pdf.save(nome_file, file_temporaneo, save=False)
我在 Ubuntu 18.04 上使用 Django 3.8.2,我在保存 Django 模型时生成了一个 PDF 文件,但是文件是无限循环生成的。
我有这个 django 模型:
class Fattura(models.Model):
ordine = models.ForeignKey(Ordine, on_delete=models.CASCADE, related_name="fatture", null=False)
pdf = models.FileField(upload_to='archivio/fatture/%Y/%m')
pdf
字段是在保存实例时根据相关“ordine”字段中包含的信息生成的,该字段是另一个模型的外键:
class Ordine(models.Model):
utente = models.ForeignKey(User, on_delete=models.CASCADE, related_name="ordini", null=False)
data = models.DateField(auto_now_add=True)
abbonamento = models.ForeignKey(Abbonamento, on_delete=models.PROTECT, null=False)
importo = models.DecimalField(max_digits = 5, decimal_places = 2, null=False)
我在 Fattura 模型的 save()
方法中声明了生成 PDF 的所有指令。我正在使用 Django 文档推荐的库:reportlab。这是自定义保存方法:
def save(self, *args, **kwargs):
self.count_save += 1 # I defined this attribute which I increment to understand what is actually looping
print("COUNT SAVE: " + str(self.count_save)) # it always grows, that's the save method being re-called
if self.pdf._file == None:
try:
buffer = io.BytesIO()
p = canvas.Canvas(buffer)
p.drawString(100,100, str(self.ordine))
p.showPage()
p.save()
buffer.seek(0)
utente = self.ordine.utente
num_questa_fattura = utente.ordini.count()
nome_file = "{}_{}-{}.pdf".format(
self.ordine.utente.first_name.lower(),
self.ordine.utente.last_name.lower(),
num_questa_fattura)
percorso = '{}/upload/archivio/fatture/{}/{}/{}'.format(
BASE_DIR, # from settings.py
self.ordine.data.year,
self.ordine.data.month,
nome_file)
file_temporaneo = NamedTemporaryFile(delete=True)
file_temporaneo.write(buffer.getbuffer())
file_temporaneo.flush()
temp_file = File(file_temporaneo, name = nome_file)
print(nome_file)
print(file_temporaneo)
print("--------------------- SAVE")
self.pdf.save(nome_file, file_temporaneo, save=True) # saving the field (EDIT: this was the problem, setting save to True resaves the whole model object, and it was creating an infinite loop)
file_temporaneo.close()
except:
raise ValidationError("Invoice could not be saved")
super().save(*args, **kwargs) # saving the object to the database
当我使用 Django 管理面板保存 Fattura 对象时,在我声明的文件夹内循环生成数百个 PDF 文件,但没有真正完成数据库保存。之后没有可用的 Django 模型对象,因此最终没有任何内容保存到数据库中,每次生成恰好 499 个文件。
我不确定是什么导致了这个循环,也许是 try
语句中的 pdf 字段保存方法?还是最后的super().save(*args, **kwargs)
?不过我无法删除它,否则如果 PDF 文件实际上与一个实例关联并且我正在更新另一个字段,则不会保存任何内容 ordine
这是我的日志的摘录
[Tue Nov 02 15:25:06.974768 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] COUNT SAVE: 262
[Tue Nov 02 15:25:07.010584 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] maria_rosselli-1.pdf
[Tue Nov 02 15:25:07.015778 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] <tempfile._TemporaryFileWrapper object at 0x7f7b07ac0390>
[Tue Nov 02 15:25:07.020944 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] --------------------- SAVE
[Tue Nov 02 15:25:07.124451 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] COUNT SAVE: 263
[Tue Nov 02 15:25:07.164934 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] maria_rosselli-1.pdf
[Tue Nov 02 15:25:07.170144 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] <tempfile._TemporaryFileWrapper object at 0x7f7b07ac0e48>
[Tue Nov 02 15:25:07.175250 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] --------------------- SAVE
[Tue Nov 02 15:25:07.253426 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] COUNT SAVE: 264
[Tue Nov 02 15:25:07.286589 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] maria_rosselli-1.pdf
[Tue Nov 02 15:25:07.291734 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] <tempfile._TemporaryFileWrapper object at 0x7f7b07ac0e10>
[Tue Nov 02 15:25:07.296894 2021] [wsgi:error] [pid 10050] [remote 95.x.x.x:36048] --------------------- SAVE
保存pdf时需要设置save为False才能再次调用模型实例save方法:
self.pdf.save(nome_file, file_temporaneo, save=False)