序列化和字符串转储以及Django Rest Framework API响应之间的延迟

时间:2018-10-09 18:59:49

标签: python json django postgresql django-rest-framework

我正在使用Django 2.1和django rest框架在我的项目上实现REST API。

在尝试解决项目中一些序列化缓慢的问题时,我意识到执行

MenuOption.lower()

在终端上只需不到2秒即可完成,而在视图上运行等效代码

json.dumps(ChecklistSerializer(intelligence.models.Checklist.objects.get(id=4), many=False).data)

耗时超过60秒。因此,我的问题是:

  1. 此时间差是否一定意味着慢速问题不是归因于序列化程序本身?
  2. 如何配置API中的所有时间(包括渗透检查和相关内容)?

相关型号:

class ChecklistDetail(APIView):
    permission_classes = (permissions.IsAuthenticated, StaffPermission)

    def get(self, request, pk, format=None):
        # pylint: disable=E1101
        checklist = Checklist.objects.get(pk=pk)
        serializer = ChecklistSerializer(checklist, many=False)
        return Response(serializer.data)

相关的序列化器:

class ChecklistPillar(BaseModel):
    """A model to represent a checklist pillar.

    Some of the checklists characteristics are related to checklist pillars.

    Attributes:
        name (str): The name of the pillar.
        name_pt (str): The name of the pillar in portuguese.
        symbol (str): The symbol of the pillar.
    """
    name = models.CharField(max_length=100, null=False, unique=True)
    name_pt = models.CharField(
        max_length=100, null=True, unique=True, blank=True)
    symbol = models.CharField(
        max_length=50, null=True, unique=True, blank=True)

    def __str__(self):
        if self.symbol is not None:
            return str(self.symbol)
        else:
            return str(self.name)

    def __repr__(self):
        return f'NoteType({self})'


class ChecklistCharacteristic(BaseModel):
    """A model to represent a checklist characteristic.

    Some of the checklists questions are related to checklist characteristic.

    Attributes:
        name (str): The name of the characteristic.
        name_pt (str): The name of the characteristic in portuguese.
        symbol (str): The symbol of the characteristic.
        pillar (ChecklistPillar): The pillar of the characteristic.
    """
    name = models.CharField(max_length=100, null=False, unique=True)
    name_pt = models.CharField(
        max_length=100, null=True, unique=True, blank=True)
    symbol = models.CharField(
        max_length=50, null=True, unique=True, blank=True)
    pillar = models.ForeignKey(
        'ChecklistPillar', null=True, on_delete=models.CASCADE,
        related_name='checklist_characteristics_as_pillar', blank=True)

    def __str__(self):
        if self.symbol is not None:
            message = str(self.symbol)
        else:
            message = str(self.name)

        if self.pillar is not None:
            message += f' (Pillar: {self.pillar})'

        return str(message)

    def __repr__(self):
        return f'ChecklistCharacteristic({self})'


class ChecklistQuestion(BaseModel):
    """A model to represent a checklist question.

    The checklist questions are designed to help analysts spot quantitative and
    qualitative investment redflags on companies.

    Attributes:
        content (str): The content of the question.
        content_pt (str): The content of the question in portuguese.
        is_invertied (bool): Whether the question is inverted (the desired
            response to a non-inverted question is True).
        characteristic (ChecklistCharacteristic): The characteristic of the
            question.
    """
    content = models.TextField(null=True, blank=True)
    content_pt = models.TextField(null=True, blank=True)
    is_inverted = models.BooleanField(null=False, default=False)
    characteristic = models.ForeignKey(
        'ChecklistCharacteristic', null=True, on_delete=models.PROTECT,
        related_name='cheklist_questions_as_characteristic', blank=True)
    question_number = models.PositiveIntegerField(default=0, null=True)

    def __str__(self):
        # pylint: disable=E1101
        # pylint: disable=E1136
        text = self.content if len(self.content) < 50 \
            else self.content[:50] + '...'
        return f'[{self.characteristic}] {text}'

    def __repr__(self):
        return f'ChecklistQuestion({self})'


class ChecklistAnswer(BaseModel):
    """A model to represent an answer to a checklist question.

    When a question is not inverted, the desired response is True (yes). If the
    response is False (no) and the question is not inverted or vice-versa then
    the answer to that question will be a red-flag.

    Attributes:
        question (ChecklistQuestion): The question to which this answer is
            related.
        answer (bool or None): The answer to the question. The answer None
            means that the question does not apply on the specific case of the
            company.
        checklist (Checklist): The checklist of which this answer is a part.
    """
    question = models.ForeignKey(
        'ChecklistQuestion', null=False, on_delete=models.CASCADE,
        related_name='checklist_answers_as_question')
    answer = models.NullBooleanField()
    checklist = models.ForeignKey(
        'Checklist', null=False, on_delete=models.CASCADE,
        related_name='checklist_answers_as_checklist')

    @property
    def redflag(self):
        # pylint: disable=E1101
        return self.answer != self.question.is_inverted

    def __str__(self):
        return f'{"[RED FLAG!] " if self.redflag else ""}' \
            f'{self.question}: {"Y" if self.answer else "N"}'

    def __repr__(self):
        return f'ChecklistAnswer({self})'


class Checklist(BaseModel):
    """A model to represent a company checklist.

    A checklist is comprised of many answers to fundamental questions related
    to a company's corporate health.

    Attributes:
        author (User): The author of the checklist.
        company (Company): The company to which the checklist is referring.
        published (bool): Whether this checklist is published or just a draft.
        publication_time (datetime): The publication time of the checklist.
    """
    author = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
    company = models.ForeignKey(
        'entity.Company', null=False, on_delete=models.CASCADE,
        related_name='checklists_as_company')
    published = models.BooleanField(default=False)
    publication_time = models.DateTimeField(null=False)

    @property
    def answers(self):
        # pylint: disable=E1101
        return ChecklistAnswer.objects.filter(checklist=self)

    @property
    def number_of_redflags(self):
        # pylint: disable=E1101
        return len([ans for ans in self.answers if ans.redflag])

    @property
    def scores(self):
        # First we get all valid answers of the checlist
        valid_answers = self.answers.filter(~Q(answer=None)).filter(
            ~Q(question__characteristic=None))

        # Now we should aggregate the answers by characteristic
        characteristics = {}

        for valid_answer in valid_answers:
            characteristic = valid_answer.question.characteristic
            if characteristic not in characteristics.keys():
                characteristics[characteristic] = [valid_answer]
            else:
                characteristics[characteristic] += [valid_answer]

        # Now we will decide the scores for each category
        scores = {}

        for characteristic, answers in characteristics.items():
            total_answers = len(answers)
            redflags = len([answer for answer in answers if answer.redflag])
            scores[characteristic.id] = max(min(
                6 - ceil((10 * redflags) / total_answers), 5), 0)

        return scores

    def __str__(self):
        # pylint: disable=E1101
        return f'[{self.updated_at}] {self.company.symbol} ' \
            f'({self.author.first_name[0]}{self.author.last_name[0]})'

    def __repr__(self):
        return f'Checklist({self})'

图书馆

class ChecklistPillarSerializer(serializers.ModelSerializer):
    class Meta:
        model = ChecklistPillar
        fields = '__all__'


class ChecklistCharacteristicSerializer(serializers.ModelSerializer):
    pillar = ChecklistPillarSerializer(many=False, read_only=True)

    class Meta:
        model = ChecklistCharacteristic
        fields = '__all__'


class ChecklistQuestionSerializer(serializers.ModelSerializer):
    class Meta:
        model = ChecklistQuestion
        fields = (
            'id',
            'created_at',
            'updated_at',
            'content',
            'content_pt',
            'is_inverted',
            'characteristic_id',
            'question_number',
        )


class ChecklistAnswerSerializer(serializers.ModelSerializer):
    question = ChecklistQuestionSerializer(many=False, read_only=True)

    class Meta:
        model = ChecklistAnswer
        fields = '__all__'

    def to_representation(self, instance):
        # pylint: disable=E1101
        return {
            **super().to_representation(instance),
            'redflag': instance.redflag,
        }


class ChecklistAnswerListSerializer(serializers.ModelSerializer):
    class Meta:
        model = ChecklistAnswer
        fields = (
            'question_id',
            'answer',
        )


class ChecklistListSerializer(serializers.ModelSerializer):
    author = UserListSerializer(many=False, read_only=True)
    company = CompanyListSerializer(many=False, read_only=True)

    class Meta:
        model = Checklist
        fields = '__all__'


class ChecklistSerializer(serializers.ModelSerializer):
    checklist_answers_as_checklist = ChecklistAnswerListSerializer(
        many=True, read_only=True)

    class Meta:
        model = Checklist
        fields = '__all__'

    def to_representation(self, instance):
        # pylint: disable=E1101
        return {
            **super().to_representation(instance),
            'number_of_redflags': instance.number_of_redflags,
            'scores': instance.scores,
        }

Gunicorn配置[[source]] url = "https://pypi.python.org/simple" verify_ssl = true name = "pypi" [packages] django = "*" gunicorn = "*" whitenoise = "*" python-decouple = "*" dj-database-url = "*" django-celery-beat = "*" django-celery-results = "*" djangorestframework = "*" djangorestframework-simplejwt = "*" django-cors-headers = "*" celery = {extras = ["redis"]} python-dateutil = "*" "psycopg2-binary" = "*" requests = "*" pyyaml = "*" invoke = "*" pandas = "*" scipy = "*" flower = "*" django-silk = "*" [dev-packages] [requires] python_version = "3.6"

所有项目都在Docker容器(gunicorn project.wsgi -b 0.0.0.0:80 --workers 5 --log-level debug --error-logfile /var/log/gunicorn_err.log --log-file /var/log/gunicorn.log --timeout 240)上运行

0 个答案:

没有答案