Annotate performance Django - python

I've got the following models:
class Match(models.Model):
objects = BulkUpdateOrCreateQuerySet.as_manager()
id = models.AutoField(primary_key=True)
betsapi_id = models.IntegerField(unique=True, null=False)
competition:Competition = models.ForeignKey(Competition, on_delete=models.CASCADE, related_name='matches')
season:Season = models.ForeignKey(Season, on_delete=models.CASCADE, related_name='season_matches', null=True, default=None)
home:Team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='home_matches')
away:Team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='away_matches')
minute = models.IntegerField(default=None, null=True)
period = models.CharField(max_length=25, default=None, null=True)
datetime = models.DateTimeField()
status = models.IntegerField()
opta_match = models.OneToOneField(OptaMatch, on_delete=models.CASCADE, related_name='match', default=None, null=True)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
class Season(models.Model):
id = models.AutoField(primary_key=True)
competition:Competition = models.ForeignKey(to=Competition, on_delete=models.CASCADE, null=False, blank=False, related_name='seasons')
start_date = models.DateTimeField(blank=False, null=False)
end_date = models.DateTimeField(blank=False, null=False)
name = models.CharField(max_length=255, null=True, default=None)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
class Event(models.Model):
objects = BulkUpdateOrCreateQuerySet.as_manager()
id = models.AutoField(primary_key=True)
betsapi_id = models.IntegerField(unique=True)
name = models.CharField(max_length=255)
minute = models.IntegerField()
player_name = models.CharField(max_length=255, null=True, default=None)
extra_player_name = models.CharField(max_length=255, null=True, default=None)
period = models.CharField(max_length=255)
team:Team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='events')
match:Match = models.ForeignKey(Match, on_delete=models.CASCADE, related_name='events')
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
And I wrote the following annotations to a Match object:
all_matches_qs = (Match
.objects
.filter(status=1)
.select_related('home', 'away', 'competition', 'competition__country', 'season', 'opta_match')
.prefetch_related(
Prefetch("season", queryset=Season.objects.prefetch_related(
Prefetch("season_matches", queryset=Match.objects.prefetch_related(
Prefetch('statistics')))
)),
Prefetch('events', queryset=Event.objects.select_related("team", "match").filter(name__in=["Corner", "Goal", "Substitution", "Yellow Card", "Red Card"])),
)
.annotate(season_statistics_count=Count('season__season_matches__statistics'))
.annotate(goals=Count('events', distinct=True, filter=(Q(events__name='Goal') & Q(events__team=F('home')))))
)
Executing this on about 25 records takes me about 3.75 seconds whereas if I remove one of the annotations (doesn't matter which one) the time to execute drops to about 0.5 seconds.
Also, removing the filter(status=1) seems to be dropping the time to execute to near 0.3s.
I'm wondering what is causing this issue and how to ensure I can execute both annotations AND the filter without a drastic performance drop?

Related

Serialize same level object from Many to many field

I have to serialize spare instance from spare variety many to many field.
Models.py
class SpareVariety(models.Model):
quality = models.ForeignKey(Quality, max_length=255, on_delete=models.CASCADE, null=True, blank=True)
variety_name = models.CharField(max_length=255, null=True, blank=True)
property = models.ForeignKey(SpareProperty, null=True, blank=True, on_delete=models.CASCADE)
purchase_price = models.PositiveIntegerField(help_text="in INR", blank=True, null=True)
retail_price = models.FloatField(help_text="All values in INR", blank=True, null=True)
dealer_price = models.FloatField(help_text="All values in INR", blank=True, null=True)
stock_available = models.PositiveIntegerField(blank=True, null=True,default=True)
spare_costing = models.ForeignKey(SpareCosting, on_delete=models.CASCADE, blank=True, null=True)
spare_discount = models.ForeignKey(Discount, on_delete=models.CASCADE, blank=True, null=True)
is_available = models.BooleanField(default=False)
date_added = models.DateTimeField(auto_now=True)
date_updated = models.DateTimeField(auto_now_add=True)
class Spare(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
spare_variety = models.ManyToManyField(SpareVariety, related_name='spare_varieties', null=True, blank=True)
name = models.CharField(max_length=255, help_text="Enter the name of spare (Ex:Display, Speakers)")
type = models.ForeignKey(Type, blank=True, null=True, on_delete=models.CASCADE)
date_added = models.DateTimeField(auto_now=True)
date_updated = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.product.name, self.name)
Serialize the spare model from spare variety serializer
serializers.py
class SpareVarietySerializer(serializers.HyperlinkedModelSerializer):
spare_costing= SpareCostingSerializer(many=False, read_only=False)
spare_discount = DiscountSerializer(many=False, read_only=False)
quality = QualitySerializer(many=False, read_only=False)
property = SparePropertySerializer(many=False, read_only=False)
spare_name = serializers.CharField(read_only=True, source="spare.name")
class Meta:
model = SpareVariety
fields = ['id','quality','variety_name','purchase_price','spare_name','retail_price','property', 'dealer_price', 'stock_available','spare_costing','spare_discount','is_available', 'date_added', 'date_updated',]

Django complex query with page load slow

I have a quiz application made with Django. I am basically loading a pretty complex query. What I am basically doing is creating a new exam with this logic:
Fetch the question from the question bank (the Question model)
I get a certain questions number from each subject and I use them to create a QuestionDraft so I can store and save each student result.
Each QuestionDraft has the AnswerDraft which I use for storing the user answered questions (each AnswerDraft is basically a carbon copy of the question bank Answer).
While I wanna load a 50-question-test everything works pretty fine but when I want to load more than that amount of question, the page is loading extremely slow.
I would like to know if, based on the models and the code I post down below, there is any way to improve the efficiency of the queries and/or the loading time.
models.py
class QuestionSubject(models.Model):
quiz_course = models.ForeignKey(QuizTheoryCourse, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
exam_questions_num = models.IntegerField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Question(models.Model):
id = models.CharField(max_length=7,
default=generate_question_id,
unique=True,
primary_key=True,
editable=False)
question_subject = models.ForeignKey(
QuestionSubject, on_delete=models.CASCADE)
text = models.TextField()
mark = models.IntegerField(default=1)
is_published = models.BooleanField(default=True)
question_bank_id = models.CharField(max_length=255, blank=True, null=True)
question_topic = models.ForeignKey(
QuestionTopic, on_delete=models.CASCADE, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
text = models.TextField()
is_correct = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class QuizProfile(models.Model):
id = models.CharField(max_length=7,
default=generate_question_id,
unique=True,
primary_key=True,
editable=False)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
subject = models.ForeignKey(
QuestionSubject, on_delete=models.CASCADE, blank=True, null=True)
total_score = models.DecimalField(default=0,
decimal_places=2,
max_digits=5)
quiz_type = models.CharField(
max_length=255, choices=quiz_type, blank=True, null=True)
right_answer = models.IntegerField(default=0)
is_completed = models.BooleanField(default=False)
is_assigned = models.BooleanField(blank=True, null=True, default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user.username + ' ' + self.id
class Meta:
ordering = ('-created_at',)
class QuestionDraft(models.Model):
quiz_profile = models.ForeignKey(QuizProfile,
on_delete=models.CASCADE,
blank=True,
null=True)
question = models.ForeignKey(Question,
on_delete=models.CASCADE,
blank=True,
null=True)
text = models.TextField()
is_answered = models.BooleanField(blank=True, null=True)
is_correct = models.BooleanField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.quiz_profile) + ' ' + str(self.question)
class AnswerDraft(models.Model):
quiz_profile = models.ForeignKey(QuizProfile,
on_delete=models.CASCADE,
blank=True,
null=True)
question_draft = models.ForeignKey(QuestionDraft, on_delete=models.CASCADE)
answer = models.ForeignKey(Answer,
on_delete=models.CASCADE,
null=True,
blank=True)
text = models.TextField()
is_answered = models.BooleanField(blank=True, null=True)
is_correct = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.quiz_profile) + ' ' + str(self.answer)
class QuizDraft(models.Model):
id = models.CharField(max_length=7,
default=generate_question_id,
unique=True,
primary_key=True,
editable=False)
quiz_profile = models.ForeignKey(QuizProfile, on_delete=models.CASCADE)
question_draft = models.ForeignKey(QuestionDraft,
on_delete=models.CASCADE,
blank=True,
null=True)
def __str__(self):
return str(self.quiz_profile)
views.py
def ppl_exam_generator_util(request, subjects):
question_list = [Question.objects.filter(question_subject=subject).order_by(
'?')[:int(subject.exam_questions_num)]for subject in subjects]
quiz_profile = QuizProfile(
user=request.user, quiz_type='ppl_exam')
quiz_profile.save()
for ques in question_list:
for q in ques:
question = Question.objects.get(id=q.id)
quiz_attempt = QuizAttempt(quiz_profile=quiz_profile,
question=question)
quiz_attempt.save()
question_draft = QuestionDraft(
question=question, text=question.text, quiz_profile=quiz_profile)
question_draft.save()
quiz_draft = QuizDraft(
quiz_profile=quiz_profile, question_draft=question_draft)
quiz_draft.save()
answers = Answer.objects.filter(question__id=question.id)
shuffle(list(answers))
for ans in answers:
draft_answer = AnswerDraft(
question_draft=question_draft, answer=ans, text=ans.text, quiz_profile=quiz_profile)
draft_answer.save()
return HttpResponseRedirect(reverse('quiz:new_ppl_exam', kwargs={'pk': quiz_profile.id}))
I tried also with the connection.queries tool Django provides, but each query is pretty fast. I don't know if it's a problem with the nested forloop or something else.

Find pk in queryset Django

I have a problem in obtaining a single id from a queryset. I post my models and views in order to be more clear:
models.py
class MissionEntry(models.Model):
student = models.ForeignKey(
Student, on_delete=models.DO_NOTHING, blank=True, null=True)
mission = models.ForeignKey(
Mission, on_delete=models.DO_NOTHING, null=True, blank=True)
log_entry = models.ForeignKey(
LogEntry, on_delete=models.DO_NOTHING, blank=True, null=True)
learning_objective = models.ForeignKey(
LearningObjective, on_delete=models.DO_NOTHING, blank=True, null=True)
grade = models.CharField(
max_length=10, choices=GRADING_VALUE, blank=True, null=True)
note = models.TextField(blank=True, null=True)
debriefing = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.mission) + ' ' + str(self.log_entry)
class Meta:
verbose_name_plural = 'Mission Entries'
class MissionEntryStatus(models.Model):
mission = models.ForeignKey(
Mission, on_delete=models.PROTECT, null=True, blank=True)
student = models.ForeignKey(Student, on_delete=models.PROTECT)
is_completed = models.BooleanField(default=False)
is_failed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class StudentMission(models.Model):
mission = models.ForeignKey(Mission, on_delete=models.PROTECT)
student_training_course = models.ForeignKey(
StudentTrainingCourse, on_delete=models.PROTECT)
mission_status = models.ForeignKey(
MissionEntryStatus, on_delete=models.PROTECT, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['mission__name']
def __str__(self):
return self.mission.name
class LogEntry(models.Model):
aircraft = models.ForeignKey(Aircraft, on_delete=models.DO_NOTHING)
adep = models.ForeignKey(
Aerodrome, on_delete=models.PROTECT, related_name='adep')
ades = models.ForeignKey(
Aerodrome, on_delete=models.PROTECT, related_name='ades')
date = models.DateField()
etd = models.TimeField()
ata = models.TimeField()
eet = models.TimeField()
function_type = models.ForeignKey(FunctionType, on_delete=models.PROTECT)
student = models.ForeignKey(
Student, on_delete=models.PROTECT, blank=True, null=True)
instructor = models.ForeignKey(
Instructor, on_delete=models.PROTECT, blank=True, null=True)
student_mission = models.ForeignKey(
'mission.StudentMission', on_delete=models.PROTECT, null=True, blank=True)
note = models.TextField(null=True, blank=True)
cross_country = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
views.py
def student_mission_list(request, pk):
student = Student.objects.get(id=pk)
student_training_course = StudentTrainingCourse.objects.filter(
student_id=student.id)
missions = StudentMission.objects.filter(
student_training_course_id__in=student_training_course)
mission_entry = MissionEntry.objects.filter(student_id=student)
log_entry = LogEntry.objects.filter(student_mission_id__in=missions)
print(log_entry)
context = {
'student': student,
'missions': missions,
'mission_entry': mission_entry,
}
return render(request, 'mission/student_mission_list.html', context)
In fact, what I need to do, is to obtain a single value for the log_entry. The problem is that, obviously, I am retrieving multiple values of log_entry. But I would like to get the single pk of the log_entry.
Any suggestion? Should I remodel the models.py file?
try this:
log_entry = LogEntry.objects.get(student_mission_id__in=missions)
print(log_entry.id)

Python Django - Not 'object' attribute on scaffolded model

I'm only a newbie in Python and Django.
I'm working with a MySQL database, I have created the model with the command: python manage.py inspectdb > /app/models/model.py. And it works wonderfully.
model.py
from __future__ import unicode_literals
from django.db import models
class Account(models.Model):
id = models.BigAutoField(primary_key=True)
login = models.CharField(unique=True, max_length=30)
lang = models.CharField(max_length=4)
forum_name = models.CharField(max_length=80)
hwid = models.CharField(max_length=255, blank=True, null=True)
use_allowed_hwids = models.IntegerField(blank=True, null=True)
password = models.CharField(max_length=45)
social_id = models.CharField(max_length=13)
email = models.CharField(max_length=64)
create_time = models.DateTimeField(blank=True, null=True)
status = models.CharField(max_length=8)
reason = models.CharField(max_length=255, blank=True, null=True)
securitycode = models.CharField(max_length=192, blank=True, null=True)
newsletter = models.IntegerField(blank=True, null=True)
empire = models.IntegerField()
name_checked = models.IntegerField()
availdt = models.DateTimeField(db_column='availDt', blank=True, null=True) # Field name made lowercase.
mileage = models.IntegerField()
cash = models.IntegerField()
gold_expire = models.DateTimeField()
silver_expire = models.DateTimeField()
safebox_expire = models.DateTimeField()
autoloot_expire = models.DateTimeField()
fish_mind_expire = models.DateTimeField()
marriage_fast_expire = models.DateTimeField()
money_drop_rate_expire = models.DateTimeField()
shop_double_up_expire = models.DateTimeField()
total_cash = models.IntegerField()
total_mileage = models.IntegerField()
ip = models.CharField(max_length=255, blank=True, null=True)
last_pw_change = models.DateTimeField(blank=True, null=True)
web_admin = models.IntegerField()
web_ip = models.CharField(max_length=15)
web_aktiviert = models.CharField(max_length=32)
real_name = models.CharField(max_length=32, blank=True, null=True)
question1 = models.CharField(max_length=64, blank=True, null=True)
answer1 = models.CharField(max_length=64, blank=True, null=True)
last_vote = models.DateTimeField(blank=True, null=True)
lostpw_token = models.CharField(max_length=64, blank=True, null=True)
last_play = models.DateTimeField(blank=True, null=True)
remember_token = models.TextField(blank=True, null=True)
class Meta:
managed = False
db_table = 'account'
All works fine, but I can't see any "objects" attribute in my intellisense, and if i write it i can see only "Accounts.objects"... And no more
screenshot
I'm using Python 36

Filter one-to-many relationship

I'm using django-filter and I would like to ask you if it could filter one to many reliontionship because I did not found any doc or example even on StackOverflow., here are the model, the filter and the view
class Aliens(models.Model):
class Meta:
db_table = 'aliens'
verbose_name = ('Introduction Event')
verbose_name_plural = ('Introuction Events')
ordering = ['alien']
alien = models.OneToOneField(Taxonomy, verbose_name=u"Non-indigenous Species",
on_delete=models.CASCADE, null=True, blank=True)
#SpeciesName = models.CharField(max_length=100, verbose_name=u"Species Name", blank=True, null=True)
group = models.OneToOneField(Ecofunctional, verbose_name=u"Ecofunctional Group", on_delete=models.CASCADE,
blank=True, null=True, default='')
firstsight = models.IntegerField(('First Mediterranean Sighting'), choices=YEAR_CHOICES, blank=True, null=True)
med_citation = models.ForeignKey(biblio, verbose_name=u"Mediterranean first citation", on_delete=models.CASCADE,
null=True, blank=True)
origin = models.OneToOneField(Origin, on_delete=models.CASCADE, blank=True, null=True, default='',
verbose_name=u"Origin")
status = models.OneToOneField(SuccessType, on_delete=models.CASCADE, blank=True, null=True, default='',
verbose_name=u"Establishement")
created_by = CurrentUserField()
created_at = models.DateField('date of inclusion', blank=True, null=True, default=datetime.datetime.now())
photo = models.ImageField(upload_to='photos', blank=True, null=True)
vector = models.ManyToManyField(vectors, verbose_name=u"Vectors/Pathways")
updated_at = models.DateField('date of updating', blank=True, null=True, default=datetime.datetime.now())
updated_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='%(class)s_requests_updated',
default=CurrentUserField(), null=True)
notes = models.TextField(verbose_name='Notes', blank=True, null=True)
db_status = StateField(verbose_name='Species Status in the Db', blank=True, null=True)
def __str__(self): # __unicode__ on Python 2
return self.alien.SpeciesName
class Distributions(models.Model):
class Meta:
db_table = 'distributions'
verbose_name = ('verified occurence')
verbose_name_plural = ('verified occurences')
alien = models.ForeignKey(Aliens, verbose_name=u"Non-Indeginous Species", related_name='distributions',
on_delete=models.CASCADE, null=True, blank=True)
country = models.OneToOneField(Country, on_delete=models.CASCADE, verbose_name='Country', blank=True, null=True)
seas = models.OneToOneField(regionalseas, on_delete=models.CASCADE, verbose_name='Regional Sea', blank=True,
null=True)
MSFD = models.OneToOneField(MSFD, on_delete=models.CASCADE, verbose_name='MSFD/EcAp Sub-region', blank=True,
null=True)
area1stSighting = models.DateField('First Areas Sighting', blank=True, null=True, default=datetime.datetime.now())
AreaSuccessType = models.OneToOneField(SuccessType, on_delete=models.CASCADE,
verbose_name='Area Establishement/Success', blank=True, null=True)
Area_citation = models.ForeignKey(biblio, verbose_name=u"Area first citation", on_delete=models.CASCADE, null=True,
blank=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='%(class)s_requests_created',
default='')
created_at = models.DateField('date of Edition', blank=True, null=True, default=datetime.datetime.now())
updated_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='%(class)s_requests_updated',
default='')
updated_at = models.DateField('date of updating', blank=True, null=True, default=datetime.datetime.now())
notes = models.TextField(verbose_name='Notes', blank=True, null=True)
dverification = StateField(verbose_name='Validated ')
def __str__(self): # __unicode__ on Python 2
return self.alien.SpeciesName
class AliensFilter(django_filters.FilterSet):
country = filters.ModelChoiceFilter(label='Country', queryset=Country.objects.all())
msfd = filters.ModelChoiceFilter(label='MSF/EcAp Subregions', queryset=MSFD.objects.all())
regseas = filters.ModelChoiceFilter(label='Regional Seas', queryset=regionalseas.objects.all())
vector = filters.ModelChoiceFilter(label='Vectors/Pathway', queryset=vectors.objects.all())
Species = filters.ModelChoiceFilter(label='Species Name', queryset=Taxonomy.objects.all())
class Meta:
model = Aliens
fields = (
'Species', 'group', 'origin', 'firstsight', 'status', 'vector', 'country', 'msfd', 'regseas')
def search(request):
Aliens_list = Aliens.objects.all().select_related('origin', 'status', 'group', 'Taxonomy')
aliens_filter = AliensFilter(request.GET, queryset=Aliens_list)
# return render(request, 'mamias/list.html', {'filter': aliens_filter})
return render(request, 'mamias/list2.html', {'filter': aliens_filter})
How could I filter based on country for example?
There is no direct relationship between the Aliean and Country models. You would need to instead filter by country through the distributions relationship.
from django_filters import FilterSet, filters
class AlienFilter(FilterSet):
country = filters.ModelChoiceFilter(
field_name='distributions__country',
queryset=Country.objects.all(),
)

Categories

Resources