我正在使用Django 2.1和django rest框架在我的项目上实现REST API。
在尝试解决项目中一些序列化缓慢的问题时,我意识到执行
MenuOption.lower()
在终端上只需不到2秒即可完成,而在视图上运行等效代码
json.dumps(ChecklistSerializer(intelligence.models.Checklist.objects.get(id=4), many=False).data)
耗时超过60秒。因此,我的问题是:
相关型号:
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
)上运行