Skip to content
Snippets Groups Projects
serializers.py 6.25 KiB
Newer Older
"""
Serializers creating JSONs for every Model from .models
"""
from rest_framework import serializers
borzechof99's avatar
borzechof99 committed
from .models import Sport, Criterion, Question, validate_rating


class SportListSerializer(serializers.ModelSerializer):
    """
    Serializes all sports.
    """

    class Meta:
        model = Sport
borzechof99's avatar
borzechof99 committed
        fields = ("id", "name", "url", "criteria_ratings")
class QuestionListSerializer(serializers.ModelSerializer):
    """
    Serializes all Questions.
    """

    class Meta:
        model = Question
borzechof99's avatar
borzechof99 committed
        fields = ("id", "text", "criterion")
class CriterionListSerializer(serializers.ModelSerializer):
    """
    Serializes Criterions
    """

    class Meta:
        model = Criterion
borzechof99's avatar
borzechof99 committed
        fields = ("id", "name")


class SmallSportListSerializer(serializers.BaseSerializer):
borzechof99's avatar
borzechof99 committed
    """
    Serializes Lists of Sport Objects in a "Simple" Manner, with Criterions being represented in a Bool.
    """

    def to_representation(self, sport_filled_tuples):
        """
        Takes a List of (Sport, bool) tuples to Serialize.
        The Bool Represents whether the Sport is Filled or not.
        """
borzechof99's avatar
borzechof99 committed
        for sport, boolean in sport_filled_tuples:
            serialized_data.append(
                {
borzechof99's avatar
borzechof99 committed
                    "id": sport.pk,
                    "name": sport.name,
                    "url": sport.url,
                    "is_filled": boolean,
                }
            )

        return serialized_data


class SingleSportSerializer(serializers.BaseSerializer):
borzechof99's avatar
borzechof99 committed
    """
    Serializes and Deserializes a Single Sport Object
    """

    def to_representation(self, sport):
borzechof99's avatar
borzechof99 committed
        """
        Takes a Single Sport Object and Serializes it and all its Criteria
        """
borzechof99's avatar
borzechof99 committed
        serialized_data["id"] = sport.pk
        serialized_data["name"] = sport.name
        serialized_data["url"] = sport.url
        serialized_data["currently_active"] = sport.currently_active
        serialized_data["last_used"] = sport.last_used

        criteria = []

        for criterion in sport.criteria_ratings.iterator():
            criterion_data = {}

borzechof99's avatar
borzechof99 committed
            criterion_data["id"] = criterion.pk
            criterion_data["name"] = criterion.name

            criterion_data["value"] = sport.get_rating(criterion)

            criteria.append(criterion_data)

        serialized_data["criteria"] = criteria

        return serialized_data

    def to_internal_value(self, request):
        """
        The Data in the Request is taken and written to another Dictionary.
        During this process, the Data is Validated on whether the Rating Value and Criterion ID are valid.
        If the Request is PATCHing or PUTting an existing Sport, not every field must be existant.
        So, the existance is explicitly checked.
        TODO: Different Functions based on PUT or PATCH?
        # If The Sport is Being Patched, Name or URL may not be changed.
        # That means that those Fields might not be sent in the Request,
        # leading to needing to check whether they exist.
        if "name" in request.data.keys():
            sport_dictionary["name"] = request.data["name"]

        if "url" in request.data.keys():
            sport_dictionary["url"] = request.data["url"]
        if "currently_active" in request.data.keys():
            sport_dictionary["currently_active"] = request.data["currently_active"]

        # If the Sport is only now created with a POST-Request, no Criteria can be filled out for it
        # This is because the Admin Frontend doesn't have a list of Criteria ready
        if "criteria" in request.data.keys():
            # A Number of Criteria may be sent with the Sport
            sport_dictionary["criteria"] = []
            # For every Sent Criterion, the ID of the Criterion and the Rating Value is being tested for Validity
            for criterion in request.data["criteria"]:
                value = criterion["value"]
                try:
                    validate_rating(value)
                    crit = Criterion.objects.get(pk=criterion["id"])
                except:  # pylint: disable=bare-except
                    return None

                sport_dictionary["criteria"].append((crit, value))

        return sport_dictionary


class IncompleteSportSerializer(serializers.BaseSerializer):
borzechof99's avatar
borzechof99 committed
    """
    Serializes every Sport Object with Incomplete Criteria Ratings.
    Includes the Name and ID of both the Sport and the Criteria.
    """

    def to_representation(self, incomplete_sports):
borzechof99's avatar
borzechof99 committed
        """
        Serializes Every given Sport Object and goes through every Criterium to serialize those that are unrated.
        """

        incomplete_sport_list = []

        for sport in incomplete_sports:
            incomplete_sport = {
                "id": sport.pk,
                "name": sport.name,
                "criteria": [],
            }

            for crit in sport.criteria_ratings.iterator():
dominip89's avatar
dominip89 committed
                # Asking this way to save an indentation and for readability. Would also work when asking for = -1 and handling the append then.
                if sport.get_rating(crit) != -1:
                    continue

                incomplete_sport["criteria"].append(
                    {
                        "id": crit.pk,
                        "name": crit.name,
                    }
                )

            incomplete_sport_list.append(incomplete_sport)

        return incomplete_sport_list


class CriteriaSerializer(serializers.BaseSerializer):
borzechof99's avatar
borzechof99 committed
    """
    Serializes Every Criterium and Metadata
    """

    def to_representation(self, data):
borzechof99's avatar
borzechof99 committed
        """
        Takes Tuples of (Criterium, Int, Int),
        where the Integers are the Number of Sports in which the Rating is >1
        and the cumulated sum of Ratings >1, respectively
        """

        criteria_list = []

        for crit, active_sports, sum_of_weights in data:

            criterion_dict = {}

            criterion_dict["id"] = crit.pk
            criterion_dict["question_id"] = crit.question.pk
            criterion_dict["name"] = crit.name
            criterion_dict["number_of_sports_active"] = active_sports
            criterion_dict["sum_of_weights"] = sum_of_weights
            criteria_list.append(criterion_dict)