Repository: kartoza/prj.app

Issue:
Download QGIS 3.2.0 as rst broken/raises 500 error
If you download rst for QGIS 3.2.0 you get a 500.

If I do the same in my dev env, I see:

```
MultipleObjectsReturned at /en/qgis/version/3.2.0/download/
get() returned more than one Version -- it returned 2!
```
And furter in the debug info:

![selection_476](https://user-images.githubusercontent.com/731673/40545312-abdac098-602b-11e8-838c-f14aebd72b98.png)

which to me looks like there is not enough info to select ONLY QGIS (as InaSAFE 3.2.0 is also coming though)?

Any pointers to fix this are appreciated



Discussion:
@ann26 please make the logic work on both project and version so that we don't get version conflicts.
See also http://sentry.kartoza.com/sentry/projecta/issues/236/

Resolving patch:
diff --git a/django_project/changes/views/version.py b/django_project/changes/views/version.py
--- a/django_project/changes/views/version.py
+++ b/django_project/changes/views/version.py
@@ -611,6 +611,34 @@ def _prepare_zip_archive(self, document, version_obj):
 
         return temp_path
 
+    def get_queryset(self):
+        """Get the queryset for download.
+
+        This will search a specific version within a project.
+        Thus it will not raise duplicates when there is
+        another same version name from another project.
+
+        :returns: A queryset which is filtered to only show Version
+        from specific project.
+        :rtype: QuerySet
+        :raises: Http404
+        """
+
+        if self.queryset is None:
+            project_slug = self.kwargs.get('project_slug', None)
+            slug = self.kwargs.get('slug', None)
+            if project_slug and slug:
+                try:
+                    project = Project.objects.get(slug=project_slug)
+                    queryset = Version.objects.filter(
+                        project=project, slug=slug)
+                    return queryset
+                except (Project.DoesNotExist, Version.DoesNotExist):
+                    raise Http404('Sorry! We could not find your version!')
+            else:
+                raise Http404('Sorry! We could not find your version!')
+        return self.queryset
+
 
 class VersionDownloadGnu(VersionMixin, DetailView):
     """A tabular list style view for a Version."""


Test patch:
diff --git a/django_project/changes/tests/test_views.py b/django_project/changes/tests/test_views.py
--- a/django_project/changes/tests/test_views.py
+++ b/django_project/changes/tests/test_views.py
@@ -2,10 +2,9 @@
 # flake8: noqa
 
 import json
-from django.utils.datastructures import MultiValueDict
-from django.utils.http import urlencode
-
+from mock import mock
 from django.core.urlresolvers import reverse
+from django.http import HttpResponse
 from django.test import TestCase, override_settings
 from django.test.client import Client
 from base.tests.model_factories import ProjectF
@@ -490,6 +489,10 @@ def test_EntryDelete_no_login(self):
         self.assertEqual(response.status_code, 302)
 
 
+def mocked_convert(*args, **kwargs):
+    return 'Mock document'
+
+
 class TestVersionViews(TestCase):
 
     """Tests that Version views work."""
@@ -730,6 +733,52 @@ def test_VersionDelete_no_login(self):
         }))
         self.assertEqual(response.status_code, 302)
 
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    def test_VersionDownload_no_login(self):
+        other_project = ProjectF.create(name='testproject2')
+        version_same_name_from_other_project = VersionF.create(
+            project=other_project,
+            name='1.0.1'
+        )
+        response = self.client.get(reverse('version-download', kwargs={
+            'slug': version_same_name_from_other_project.slug,
+            'project_slug': other_project.slug
+        }))
+        self.assertEqual(response.status_code, 302)
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    @mock.patch('pypandoc.convert', side_effect=mocked_convert)
+    def test_VersionDownload_login(self, mocked_convert):
+        self.client.login(username='timlinux', password='password')
+        other_project = ProjectF.create(name='testproject2')
+        version_same_name_from_other_project = VersionF.create(
+            project=other_project,
+            name='1.0.1'
+        )
+        response = self.client.get(reverse('version-download', kwargs={
+            'slug': version_same_name_from_other_project.slug,
+            'project_slug': other_project.slug
+        }))
+        self.assertEqual(
+            response.context[0].get('version'),
+            version_same_name_from_other_project)
+        self.assertEqual(response.status_code, 200)
+
+    @override_settings(VALID_DOMAIN=['testserver', ])
+    @mock.patch('pypandoc.convert', side_effect=mocked_convert)
+    def test_VersionDownload_login_notfound(self, mocked_convert):
+        self.client.login(username='timlinux', password='password')
+        response = self.client.get(reverse('version-download', kwargs={
+            'slug': 'not-found',
+            'project_slug': self.project.slug
+        }))
+        self.assertEqual(response.status_code, 404)
+        response = self.client.get(reverse('version-download', kwargs={
+            'slug': 'not-found',
+            'project_slug': None
+        }))
+        self.assertEqual(response.status_code, 404)
+
 
 class TestVersionViewsWithAnonymousUserForCRUD(TestCase):
     """