For AC-331. Update queries to use select_related and prefetch_related to avoid duplicate queries and improve performance. Add all_groups and groups items to summary_fields for hosts.

This commit is contained in:
Chris Church 2013-08-08 17:44:48 -04:00
parent 30d2a4f5c9
commit bd5e9e2b6e
3 changed files with 31 additions and 5 deletions

View File

@ -217,6 +217,7 @@ class OrganizationAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.distinct()
qs = qs.select_related('created_by')
if self.user.is_superuser:
return qs
return qs.filter(Q(admins__in=[self.user]) | Q(users__in=[self.user]))
@ -249,6 +250,7 @@ class InventoryAccess(BaseAccess):
def get_queryset(self, allowed=None):
allowed = allowed or PERMISSION_TYPES_ALLOWING_INVENTORY_READ
qs = Inventory.objects.filter(active=True).distinct()
qs = qs.select_related('created_by', 'organization')
if self.user.is_superuser:
return qs
admin_of = qs.filter(organization__admins__in=[self.user]).distinct()
@ -318,6 +320,9 @@ class HostAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.filter(active=True).distinct()
qs = qs.select_related('created_by', 'inventory', 'last_job',
'last_job_host_summary')
qs = qs.prefetch_related('groups')
inventories_qs = self.user.get_queryset(Inventory)
return qs.filter(inventory__in=inventories_qs)
@ -378,6 +383,8 @@ class GroupAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.filter(active=True).distinct()
qs = qs.select_related('created_by', 'inventory')
qs = qs.prefetch_related('parents', 'children')
inventories_qs = self.user.get_queryset(Inventory)
return qs.filter(inventory__in=inventories_qs)
@ -440,6 +447,7 @@ class CredentialAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.filter(active=True).distinct()
qs = qs.select_related('created_by', 'user', 'team')
if self.user.is_superuser:
return qs
orgs_as_admin = self.user.admin_of_organizations.all()
@ -509,6 +517,7 @@ class TeamAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.filter(active=True).distinct()
qs = qs.select_related('created_by', 'organization')
if self.user.is_superuser:
return qs
return qs.filter(
@ -560,6 +569,7 @@ class ProjectAccess(BaseAccess):
def get_queryset(self):
qs = Project.objects.filter(active=True).distinct()
qs = qs.select_related('created_by')
if self.user.is_superuser:
return qs
allowed = [PERM_INVENTORY_DEPLOY, PERM_INVENTORY_CHECK]
@ -609,6 +619,8 @@ class PermissionAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.filter(active=True).distinct()
qs = qs.select_related('created_by', 'user', 'team', 'inventory',
'project')
if self.user.is_superuser:
return qs
orgs_as_admin = self.user.admin_of_organizations.all()
@ -699,6 +711,8 @@ class JobTemplateAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.filter(active=True).distinct()
qs = qs.select_related('created_by', 'inventory', 'project',
'credential')
if self.user.is_superuser:
return qs
credential_qs = self.user.get_queryset(Credential)
@ -801,6 +815,8 @@ class JobAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.filter(active=True).distinct()
qs = qs.select_related('created_by', 'job_template', 'inventory',
'project', 'credential')
if self.user.is_superuser:
return qs
credential_qs = self.user.get_queryset(Credential)
@ -870,6 +886,7 @@ class JobHostSummaryAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.distinct()
qs = qs.select_related('created_by', 'job', 'host')
if self.user.is_superuser:
return qs
job_qs = self.user.get_queryset(Job)
@ -894,6 +911,8 @@ class JobEventAccess(BaseAccess):
def get_queryset(self):
qs = self.model.objects.distinct()
qs = qs.select_related('created_by', 'job', 'host', 'parent')
qs = qs.prefetch_related('hosts', 'children')
# Filter certain "internal" events generating by async polling.
qs = qs.exclude(event__in=('runner_on_ok', 'runner_on_failed'),

View File

@ -51,6 +51,9 @@ class GenericAPIView(generics.GenericAPIView, APIView):
# model = ModelClass
# serializer_class = SerializerClass
def get_queryset(self):
return self.request.user.get_queryset(self.model)
def get_description_context(self):
# Set instance attributes needed to get serializer metadata.
if not hasattr(self, 'request'):
@ -80,9 +83,6 @@ class ListAPIView(generics.ListAPIView, GenericAPIView):
})
return d
def get_queryset(self):
return self.request.user.get_queryset(self.model)
class ListCreateAPIView(ListAPIView, generics.ListCreateAPIView):
# Base class for a list view that allows creating new objects.

View File

@ -27,7 +27,7 @@ BASE_FIELDS = ('id', 'url', 'related', 'summary_fields', 'created', 'name',
# objects that if found we should add summary info for them
SUMMARIZABLE_FKS = (
'organization', 'host', 'group', 'inventory', 'project', 'team', 'job',
'job_template', 'credential', 'permission', 'user',
'job_template', 'credential', 'permission', 'user', 'last_job',
)
# fields that should be summarized regardless of object type
SUMMARIZABLE_FIELDS = (
@ -244,7 +244,8 @@ class HostSerializer(BaseSerializerWithVariables):
class Meta:
model = Host
fields = BASE_FIELDS + ('inventory', 'variables', 'has_active_failures')
fields = BASE_FIELDS + ('inventory', 'variables', 'has_active_failures',
'last_job', 'last_job_host_summary')
def get_related(self, obj):
res = super(HostSerializer, self).get_related(obj)
@ -262,6 +263,12 @@ class HostSerializer(BaseSerializerWithVariables):
res['last_job_host_summary'] = reverse('main:job_host_summary_detail', args=(obj.last_job_host_summary.pk,))
return res
def get_summary_fields(self, obj):
d = super(HostSerializer, self).get_summary_fields(obj)
d['all_groups'] = [{'id': g.id, 'name': g.name} for g in obj.all_groups.all()]
d['groups'] = [{'id': g.id, 'name': g.name} for g in obj.groups.all()]
return d
class GroupSerializer(BaseSerializerWithVariables):
class Meta: