So, I've got my django app, rabbitmq and celery working and processing
my uploaded files. Next step is to get the client to display status
results provided by JSON, ultimately refreshing to a results page when
complete.
I'm a little new to JSON / AJAX (AJAJ!) and I'm struggling a little
with the templates and views part.
Are there any easy examples out there?
I can't seem to find any!
Many thanks in advance for any suggestions.
Cheers
W
Hi All,
So, I've got my django app, rabbitmq and celery working and processing
my uploaded files. Next step is to get the client to display status
results provided by JSON, ultimately refreshing to a results page when
complete.
I'm a little new to JSON / AJAX (AJAJ!) and I'm struggling a little
with the templates and views part.
Are there any easy examples out there?
I'm using a message queue because the task is really "offline" and
could take 1sec or 30 seconds (or longer).
I'll look at b-list. Thankyou
W
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To post to this group, send email to django...@googlegroups.com.
> To unsubscribe from this group, send email to
> django-users...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/django-users?hl=en.
>
Sure. I have a TV recording system built using Django (the UI is web
based), which records TV shows to disk in MPEG2 format. I then use the
whole celery stack to convert those video files into something that I
can then load up onto my ipad/iphone.
The transcoding is initiated by a user clicking an icon on the episode
page, which triggers an AJAX call, which eventually calls this
function:
def setup_transcode_episode(episode):
data = { 'valid': False, }
if episode.media:
file = unicode(episode.media)
rv = transcode_episode_for_ipad.delay(file=file, episode_id=episode.id)
tm, created = TaskMeta.objects.get_or_create(task_id=rv.task_id)
episode.ipad_media = tm
episode.save()
data['task_id'] = rv.task_id
data['valid'] = True
return data
The data dictionary is returned back to the client, which now
periodically polls a view for status, using the task_id.
The task that is invoked, transcode_episode_for_ipad, looks like this:
@task
def transcode_episode_for_ipad(file, episode_id, **kwargs):
args = make_ipad_encoder_args(file=file)
out = args[-1]
ffmpeg = FFmpegProgressMonitor(file=file, task_id=kwargs['task_id'],
args=args)
rv = ffmpeg.process()
episode = TVEpisode.objects.get(id=episode_id)
dir, fn = out.rsplit('/', 1)
imedia = MplayerFileMedia.objects.create(directory=dir, file=fn)
episode.ipad_media = imedia
episode.save()
return rv
This is pretty straight-forward, I simply produce the arguments for
ffmpeg, and then process it, monitoring the output of the ffmpeg to
give me hints about how long through the transcoding process we are,
which I then store in memcache, to avoid requiring a database hit to
find out the status of the task.
This is easier than it sounds, every <n> frames, ffmpeg prints out a
line indicating how far through the file it is. Just monitor the
output and update the cache as appropriate.
The way my models are set up, TVEpisode.ipad_media is a generic
foreign key, so while transcoding is taking place it points at the
TaskMeta object, which contains the task id. This allows us to know
that the task is underway in the background, even if we didn't
initiate it ourselfs, and use that information to poll for status etc
as appropriate.
Cheers
Tom
I think this seems to be exactly what I was looking for...
Can I ask for JS code that does the periodic polling from the client
please and possibly the appropriate bits of the template?
Many thanks!
W
Sure. In the main page view, I check to see whether I have transcoded
or started transcoding the episode, and set context variables as
appropriate:
if episode.ipad_media:
if hasattr(episode.ipad_media, 'task_id'):
from transcoding.utils import get_task_progress
data['ipad_media_class'] = 'transcoding'
data['ipad_media_progress'] = (episode.ipad_media.task_id,
get_task_progress(episode.ipad_media.task_id))
else:
data['ipad_media_class'] = 'good'
else:
data['ipad_media_class'] = 'bad'
This is rendered into a widget on the page:
{% if episode.media %}
<div class='pushbutton'>
<div class='button play'>Play episode</div>
<div class='button ipad_{{ ipad_media_class }} {{ ipad_media_class }}'>
{% if ipad_media_progress %}
Transcoding to ipad
<div class='pct' id='{{ ipad_media_progress.0 }}'>{{
ipad_media_progress.1 }} %</div>
{% else %}
Transcode to ipad
{% endif %}
</div>
</div>
{% endif %}
Then, during page load, I configure an observer to update each
progress widget (I use the prototype JS framework):
$$('div.pct').each(function(ctl) {
new Ajax.PeriodicalUpdater(ctl, '{% url transcode_task_status_ajax %}', {
method: 'get',
asynchronous: true,
frequency: 3,
decay: 2,
parameters: { task_id: ctl.id }
});
});
That view is trivial, since it just updates the appropriate div with
the current percentage:
def transcode_task_status_ajax(request):
from transcoding.utils import get_task_progress
task_id = request.GET.get('task_id')
return HttpResponse(u'%s %%' % get_task_progress(task_id))
Cheers
Tom
This is good stuff.
W