Commit a66d2ec82e14c37308c7b92e67664eb0a1a66906
1 parent
a85b2dec
Exists in
master
and in
3 other branches
Adding youtube video log
Showing
5 changed files
with
222 additions
and
10 deletions
Show diff stats
amadeus/static/js/ytvideo.js
| @@ -20,17 +20,22 @@ function onPlayerStateChange(event) { | @@ -20,17 +20,22 @@ function onPlayerStateChange(event) { | ||
| 20 | break; | 20 | break; |
| 21 | case YT.PlayerState.ENDED: | 21 | case YT.PlayerState.ENDED: |
| 22 | clearInterval(keepAlive) | 22 | clearInterval(keepAlive) |
| 23 | - console.log('ended'); | 23 | + |
| 24 | + watchLog("close"); | ||
| 25 | + | ||
| 26 | + finishLog(); | ||
| 24 | break; | 27 | break; |
| 25 | case YT.PlayerState.PLAYING: | 28 | case YT.PlayerState.PLAYING: |
| 26 | keepAlive = setInterval(function () { | 29 | keepAlive = setInterval(function () { |
| 27 | keepLogged() | 30 | keepLogged() |
| 28 | }, 60000); | 31 | }, 60000); |
| 29 | - console.log('playing'); | 32 | + |
| 33 | + watchLog("open"); | ||
| 30 | break; | 34 | break; |
| 31 | case YT.PlayerState.PAUSED: | 35 | case YT.PlayerState.PAUSED: |
| 32 | clearInterval(keepAlive) | 36 | clearInterval(keepAlive) |
| 33 | - console.log('paused'); | 37 | + |
| 38 | + watchLog("close"); | ||
| 34 | break; | 39 | break; |
| 35 | case YT.PlayerState.BUFFERING: | 40 | case YT.PlayerState.BUFFERING: |
| 36 | console.log('buffering'); | 41 | console.log('buffering'); |
| @@ -41,6 +46,40 @@ function onPlayerStateChange(event) { | @@ -41,6 +46,40 @@ function onPlayerStateChange(event) { | ||
| 41 | } | 46 | } |
| 42 | } | 47 | } |
| 43 | 48 | ||
| 44 | -function keepLogged() { | 49 | +function keepLogged () { |
| 45 | $(document).mousemove(); | 50 | $(document).mousemove(); |
| 51 | +} | ||
| 52 | + | ||
| 53 | +function watchLog (action) { | ||
| 54 | + var url = $('#log_url').val(); | ||
| 55 | + var log_input = $('#log_id'); | ||
| 56 | + | ||
| 57 | + $.ajax({ | ||
| 58 | + url: url, | ||
| 59 | + data: {'action': action, 'log_id': log_input.val()}, | ||
| 60 | + dataType: 'json', | ||
| 61 | + success: function (data) { | ||
| 62 | + if (action == "open") { | ||
| 63 | + log_input.val(data.log_id); | ||
| 64 | + } | ||
| 65 | + }, | ||
| 66 | + error: function (data) { | ||
| 67 | + console.log(data); | ||
| 68 | + } | ||
| 69 | + }); | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +function finishLog () { | ||
| 73 | + var url = $('#log_finish_url').val(); | ||
| 74 | + | ||
| 75 | + $.ajax({ | ||
| 76 | + url: url, | ||
| 77 | + dataType: 'json', | ||
| 78 | + success: function (data) { | ||
| 79 | + console.log(data); | ||
| 80 | + }, | ||
| 81 | + error: function (data) { | ||
| 82 | + console.log(data); | ||
| 83 | + } | ||
| 84 | + }); | ||
| 46 | } | 85 | } |
| 47 | \ No newline at end of file | 86 | \ No newline at end of file |
youtube_video/templates/youtube/view.html
| @@ -47,6 +47,9 @@ | @@ -47,6 +47,9 @@ | ||
| 47 | </div> | 47 | </div> |
| 48 | </div> | 48 | </div> |
| 49 | <div id="{{subject.slug}}" class="panel-collapse in collapse category-panel-content" style="padding: 0px; overflow: hidden;"> | 49 | <div id="{{subject.slug}}" class="panel-collapse in collapse category-panel-content" style="padding: 0px; overflow: hidden;"> |
| 50 | + <input type="hidden" id="log_finish_url" value="{% url 'youtube:finish' youtube.slug %}" /> | ||
| 51 | + <input type="hidden" id="log_url" value="{% url 'youtube:watch' youtube.slug %}" /> | ||
| 52 | + <input type="hidden" id="log_id" value="" /> | ||
| 50 | <iframe src="{{ youtube.url }}?enablejsapi=1" frameborder="0" allowfullscreen id="video"></iframe> | 53 | <iframe src="{{ youtube.url }}?enablejsapi=1" frameborder="0" allowfullscreen id="video"></iframe> |
| 51 | </div> | 54 | </div> |
| 52 | </div> | 55 | </div> |
youtube_video/templates/youtube/window_view.html
| @@ -20,6 +20,9 @@ | @@ -20,6 +20,9 @@ | ||
| 20 | </style> | 20 | </style> |
| 21 | </head> | 21 | </head> |
| 22 | <body> | 22 | <body> |
| 23 | + <input type="hidden" id="log_finish_url" value="{% url 'youtube:finish' youtube.slug %}" /> | ||
| 24 | + <input type="hidden" id="log_url" value="{% url 'youtube:watch' youtube.slug %}" /> | ||
| 25 | + <input type="hidden" id="log_id" value="" /> | ||
| 23 | <iframe src="{{ youtube.url }}?enablejsapi=1" frameborder="0" allowfullscreen id="video"></iframe> | 26 | <iframe src="{{ youtube.url }}?enablejsapi=1" frameborder="0" allowfullscreen id="video"></iframe> |
| 24 | 27 | ||
| 25 | <script type="text/javascript" src="{% static 'js/ytvideo.js' %}"></script> | 28 | <script type="text/javascript" src="{% static 'js/ytvideo.js' %}"></script> |
youtube_video/urls.py
| @@ -9,4 +9,6 @@ urlpatterns = [ | @@ -9,4 +9,6 @@ urlpatterns = [ | ||
| 9 | url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteView.as_view(), name = 'delete'), | 9 | url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteView.as_view(), name = 'delete'), |
| 10 | url(r'^window_view/(?P<slug>[\w_-]+)/$', views.NewWindowView.as_view(), name = 'window_view'), | 10 | url(r'^window_view/(?P<slug>[\w_-]+)/$', views.NewWindowView.as_view(), name = 'window_view'), |
| 11 | url(r'^view/(?P<slug>[\w_-]+)/$', views.InsideView.as_view(), name = 'view'), | 11 | url(r'^view/(?P<slug>[\w_-]+)/$', views.InsideView.as_view(), name = 'view'), |
| 12 | + url(r'^watch/(?P<ytvideo>[\w_-]+)/$', views.ytvideo_watch_log, name = 'watch'), | ||
| 13 | + url(r'^finish/(?P<ytvideo>[\w_-]+)/$', views.ytvideo_finish_log, name = 'finish'), | ||
| 12 | ] | 14 | ] |
youtube_video/views.py
| 1 | from django.shortcuts import get_object_or_404, redirect, render | 1 | from django.shortcuts import get_object_or_404, redirect, render |
| 2 | from django.views import generic | 2 | from django.views import generic |
| 3 | from django.contrib import messages | 3 | from django.contrib import messages |
| 4 | +from django.http import JsonResponse | ||
| 4 | from django.core.urlresolvers import reverse, reverse_lazy | 5 | from django.core.urlresolvers import reverse, reverse_lazy |
| 5 | from django.utils.translation import ugettext_lazy as _ | 6 | from django.utils.translation import ugettext_lazy as _ |
| 6 | from django.contrib.auth.mixins import LoginRequiredMixin | 7 | from django.contrib.auth.mixins import LoginRequiredMixin |
| 7 | 8 | ||
| 8 | from amadeus.permissions import has_subject_permissions, has_resource_permissions | 9 | from amadeus.permissions import has_subject_permissions, has_resource_permissions |
| 9 | 10 | ||
| 11 | +import time | ||
| 12 | +from log.models import Log | ||
| 13 | +from log.mixins import LogMixin | ||
| 14 | +from log.decorators import log_decorator_ajax, log_decorator | ||
| 15 | + | ||
| 10 | from topics.models import Topic | 16 | from topics.models import Topic |
| 11 | 17 | ||
| 12 | from .forms import YTVideoForm, InlinePendenciesFormset | 18 | from .forms import YTVideoForm, InlinePendenciesFormset |
| 13 | from .models import YTVideo | 19 | from .models import YTVideo |
| 14 | 20 | ||
| 15 | -class NewWindowView(LoginRequiredMixin, generic.DetailView): | 21 | +class NewWindowView(LoginRequiredMixin, LogMixin, generic.DetailView): |
| 22 | + log_component = 'resources' | ||
| 23 | + log_action = 'view' | ||
| 24 | + log_resource = 'ytvideo' | ||
| 25 | + log_context = {} | ||
| 26 | + | ||
| 16 | login_url = reverse_lazy("users:login") | 27 | login_url = reverse_lazy("users:login") |
| 17 | redirect_field_name = 'next' | 28 | redirect_field_name = 'next' |
| 18 | 29 | ||
| @@ -34,9 +45,32 @@ class NewWindowView(LoginRequiredMixin, generic.DetailView): | @@ -34,9 +45,32 @@ class NewWindowView(LoginRequiredMixin, generic.DetailView): | ||
| 34 | 45 | ||
| 35 | context['title'] = _("%s - Video")%(self.object.name) | 46 | context['title'] = _("%s - Video")%(self.object.name) |
| 36 | 47 | ||
| 48 | + self.log_context['category_id'] = self.object.topic.subject.category.id | ||
| 49 | + self.log_context['category_name'] = self.object.topic.subject.category.name | ||
| 50 | + self.log_context['category_slug'] = self.object.topic.subject.category.slug | ||
| 51 | + self.log_context['subject_id'] = self.object.topic.subject.id | ||
| 52 | + self.log_context['subject_name'] = self.object.topic.subject.name | ||
| 53 | + self.log_context['subject_slug'] = self.object.topic.subject.slug | ||
| 54 | + self.log_context['topic_id'] = self.object.topic.id | ||
| 55 | + self.log_context['topic_name'] = self.object.topic.name | ||
| 56 | + self.log_context['topic_slug'] = self.object.topic.slug | ||
| 57 | + self.log_context['ytvideo_id'] = self.object.id | ||
| 58 | + self.log_context['ytvideo_name'] = self.object.name | ||
| 59 | + self.log_context['ytvideo_slug'] = self.object.slug | ||
| 60 | + self.log_context['timestamp_start'] = str(int(time.time())) | ||
| 61 | + | ||
| 62 | + super(NewWindowView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) | ||
| 63 | + | ||
| 64 | + self.request.session['log_id'] = Log.objects.latest('id').id | ||
| 65 | + | ||
| 37 | return context | 66 | return context |
| 38 | 67 | ||
| 39 | -class InsideView(LoginRequiredMixin, generic.DetailView): | 68 | +class InsideView(LoginRequiredMixin, LogMixin, generic.DetailView): |
| 69 | + log_component = 'resources' | ||
| 70 | + log_action = 'view' | ||
| 71 | + log_resource = 'ytvideo' | ||
| 72 | + log_context = {} | ||
| 73 | + | ||
| 40 | login_url = reverse_lazy("users:login") | 74 | login_url = reverse_lazy("users:login") |
| 41 | redirect_field_name = 'next' | 75 | redirect_field_name = 'next' |
| 42 | 76 | ||
| @@ -61,9 +95,32 @@ class InsideView(LoginRequiredMixin, generic.DetailView): | @@ -61,9 +95,32 @@ class InsideView(LoginRequiredMixin, generic.DetailView): | ||
| 61 | context['topic'] = self.object.topic | 95 | context['topic'] = self.object.topic |
| 62 | context['subject'] = self.object.topic.subject | 96 | context['subject'] = self.object.topic.subject |
| 63 | 97 | ||
| 98 | + self.log_context['category_id'] = self.object.topic.subject.category.id | ||
| 99 | + self.log_context['category_name'] = self.object.topic.subject.category.name | ||
| 100 | + self.log_context['category_slug'] = self.object.topic.subject.category.slug | ||
| 101 | + self.log_context['subject_id'] = self.object.topic.subject.id | ||
| 102 | + self.log_context['subject_name'] = self.object.topic.subject.name | ||
| 103 | + self.log_context['subject_slug'] = self.object.topic.subject.slug | ||
| 104 | + self.log_context['topic_id'] = self.object.topic.id | ||
| 105 | + self.log_context['topic_name'] = self.object.topic.name | ||
| 106 | + self.log_context['topic_slug'] = self.object.topic.slug | ||
| 107 | + self.log_context['ytvideo_id'] = self.object.id | ||
| 108 | + self.log_context['ytvideo_name'] = self.object.name | ||
| 109 | + self.log_context['ytvideo_slug'] = self.object.slug | ||
| 110 | + self.log_context['timestamp_start'] = str(int(time.time())) | ||
| 111 | + | ||
| 112 | + super(InsideView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) | ||
| 113 | + | ||
| 114 | + self.request.session['log_id'] = Log.objects.latest('id').id | ||
| 115 | + | ||
| 64 | return context | 116 | return context |
| 65 | 117 | ||
| 66 | -class CreateView(LoginRequiredMixin, generic.edit.CreateView): | 118 | +class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView): |
| 119 | + log_component = 'resources' | ||
| 120 | + log_action = 'create' | ||
| 121 | + log_resource = 'ytvideo' | ||
| 122 | + log_context = {} | ||
| 123 | + | ||
| 67 | login_url = reverse_lazy("users:login") | 124 | login_url = reverse_lazy("users:login") |
| 68 | redirect_field_name = 'next' | 125 | redirect_field_name = 'next' |
| 69 | 126 | ||
| @@ -146,6 +203,21 @@ class CreateView(LoginRequiredMixin, generic.edit.CreateView): | @@ -146,6 +203,21 @@ class CreateView(LoginRequiredMixin, generic.edit.CreateView): | ||
| 146 | 203 | ||
| 147 | if not pend_form.action == "": | 204 | if not pend_form.action == "": |
| 148 | pend_form.save() | 205 | pend_form.save() |
| 206 | + | ||
| 207 | + self.log_context['category_id'] = self.object.topic.subject.category.id | ||
| 208 | + self.log_context['category_name'] = self.object.topic.subject.category.name | ||
| 209 | + self.log_context['category_slug'] = self.object.topic.subject.category.slug | ||
| 210 | + self.log_context['subject_id'] = self.object.topic.subject.id | ||
| 211 | + self.log_context['subject_name'] = self.object.topic.subject.name | ||
| 212 | + self.log_context['subject_slug'] = self.object.topic.subject.slug | ||
| 213 | + self.log_context['topic_id'] = self.object.topic.id | ||
| 214 | + self.log_context['topic_name'] = self.object.topic.name | ||
| 215 | + self.log_context['topic_slug'] = self.object.topic.slug | ||
| 216 | + self.log_context['ytvideo_id'] = self.object.id | ||
| 217 | + self.log_context['ytvideo_name'] = self.object.name | ||
| 218 | + self.log_context['ytvideo_slug'] = self.object.slug | ||
| 219 | + | ||
| 220 | + super(CreateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) | ||
| 149 | 221 | ||
| 150 | return redirect(self.get_success_url()) | 222 | return redirect(self.get_success_url()) |
| 151 | 223 | ||
| @@ -176,7 +248,12 @@ class CreateView(LoginRequiredMixin, generic.edit.CreateView): | @@ -176,7 +248,12 @@ class CreateView(LoginRequiredMixin, generic.edit.CreateView): | ||
| 176 | 248 | ||
| 177 | return success_url | 249 | return success_url |
| 178 | 250 | ||
| 179 | -class UpdateView(LoginRequiredMixin, generic.UpdateView): | 251 | +class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView): |
| 252 | + log_component = 'resources' | ||
| 253 | + log_action = 'update' | ||
| 254 | + log_resource = 'ytvideo' | ||
| 255 | + log_context = {} | ||
| 256 | + | ||
| 180 | login_url = reverse_lazy("users:login") | 257 | login_url = reverse_lazy("users:login") |
| 181 | redirect_field_name = 'next' | 258 | redirect_field_name = 'next' |
| 182 | 259 | ||
| @@ -245,6 +322,21 @@ class UpdateView(LoginRequiredMixin, generic.UpdateView): | @@ -245,6 +322,21 @@ class UpdateView(LoginRequiredMixin, generic.UpdateView): | ||
| 245 | 322 | ||
| 246 | if not pend_form.action == "": | 323 | if not pend_form.action == "": |
| 247 | pend_form.save() | 324 | pend_form.save() |
| 325 | + | ||
| 326 | + self.log_context['category_id'] = self.object.topic.subject.category.id | ||
| 327 | + self.log_context['category_name'] = self.object.topic.subject.category.name | ||
| 328 | + self.log_context['category_slug'] = self.object.topic.subject.category.slug | ||
| 329 | + self.log_context['subject_id'] = self.object.topic.subject.id | ||
| 330 | + self.log_context['subject_name'] = self.object.topic.subject.name | ||
| 331 | + self.log_context['subject_slug'] = self.object.topic.subject.slug | ||
| 332 | + self.log_context['topic_id'] = self.object.topic.id | ||
| 333 | + self.log_context['topic_name'] = self.object.topic.name | ||
| 334 | + self.log_context['topic_slug'] = self.object.topic.slug | ||
| 335 | + self.log_context['ytvideo_id'] = self.object.id | ||
| 336 | + self.log_context['ytvideo_name'] = self.object.name | ||
| 337 | + self.log_context['ytvideo_slug'] = self.object.slug | ||
| 338 | + | ||
| 339 | + super(UpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) | ||
| 248 | 340 | ||
| 249 | return redirect(self.get_success_url()) | 341 | return redirect(self.get_success_url()) |
| 250 | 342 | ||
| @@ -275,7 +367,12 @@ class UpdateView(LoginRequiredMixin, generic.UpdateView): | @@ -275,7 +367,12 @@ class UpdateView(LoginRequiredMixin, generic.UpdateView): | ||
| 275 | 367 | ||
| 276 | return success_url | 368 | return success_url |
| 277 | 369 | ||
| 278 | -class DeleteView(LoginRequiredMixin, generic.DeleteView): | 370 | +class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView): |
| 371 | + log_component = 'resources' | ||
| 372 | + log_action = 'delete' | ||
| 373 | + log_resource = 'ytvideo' | ||
| 374 | + log_context = {} | ||
| 375 | + | ||
| 279 | login_url = reverse_lazy("users:login") | 376 | login_url = reverse_lazy("users:login") |
| 280 | redirect_field_name = 'next' | 377 | redirect_field_name = 'next' |
| 281 | 378 | ||
| @@ -295,4 +392,72 @@ class DeleteView(LoginRequiredMixin, generic.DeleteView): | @@ -295,4 +392,72 @@ class DeleteView(LoginRequiredMixin, generic.DeleteView): | ||
| 295 | def get_success_url(self): | 392 | def get_success_url(self): |
| 296 | messages.success(self.request, _('The YouTube Video "%s" was removed successfully from virtual environment "%s"!')%(self.object.name, self.object.topic.subject.name)) | 393 | messages.success(self.request, _('The YouTube Video "%s" was removed successfully from virtual environment "%s"!')%(self.object.name, self.object.topic.subject.name)) |
| 297 | 394 | ||
| 298 | - return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug}) | ||
| 299 | \ No newline at end of file | 395 | \ No newline at end of file |
| 396 | + self.log_context['category_id'] = self.object.topic.subject.category.id | ||
| 397 | + self.log_context['category_name'] = self.object.topic.subject.category.name | ||
| 398 | + self.log_context['category_slug'] = self.object.topic.subject.category.slug | ||
| 399 | + self.log_context['subject_id'] = self.object.topic.subject.id | ||
| 400 | + self.log_context['subject_name'] = self.object.topic.subject.name | ||
| 401 | + self.log_context['subject_slug'] = self.object.topic.subject.slug | ||
| 402 | + self.log_context['topic_id'] = self.object.topic.id | ||
| 403 | + self.log_context['topic_name'] = self.object.topic.name | ||
| 404 | + self.log_context['topic_slug'] = self.object.topic.slug | ||
| 405 | + self.log_context['ytvideo_id'] = self.object.id | ||
| 406 | + self.log_context['ytvideo_name'] = self.object.name | ||
| 407 | + self.log_context['ytvideo_slug'] = self.object.slug | ||
| 408 | + | ||
| 409 | + super(DeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) | ||
| 410 | + | ||
| 411 | + return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug}) | ||
| 412 | + | ||
| 413 | +@log_decorator_ajax('resources', 'watch', 'ytvideo') | ||
| 414 | +def ytvideo_watch_log(request, ytvideo): | ||
| 415 | + action = request.GET.get('action') | ||
| 416 | + | ||
| 417 | + if action == 'open': | ||
| 418 | + ytvideo = get_object_or_404(YTVideo, slug = ytvideo) | ||
| 419 | + | ||
| 420 | + log_context = {} | ||
| 421 | + log_context['category_id'] = ytvideo.topic.subject.category.id | ||
| 422 | + log_context['category_name'] = ytvideo.topic.subject.category.name | ||
| 423 | + log_context['category_slug'] = ytvideo.topic.subject.category.slug | ||
| 424 | + log_context['subject_id'] = ytvideo.topic.subject.id | ||
| 425 | + log_context['subject_name'] = ytvideo.topic.subject.name | ||
| 426 | + log_context['subject_slug'] = ytvideo.topic.subject.slug | ||
| 427 | + log_context['topic_id'] = ytvideo.topic.id | ||
| 428 | + log_context['topic_name'] = ytvideo.topic.name | ||
| 429 | + log_context['topic_slug'] = ytvideo.topic.slug | ||
| 430 | + log_context['ytvideo_id'] = ytvideo.id | ||
| 431 | + log_context['ytvideo_name'] = ytvideo.name | ||
| 432 | + log_context['ytvideo_slug'] = ytvideo.slug | ||
| 433 | + log_context['timestamp_start'] = str(int(time.time())) | ||
| 434 | + log_context['timestamp_end'] = '-1' | ||
| 435 | + | ||
| 436 | + request.log_context = log_context | ||
| 437 | + | ||
| 438 | + log_id = Log.objects.latest('id').id | ||
| 439 | + | ||
| 440 | + return JsonResponse({'message': 'ok', 'log_id': log_id}) | ||
| 441 | + | ||
| 442 | + return JsonResponse({'message': 'ok'}) | ||
| 443 | + | ||
| 444 | +@log_decorator('resources', 'finish', 'ytvideo') | ||
| 445 | +def ytvideo_finish_log(request, ytvideo): | ||
| 446 | + ytvideo = get_object_or_404(YTVideo, slug = ytvideo) | ||
| 447 | + | ||
| 448 | + log_context = {} | ||
| 449 | + log_context['category_id'] = ytvideo.topic.subject.category.id | ||
| 450 | + log_context['category_name'] = ytvideo.topic.subject.category.name | ||
| 451 | + log_context['category_slug'] = ytvideo.topic.subject.category.slug | ||
| 452 | + log_context['subject_id'] = ytvideo.topic.subject.id | ||
| 453 | + log_context['subject_name'] = ytvideo.topic.subject.name | ||
| 454 | + log_context['subject_slug'] = ytvideo.topic.subject.slug | ||
| 455 | + log_context['topic_id'] = ytvideo.topic.id | ||
| 456 | + log_context['topic_name'] = ytvideo.topic.name | ||
| 457 | + log_context['topic_slug'] = ytvideo.topic.slug | ||
| 458 | + log_context['ytvideo_id'] = ytvideo.id | ||
| 459 | + log_context['ytvideo_name'] = ytvideo.name | ||
| 460 | + log_context['ytvideo_slug'] = ytvideo.slug | ||
| 461 | + | ||
| 462 | + request.log_context = log_context | ||
| 463 | + | ||
| 464 | + return JsonResponse({'message': 'ok'}) | ||
| 300 | \ No newline at end of file | 465 | \ No newline at end of file |