Skip to content

Add a mixin class for dashboard views on models with project relations #2353

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 9, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions readthedocs/projects/views/mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Mixin classes for project views"""

from django.shortcuts import get_object_or_404

from readthedocs.projects.models import Project


class ProjectRelationMixin(object):

"""Mixin class for constructing model views for project dashboard

This mixin class is used for model views on models that have a relation
to the :py:cls:`Project` model.

:cvar project_lookup_url_kwarg: URL kwarg to use in project lookup
:cvar project_lookup_field: Query field for project relation
:cvar project_context_object_name: Context object name for project
"""

project_lookup_url_kwarg = 'project_slug'
project_lookup_field = 'project'
project_context_object_name = 'project'

def get_project_queryset(self):
return Project.objects.for_admin_user(user=self.request.user)

def get_project(self):
if self.project_lookup_url_kwarg not in self.kwargs:
return None
return get_object_or_404(
self.get_project_queryset(),
slug=self.kwargs[self.project_lookup_url_kwarg]
)

def get_queryset(self):
return self.model.objects.filter(
**{self.project_lookup_field: self.get_project()}
)

def get_context_data(self, **kwargs):
context = super(ProjectRelationMixin, self).get_context_data(**kwargs)
context[self.project_context_object_name] = self.get_project()
return context
27 changes: 26 additions & 1 deletion readthedocs/rtd_tests/tests/test_project_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
from django.test import TestCase
from django.contrib.auth.models import User
from django.contrib.messages import constants as message_const
from django.views.generic.base import ContextMixin
from django_dynamic_fixture import get
from django_dynamic_fixture import new

from readthedocs.core.models import UserProfile
from readthedocs.rtd_tests.base import (WizardTestCase, MockBuildTestCase,
RequestFactoryTestMixin)
from readthedocs.projects.exceptions import ProjectSpamError
from readthedocs.projects.models import Project
from readthedocs.projects.models import Project, Domain
from readthedocs.projects.views.private import ImportWizardView
from readthedocs.projects.views.mixins import ProjectRelationMixin


@patch('readthedocs.projects.views.private.trigger_build', lambda x, basic: None)
Expand Down Expand Up @@ -330,3 +332,26 @@ def test_delete_project(self):
remove_dir.apply_async.assert_called_with(
queue='celery',
args=[project.doc_path])


class TestPrivateMixins(MockBuildTestCase):

def setUp(self):
self.project = get(Project, slug='kong')
self.domain = get(Domain, project=self.project)

def test_project_relation(self):
"""Class using project relation mixin class"""

class FoobarView(ProjectRelationMixin, ContextMixin):
model = Domain

def get_project_queryset(self):
# Don't test this as a view with a request.user
return Project.objects.all()

view = FoobarView()
view.kwargs = {'project_slug': 'kong'}
self.assertEqual(view.get_project(), self.project)
self.assertEqual(view.get_queryset().first(), self.domain)
self.assertEqual(view.get_context_data()['project'], self.project)