Using m2m_changed signal [duplicate]
-
01-07-2021 - |
Question
first some information about the app: I want to be able to upload a pdf file, that pdf file will be converted to images (for every pdf page one image). These images will then be shown on the website and the pdf can be downloaded: So far I have this:
def upload_to(path):
def upload_callback(instance, filename):
return '%s' % os.path.join(settings.MEDIA_ROOT, path, str(instance), filename)
return upload_callback
class Document(models.Model):
name = models.TextField()
pdf_file = models.FileField(upload_to=upload_to('pdfs'))
images = models.ManyToManyField('Image', null=True, blank=True)
class Image(models.Model):
image = models.ImageField(upload_to='pdfimages')
Now to create the images and the image objects i overwrote the save function of the Document class: I looks like this:
def save(self, *args, **kwargs):
path = os.path.join(settings.MEDIA_ROOT, 'pdfs', self.name)
imagepath = os.path.join(settings.MEDIA_ROOT, 'pdfimages')
if os.path.exists(path):
for file_ in os.listdir(path):
if file_ == self.pdf_file.name:
continue
super(Document, self).save(*args, **kwargs)
save_to = os.path.join(path, os.path.splitext(self.pdf_file.name)[0] +
'_page.png')
pdffile = os.path.join(path, self.pdf_file.name)
args = ['convert', '-density', '100', '-depth',
'8', '-quality', '85', pdffile, save_to ]
subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
for file_ in os.listdir(path):
if file_.endswith('png'):
try:
shutil.move((os.path.join(settings.MEDIA_ROOT,
'pdfs', self.name, file_)),
imagepath)
except Exception:
pass
for file_ in os.listdir(imagepath):
i, created = Image.objects.get_or_create(image="pdfimages/%s" % file_)
First that code isn't very nice and second the most important action is still missing. Adding the image to the document meaning updating the m2m relation. Now I have two questions:
- Can I write above code nicer? (mostly don't like the
super(Document, self).save(*args, **kwargs) in the middle of the code.
- For the m2m update I looked at m2m_changed signal but I honestly don't understand how to use it.
EDIT:
It's actually quite easy once you understand the parametere, thanks
Solution
check this post on usage of m2m signal.
You can move all your post save processing logic to the signal