-
Notifications
You must be signed in to change notification settings - Fork 12
Log Guide [EN US]
The log system is used to collect important information about Amadeus's users profile, giving the possibility to know which parts are more accessed and how much time are spent on it, among other things. With this bunch of information we are able to improve the students learning by telling him directions to increase his grades.
To be able to use the log system you'll need import in the views.py file of your app the following packages:
- LogMixin from core.models: used to activate the log system in Class-Based Views;
- log_decorator from core.decorators: used to activate the log system in Function-Based Views;
- log_decorator_ajax from core.decorators: used to activate the log system in Function-Based Views that are activated by ajax components like accordion or collapse in case you need to store the time spent by the user with the component open;
- Log from core.models: used in case you need store the time spent by the user in the page;
-
Class-Based Views:
-
First you need to make your class extends the LogMixin:
class MyView(..., LogMixin,...):
-
Doing this the following attributes will be available to your class:
- log_action - A string that indicates what was the user's action (Ex.: viewed, create, update...)
- log_resource - A string that indicates what was the resource (i.e. part of the app) whose user has taken action (Ex.: forum, course, topic...)
- log_component - A string that indicates what was the app whose user has taken action (The app's name)
- log_context - A dict that stores all relevant information about the context of the resource, like all the path to get to it, and info about the resource specifically.
In code:
class MyView(..., LogMixin,...): log_action = "" log_resource = "" log_component = "" log_context = {} #other attributes
Obs.: The log_context attribute should be explicit declared in the class attribute's section in order to access it in the class methods to populate it. For it's population you can use any of the class-based views methods (form_valid, dispatch, get_success_url) since you have all the required information in it. In code:
class MyView(..., LogMixin,...): #attribute definitions and other methods def get_success_url(self): #some routine/definitions self.log_context['key'] = value #possibly more log_context info #other method routines/definitions
Obs².: All information putted in log_context should be json serializable (It's recommended to use only strings)
-
With the fields fulfilled the attributes you'll need to call in one of your methods (the same as you used to populate the log_context) the following function:
super(ClassViewName, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
This function receives as parameter all the log attributes that are available through the addition of LogMixin and the user that made the request. It is important to ensure that the user is not an anonymous user which can be made by the addition of LoginRequiredMixin (See the Django documentation about it).
-
In order to store the time spent by the user in that resource you should:
- Add this in your log_context:
self.log_context['timestamp_start'] = str(int(time.time()))
- Add this line after calling the createLog function:
self.request.session['log_id'] = Log.objects.latest('id').id
-
Here is a full example on how it would be the code:
import time from django.shortcuts import render, get_object_or_404 from django.core.urlresolvers import reverse, reverse_lazy from core.models import Log from core.mixins import LogMixin from .forms import ForumForm from .models import Forum class CreateForumView(LoginRequiredMixin, generic.edit.CreateView, LogMixin): log_component = "forum" log_action = "create" log_resource = "forum" log_context = {} login_url = reverse_lazy("core:home") redirect_field_name = 'next' template_name = 'forum/forum_form.html' form_class = ForumForm def get_success_url(self): self.success_url = reverse('course:forum:render_forum', args = (self.object.id, )) #In this case Forum has a relation with topic (You need to access a topic to reach the forum) #So info about the forum's topic is provided to the log_context self.log_context['forum_id'] = self.object.id self.log_context['forum_name'] = self.object.name self.log_context['topic_id'] = self.object.topic.id self.log_context['topic_name'] = self.object.topic.name self.log_context['topic_slug'] = self.object.topic.slug super(CreateForumView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) return self.success_url class ForumDetailView(LoginRequiredMixin, LogMixin, generic.DetailView): log_component = "forum" log_action = "viewed" log_resource = "forum" log_context = {} login_url = reverse_lazy("core:home") redirect_field_name = 'next' model = Forum template_name = 'forum/forum_view.html' context_object_name = 'forum' def dispatch(self, *args, **kwargs): forum = get_object_or_404(Forum, slug = self.kwargs.get('slug')) #In this case Forum has a relation with topic (You need to access a topic to reach the forum) #So info about the forum's topic is provided to the log_context self.log_context['forum_id'] = forum.id self.log_context['forum_name'] = forum.name self.log_context['topic_id'] = forum.topic.id self.log_context['topic_name'] = forum.topic.name self.log_context['topic_slug'] = forum.topic.slug self.log_context['timestamp_start'] = str(int(time.time())) super(ForumDetailView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) self.request.session['log_id'] = Log.objects.latest('id').id return super(ForumDetailView, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): context = super(ForumDetailView, self).get_context_data(**kwargs) forum = get_object_or_404(Forum, slug = self.kwargs.get('slug')) context['forum'] = forum return context
-
-
Function-Based Views:
-
To get log_system working with function-based views all you have to do is to add the following decorator:
@log_decorator("", "", "")
In it, the first parameter refers to log_component; the second to log_action; e the third to log_resource;
Obs.: To populate the log_context all you need is, in the body of your function, add it in the request parameter "log_context". In code:
log_context = {} log_context['course_id'] = course.id log_context['course_name'] = course.name log_context['course_slug'] = course.slug log_context['course_category_id'] = course.category.id log_context['course_category_name'] = course.category.name request.log_context = log_context
The full code would be something like this:
#imports and other functions @log_decorator("course", "subscribe", "course") def subscribe_course(request, slug): course = get_object_or_404(Course, slug = slug) course.students.add(request.user) log_context = {} log_context['course_id'] = course.id log_context['course_name'] = course.name log_context['course_slug'] = course.slug log_context['course_category_id'] = course.category.id log_context['course_category_name'] = course.category.name request.log_context = log_context return JsonResponse({"status": "ok", "message": _("Successfully subscribed to the course!")})
-
If you want to store the time spent by the user you'll need to change the decorator to:
Obs.: This is recommended in ajax requests, if this is not the case you should consider using Class-Based Views@log_decorator_ajax("", "", "")
Obs.: The parameters are the same as in log_decorator.
In addition to it you'll need to add to your log_context:
log_context['timestamp_start'] = str(int(time.time())) log_context['timestamp_end'] = "-1"
And get the last generated log id to pass to response:
log_id = Log.objects.latest('id').id response = JsonResponse({"message": "ok", "log_id": log_id})
The full code would be similar to this:
@log_decorator_ajax("courses", "viewed", "topic") def topic_log(request, topic): topic = get_object_or_404(Topic, id = topic) log_context = {} log_context['topic_id'] = topic.id log_context['topic_name'] = topic.name log_context['topic_slug'] = topic.slug log_context['subject_id'] = topic.subject.id log_context['subject_name'] = topic.subject.name log_context['subject_slug'] = topic.subject.slug log_context['timestamp_start'] = str(int(time.time())) log_context['timestamp_end'] = "-1" request.log_context = log_context log_id = Log.objects.latest('id').id response = JsonResponse({"message": "ok", "log_id": log_id}) return response
-