Repository: ansible/awx

Issue:
Demo Project cannot be deleted. Official Docker images - 1.0.4.97
##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!-- Pick the area of AWX for this issue, you can have multiple, delete the rest: -->
 - API
 - UI

##### SUMMARY
<!-- Briefly describe the problem. -->
Demo project can not be deleted from Projects on fresh deploy of AWX  1.0.4.97 from Docker hub official images.

Logs from awx_web container:
https://pastebin.com/9QDS84Sf


##### ENVIRONMENT
* AWX version: 1.0.4.97
* AWX install method: docker linux
* Operating System: Docker

##### STEPS TO REPRODUCE

<!-- For bugs, please show exactly how to reproduce the problem. For new
features, show how the feature would be used.  -->

1. run awx stack on version 1.0.4.97
2. try to delete demo project from projects
3. Error shows up ( Call to /api/v2/projects/4/ failed. DELETE returned status: 500 A server error has occurred. ) 
4. more logs in awx_web



Discussion:
Same issue in AWX 1.0.4.96
Looks like one of the model classes didn't receive the new mixin `RelatedJobsMixin`

Resolving patch:
diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py
--- a/awx/main/models/jobs.py
+++ b/awx/main/models/jobs.py
@@ -456,7 +456,7 @@ def notification_templates(self):
     RelatedJobsMixin
     '''
     def _get_active_jobs(self):
-        return Job.objects.filter(status__in=ACTIVE_STATES)
+        return Job.objects.filter(status__in=ACTIVE_STATES, job_template=self)
 
 
 class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskManagerJobMixin):
diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py
--- a/awx/main/models/projects.py
+++ b/awx/main/models/projects.py
@@ -25,7 +25,11 @@
     NotificationTemplate,
     JobNotificationMixin,
 )
-from awx.main.models.unified_jobs import * # noqa
+from awx.main.models.unified_jobs import (
+    UnifiedJob,
+    UnifiedJobTemplate,
+    ACTIVE_STATES,
+)
 from awx.main.models.mixins import (
     ResourceMixin,
     TaskManagerProjectUpdateMixin,
@@ -230,7 +234,7 @@ def get_lock_file(self):
         return proj_path + '.lock'
 
 
-class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEnvMixin):
+class Project(UnifiedJobTemplate, ProjectOptions, ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin):
     '''
     A project represents a playbook git repo that can access a set of inventories
     '''
@@ -447,8 +451,21 @@ def notification_templates(self):
     def get_absolute_url(self, request=None):
         return reverse('api:project_detail', kwargs={'pk': self.pk}, request=request)
 
+    '''
+    RelatedJobsMixin
+    '''
+    def _get_active_jobs(self):
+        return UnifiedJob.objects.non_polymorphic().filter(
+            models.Q(status__in=ACTIVE_STATES) &
+            (
+                models.Q(Job___project=self) |
+                models.Q(ProjectUpdate___project=self)
+            )
+        )
+
 
-class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManagerProjectUpdateMixin, RelatedJobsMixin):
+
+class ProjectUpdate(UnifiedJob, ProjectOptions, JobNotificationMixin, TaskManagerProjectUpdateMixin):
     '''
     Internal job for tracking project updates from SCM.
     '''
@@ -563,15 +580,4 @@ def preferred_instance_groups(self):
             return self.global_instance_groups
         return selected_groups
 
-    '''
-    RelatedJobsMixin
-    '''
-    def _get_active_jobs(self):
-        return UnifiedJob.objects.non_polymorphic().filter(
-            Q(status__in=ACTIVE_STATES) &
-            (
-                Q(Job___project=self) |
-                Q(ProjectUpdate___project=self)
-            )
-        )
 
diff --git a/awx/main/models/workflow.py b/awx/main/models/workflow.py
--- a/awx/main/models/workflow.py
+++ b/awx/main/models/workflow.py
@@ -415,7 +415,7 @@ def node_prompts_rejected(self):
     RelatedJobsMixin
     '''
     def _get_active_jobs(self):
-        return WorkflowJob.objects.filter(status__in=ACTIVE_STATES)
+        return WorkflowJob.objects.filter(status__in=ACTIVE_STATES, workflow_job_template=self)
 
 
 class WorkflowJob(UnifiedJob, WorkflowJobOptions, SurveyJobMixin, JobNotificationMixin):


Test patch:
diff --git a/awx/main/tests/functional/test_projects.py b/awx/main/tests/functional/test_projects.py
--- a/awx/main/tests/functional/test_projects.py
+++ b/awx/main/tests/functional/test_projects.py
@@ -251,3 +251,10 @@ def test_project_unique_together_with_org(organization):
         proj2.validate_unique()
     proj2 = Project(name='foo', organization=None)
     proj2.validate_unique()
+
+
+@pytest.mark.django_db
+def test_project_delete(delete, organization, admin_user):
+    proj = Project(name='foo', organization=organization)
+    proj.save()
+    delete(reverse('api:project_detail', kwargs={'pk':proj.id,}), admin_user)