I am trying to write a small application that receives video files, and convert them to a uniform format after they have been uploaded (thus added to the database). I have searched the web for the best solution for this, and have decided to use Django's signals with Celery. But for now I'm trying to create a proof-of-concept to see if it works.
I'm trying to execute a video_repalce()
method after a new video has been uploaded (thus, a new row has been added to database). But the signal doesn't work right, or I didn't understand how the whole system works.
I'm using Django 1.2.3 with pre-defined signal django.db.models.signals.post_init
, which should be called after a model has been instantiated (thus, a new row was added to the database).
from django.core.files.base import File
from django.db.models.signals import post_init
import os
import os.path
import subprocess
class Project(models.Model):
video = models.FileField(upload_to="projects/videos")
def replace_video(self):
"""Replace original video with an updated one."""
# Video conversion process code goes here,
# resulting in a new external video file.
self.video.delete() # Delete the original video.
self.video.save("newfile.webm", File(open("path/to/newfile.webm") ,"wb"))) # Save the new video instead.
self.save() # Commit everything to database.
os.remove("path/to/newfile.webm") # Remove original video copy after it was commited (copied) into the DB.
# ...
# ...
def handle_new_project(sender, **kwargs):
"""Handels some additional tasks for a new added project. i.e. convert video to uniform format."""
project = kwargs['instance']
project.replace_video()
# Call 'Project.replace_video()' every time a new project is added.
post_init.connect(handle_new_project, sender=Project, dispatch_uid="new_project_added")
However, post_init is called not only when a new model instance is created, but also...:
self.pk
is None
!save()
-ing a model. The code above is also executed when I hit self.save()
.Practically, it not working according to the docs.
What am I doing wrong? Remember that this is a proof-of-concept. I intend to move the code to Celery after I see it's working. But, if the signals don't work right, Celery won't help - The signal will always be resent a couple of times whenever I save()
or update a video.
Do you think I shouldn't call save()
inside the replace_video()
method? So where should I call it? Which signal should I choose? post_save
isn't a good option because it's also called whenever I hit save()
.
You seem to have a bit of confusion over what it means to instantiate an object. It has nothing whatever to do with the database. This instantiates a model object without saving it to the database, in which case its pk will be None:
MyObject(field1='foo', field2='bar')
and this (indirectly) instantiates an object by getting it from the database:
MyObject.objects.get(field1='baz')
The post_init
signal will be sent in both of these cases, even though neither of them has anything to do with saving to the database.
If you want something to happen when you save, either override the save
method itself, or use the pre_save
or post_save
signals. You can check there whether or not the object has been previously saved, by verifying if its pk
is None.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With