Source code for msgvis.apps.api.serializers

"""
This module defines serializers for the main API data objects:

.. autosummary::
    :nosignatures:

    DimensionSerializer
    FilterSerializer
    MessageSerializer
    QuestionSerializer

"""
from django.core.paginator import Paginator

from rest_framework import serializers, pagination

import msgvis.apps.corpus.models as corpus_models
import msgvis.apps.questions.models as questions_models
import msgvis.apps.enhance.models as enhance_models
import msgvis.apps.groups.models as groups_models
from msgvis.apps.dimensions import registry
from django.contrib.auth.models import User

# A simple string field that looks up dimensions on deserialization
class DimensionKeySerializer(serializers.CharField):
    def to_internal_value(self, data):
        return registry.get_dimension(data)

    def to_representation(self, instance):
        return instance.key


[docs]class DimensionSerializer(serializers.Serializer): """ JSON representation of Dimensions for the API. Dimension objects describe the variables that users can select to visualize the dataset. An example is below: :: { "key": "time", "name": "Time", "description": "The time the message was sent", } """ key = serializers.CharField(read_only=True) name = serializers.CharField(read_only=True) description = serializers.CharField(read_only=True) def to_internal_value(self, data): return registry.get_dimension(data['key'])
[docs]class FilterSerializer(serializers.Serializer): """ Filters indicate a subset of the range of a specific dimension. Below is an array of three filter objects. :: [{ "dimension": "time", "min_time": "2010-02-25T00:23:53Z", "max_time": "2010-02-28T00:23:53Z" }, { "dimension": "words", "levels": [ "cat", "dog", "alligator" ] }, { "dimension": "reply_count", "max": 100 }] Although every filter has a ``dimension`` field, the specific properties vary depending on the type of the dimension and the kind of filter. At this time, there are three types of filters: - Quantitative dimensions can be filtered using one or both of the ``min`` and ``max`` properties (inclusive). - The time dimension can be filtered using one or both of the ``min_time`` and ``max_time`` properties (inclusive). - Categorical dimensions can be filtered by specifying an ``include`` list. All other items are assumed to be excluded. The 'value' field may also be used for exact matches. """ dimension = DimensionKeySerializer() min = serializers.FloatField(required=False) max = serializers.FloatField(required=False) min_time = serializers.DateTimeField(required=False) max_time = serializers.DateTimeField(required=False) levels = serializers.ListSerializer(child=serializers.CharField(allow_null=True, allow_blank=True), required=False) value = serializers.CharField(allow_null=True, allow_blank=True, required=False)
class PersonSerializer(serializers.ModelSerializer): profile_image_processed_url = serializers.CharField() class Meta: model = corpus_models.Person fields = ('id', 'dataset', 'original_id', 'username', 'full_name', 'profile_image_processed_url', )
[docs]class MessageSerializer(serializers.ModelSerializer): """ JSON representation of :class:`.Message` objects for the API. Messages are provided in a simple format that is useful for displaying examples: :: { "id": 52, "dataset": 2, "text": "Some sort of thing or other", "sender": { "id": 2, "dataset": 1 "original_id": 2568434, "username": "my_name", "full_name": "My Name" }, "time": "2010-02-25T00:23:53Z" } Additional fields may be added later. """ sender = PersonSerializer() embedded_html = serializers.CharField() media_url = serializers.CharField() class Meta: model = corpus_models.Message fields = ('id', 'dataset', 'text', 'sender', 'time', 'original_id', 'embedded_html', 'media_url', )
class ArticleSerializer(serializers.ModelSerializer): class Meta: model = questions_models.Article fields = ('id', 'authors', 'link', 'title', 'year', 'venue',)
[docs]class QuestionSerializer(serializers.ModelSerializer): """ JSON representation of a :class:`.Question` object for the API. Research questions extracted from papers are given in the following format: :: { "id": 5, "text": "What is your name?", "source": { "id": 13, "authors": "Thingummy & Bob", "link": "http://ijn.com/3453295", "title": "Names and such", "year": "2001", "venue": "International Journal of Names" }, "dimensions": ["time", "author_name"] } The ``source`` object describes a research article reference where the question originated. The ``dimensions`` list indicates which dimensions the research question is associated with. """ source = ArticleSerializer(read_only=True) dimensions = serializers.SlugRelatedField(many=True, read_only=True, slug_field='key', source="ordered_dimensions") class Meta: model = questions_models.Question fields = ('id', 'source', 'dimensions', 'text',) read_only_fields = fields
class WordSerializer(serializers.ModelSerializer): class Meta: model = enhance_models.Word def to_representation(self, instance): return instance.text class MessageTypeSerializer(serializers.ModelSerializer): class Meta: model = corpus_models.MessageType def to_representation(self, instance): return instance.name class ExampleMessageSerializer(serializers.Serializer): dataset = serializers.PrimaryKeyRelatedField(queryset=corpus_models.Dataset.objects.all()) filters = serializers.ListField(child=FilterSerializer(), required=False) focus = serializers.ListField(child=FilterSerializer(), required=False) #messages = serializers.ListField(child=MessageSerializer(), required=False, read_only=True) groups = serializers.ListField(child=serializers.IntegerField(), required=False) messages = serializers.SerializerMethodField('paginated_messages') def paginated_messages(self, obj): request = self.context.get('request') messages_per_page = 10 page = 1 if request and request.query_params.get('page'): page = request.query_params.get('page') if request and request.query_params.get('messages_per_page'): messages_per_page = request.query_params.get('messages_per_page') paginator = Paginator(obj["messages"][:], messages_per_page) messages = paginator.page(page) serializer = PaginatedMessageSerializer(messages) return serializer.data class KeywordMessageSerializer(serializers.Serializer): dataset = serializers.PrimaryKeyRelatedField(queryset=corpus_models.Dataset.objects.all()) keywords = serializers.CharField(allow_null=True, allow_blank=True, required=False) messages = serializers.SerializerMethodField('paginated_messages') types_list = serializers.ListField(child=serializers.CharField(), required=False) def paginated_messages(self, obj): request = self.context.get('request') messages_per_page = 10 page = 1 if request and request.query_params.get('page'): page = request.query_params.get('page') if request and request.query_params.get('messages_per_page'): messages_per_page = request.query_params.get('messages_per_page') paginator = Paginator(obj["messages"].all(), messages_per_page) messages = paginator.page(page) serializer = PaginatedMessageSerializer(messages) return serializer.data class KeywordListSerializer(serializers.Serializer): dataset = serializers.IntegerField(required=True) q = serializers.CharField(allow_null=True, allow_blank=True, required=False) keywords = serializers.ListField(child=serializers.CharField(), required=False) class PaginatedMessageSerializer(pagination.PaginationSerializer): class Meta: object_serializer_class = MessageSerializer class GroupSerializer(serializers.ModelSerializer): messages = serializers.SerializerMethodField('paginated_messages', required=False) message_count = serializers.IntegerField(required=False) include_types = MessageTypeSerializer(many=True, required=False) types_list = serializers.ListField(child=serializers.CharField(), required=False) order = serializers.IntegerField(required=False, read_only=True) is_search_record = serializers.BooleanField(default=False) class Meta: model = groups_models.Group fields = ('id', 'owner', 'order', 'created_at', 'dataset', 'name', 'keywords', 'messages', 'message_count', 'include_types', 'types_list', 'is_search_record', ) read_only_fields = ('owner', 'order', 'created_at', ) def paginated_messages(self, obj): if self.context and self.context.get('show_message'): paginator = Paginator(obj.messages.all(), 10) page = 1 request = self.context.get('request') if request and request.query_params.get('page'): page = request.query_params.get('page') messages = paginator.page(page) serializer = PaginatedMessageSerializer(messages) return serializer.data else: return None def create(self, validated_data): group = groups_models.Group.objects.create(dataset=validated_data["dataset"], name=validated_data["name"]) if validated_data.get('keywords'): group.keywords = validated_data.get('keywords') group.save() if validated_data.get('types_list'): include_types = [corpus_models.MessageType.objects.get(name=x) for x in validated_data.get('types_list')] group.include_types = include_types else: include_types = corpus_models.MessageType.objects.filter(id > 0).all() group.include_types = include_types return group class DatasetSerializer(serializers.ModelSerializer): class Meta: model = corpus_models.Dataset fields = ('id', 'name', 'description', 'message_count', 'has_prefetched_images', ) read_only_fields = ('id', 'name', 'description', 'message_count', 'has_prefetched_images', ) class SampleQuestionSerializer(serializers.Serializer): dimensions = serializers.ListField(child=serializers.CharField(), required=False) questions = serializers.ListField(child=QuestionSerializer(), required=False, read_only=True) class DataTableSerializer(serializers.Serializer): dataset = serializers.PrimaryKeyRelatedField(queryset=corpus_models.Dataset.objects.all()) dimensions = serializers.ListField(child=DimensionKeySerializer()) filters = serializers.ListField(child=FilterSerializer(), required=False) exclude = serializers.ListField(child=FilterSerializer(), required=False) result = serializers.DictField(required=False, read_only=True) page_size = serializers.IntegerField(required=False) page = serializers.IntegerField(required=False) search_key = serializers.CharField(allow_null=True, allow_blank=True, required=False) mode = serializers.CharField(allow_null=True, allow_blank=True, required=False) groups = serializers.ListField(child=serializers.IntegerField(), required=False) class ActionHistorySerializer(serializers.ModelSerializer): created_at = serializers.DateTimeField(required=False) class Meta: model = groups_models.ActionHistory fields = ('id', 'owner', 'type', 'contents', 'created_at', ) read_only_fields = ('id', ) class ActionHistoryListSerializer(serializers.Serializer): records = serializers.ListField(child=ActionHistorySerializer(), required=True)