Hi,
Raphael Hertzog <hert...@debian.org> writes: > Can you say what minimal version? We have 3.4 in testing/unstable but > 2.4.3 in jessie. > I'm fine with requiring 3.4 although it has not yet been backported > for jessie. That will have to happen if we want to push this new module into > production. I encountered this issue when implementing pagination for json. Basically it works differently between 2.4.3 and 3.4. I decided to keep DRF 2.4.3. But i'm happy to change it if you prefer. I have no big reasons to prefer one or the other one, so i fallback on the fact that if it's on stable i go for it. > Reported-by: Paul Wise <p...@debian.org> Done. >> --- >> distro_tracker/api/tests.py | 95 >> +++++++++++++++++++++++++++++++++++++++++- >> distro_tracker/api/views.py | 42 ++++++++++++++++++- >> distro_tracker/project/urls.py | 8 ++++ > > Please don't modify project/urls.py directly. Use api/tracker_urls.py > instead (see derivative/tracker_urls.py as an example). > Done. Also realized that i forgot to include a file -_- . > I have not reviewed the rest yet. Btw sorry for the short description of my last email, i try to compensate it now: ``` $ curl -H 'Accept: application/json; indent=4' "http://tracker.dev:8000/api/v1/action-items" { "count": 21324, "next": "http://tracker.dev:8000/api/v1/action-items?page=2", "previous": null, "results": [ { "id": 1, "package_name": "consolation", "item_type_name": "debian-std-ver-outdated", "short_description": "Standards version of the package is outdated.", "severity": 0, "created_timestamp": "2016-12-12T11:20:47.064Z", "last_updated_timestamp": "2016-12-12T11:20:47.064Z", "extra_data": { "lastsv": "3.9.8", "standards_version": "3.9.7", "severely_outdated": false } }, ... ], } ``` ``` $ curl -H 'Accept: application/json; indent=4' "http://tracker.dev:8000/api/v1/action-items/2/" { "id": 2, "package_name": "gnokii", "item_type_name": "debian-std-ver-outdated", "short_description": "Standards version of the package is outdated.", "severity": 0, "created_timestamp": "2016-12-12T11:20:47.247Z", "last_updated_timestamp": "2016-12-12T11:20:47.247Z", "extra_data": { "lastsv": "3.9.8", "standards_version": "3.9.2", "severely_outdated": false } } ``` > Cheers, > -- > Raphaël Hertzog ◈ Debian Developer > > Support Debian LTS: http://www.freexian.com/services/debian-lts.html > Learn to master Debian: http://debian-handbook.info/get/ cheers, -- efkin.
>From 0790248b1c2bca5e6817476d1a6bfb35345b553d Mon Sep 17 00:00:00 2001 From: efkin <ef...@riseup.net> Date: Wed, 14 Dec 2016 13:04:52 +0100 Subject: [PATCH 1/3] Include rest_framework dependency --- distro_tracker/project/settings/defaults.py | 1 + docs/setup/setup.rst | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/distro_tracker/project/settings/defaults.py b/distro_tracker/project/settings/defaults.py index ad7defd..0f27309 100644 --- a/distro_tracker/project/settings/defaults.py +++ b/distro_tracker/project/settings/defaults.py @@ -249,6 +249,7 @@ INSTALLED_APPS = ( 'django.contrib.staticfiles', 'django.contrib.admin', 'django_email_accounts', + 'rest_framework', 'distro_tracker.html', 'distro_tracker.core', 'distro_tracker.accounts', diff --git a/docs/setup/setup.rst b/docs/setup/setup.rst index dad9ac0..0cd5508 100644 --- a/docs/setup/setup.rst +++ b/docs/setup/setup.rst @@ -15,6 +15,7 @@ Distro Tracker currently depends on the following Debian packages: - python-django-jsonfield (>= 1.0.0) - python-django-debug-toolbar (in development mode only) - python-django-captcha (optional) +- python-djangorestframework (= 2.4.3) - python-debian - python-apt - python-gpgme @@ -35,7 +36,7 @@ For Python2.7, the following additional packages are required: Here is the list of required packages for development on Debian Jessie:: - $ sudo apt install python-django python-requests python-django-jsonfield python-django-debug-toolbar python-debian python-apt python-gpgme python-yaml python-bs4 python-soappy python-ldap python-pyinotify python-tox python-mock python-lzma python-selenium python3-django python3-requests python3-django-jsonfield python3-django-debug-toolbar python3-debian python3-apt python3-gpgme python3-yaml python3-bs4 python3-pyinotify python3-selenium chromium chromedriver + $ sudo apt install python-django python-requests python-django-jsonfield python-django-debug-toolbar python-debian python-apt python-gpgme python-yaml python-bs4 python-soappy python-ldap python-pyinotify python-tox python-mock python-lzma python-selenium python-djangorestframework python3-django python3-requests python3-django-jsonfield python3-djangorestframework python3-django-debug-toolbar python3-debian python3-apt python3-gpgme python3-yaml python3-bs4 python3-pyinotify python3-selenium chromium chromedriver .. _database_setup: -- 2.1.4
>From e6428acf8d29b7f1ab6af6e199d64db186f2815c Mon Sep 17 00:00:00 2001 From: efkin <ef...@riseup.net> Date: Wed, 14 Dec 2016 13:14:35 +0100 Subject: [PATCH 2/3] Create distro_tracker submodule for API development --- distro_tracker/api/__init__.py | 0 distro_tracker/api/tests.py | 3 +++ distro_tracker/api/views.py | 3 +++ distro_tracker/project/settings/defaults.py | 1 + 4 files changed, 7 insertions(+) create mode 100644 distro_tracker/api/__init__.py create mode 100644 distro_tracker/api/tests.py create mode 100644 distro_tracker/api/views.py diff --git a/distro_tracker/api/__init__.py b/distro_tracker/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/distro_tracker/api/tests.py b/distro_tracker/api/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/distro_tracker/api/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/distro_tracker/api/views.py b/distro_tracker/api/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/distro_tracker/api/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/distro_tracker/project/settings/defaults.py b/distro_tracker/project/settings/defaults.py index 0f27309..0d42a37 100644 --- a/distro_tracker/project/settings/defaults.py +++ b/distro_tracker/project/settings/defaults.py @@ -250,6 +250,7 @@ INSTALLED_APPS = ( 'django.contrib.admin', 'django_email_accounts', 'rest_framework', + 'distro_tracker.api', 'distro_tracker.html', 'distro_tracker.core', 'distro_tracker.accounts', -- 2.1.4
>From 1131ed132b4b22a3e054a23439644512ff2e452e Mon Sep 17 00:00:00 2001 From: efkin <ef...@riseup.net> Date: Wed, 14 Dec 2016 18:45:09 +0100 Subject: [PATCH 3/3] Create basic API list/detail endpoint for ActionItem model instances Reported_by: Paul Wise <p...@debian.org> --- distro_tracker/api/serializers.py | 37 +++++++++++++ distro_tracker/api/tests.py | 105 ++++++++++++++++++++++++++++++++++++- distro_tracker/api/tracker_urls.py | 29 ++++++++++ distro_tracker/api/views.py | 52 +++++++++++++++++- 4 files changed, 219 insertions(+), 4 deletions(-) create mode 100644 distro_tracker/api/serializers.py create mode 100644 distro_tracker/api/tracker_urls.py diff --git a/distro_tracker/api/serializers.py b/distro_tracker/api/serializers.py new file mode 100644 index 0000000..fab1c42 --- /dev/null +++ b/distro_tracker/api/serializers.py @@ -0,0 +1,37 @@ +# Copyright 2014-2016 The Distro Tracker Developers +# See the COPYRIGHT file at the top-level directory of this distribution and +# at https://deb.li/DTAuthors +# +# This file is part of Distro Tracker. It is subject to the license terms +# in the LICENSE file found in the top-level directory of this +# distribution and at https://deb.li/DTLicense. No part of Distro Tracker, +# including this file, may be copied, modified, propagated, or distributed +# except according to the terms contained in the LICENSE file. + +from rest_framework import serializers + +from distro_tracker.core.models import ActionItem +from distro_tracker.core.models import PackageName + + +class ActionItemSerializer(serializers.ModelSerializer): + + package_name = serializers.RelatedField(source='package', read_only=True) + item_type_name = serializers.RelatedField(source='item_type', read_only=True) + + class Meta: + model = ActionItem + fields = ( + 'id', + 'package_name', + 'item_type_name', + 'short_description', + 'severity', + 'created_timestamp', + 'last_updated_timestamp', + 'extra_data', + ) + + + + diff --git a/distro_tracker/api/tests.py b/distro_tracker/api/tests.py index 7ce503c..255bbb8 100644 --- a/distro_tracker/api/tests.py +++ b/distro_tracker/api/tests.py @@ -1,3 +1,104 @@ -from django.test import TestCase +# Copyright 2014-2016 The Distro Tracker Developers +# See the COPYRIGHT file at the top-level directory of this distribution and +# at https://deb.li/DTAuthors +# +# This file is part of Distro Tracker. It is subject to the license terms +# in the LICENSE file found in the top-level directory of this +# distribution and at https://deb.li/DTLicense. No part of Distro Tracker, +# including this file, may be copied, modified, propagated, or distributed +# except according to the terms contained in the LICENSE file. -# Create your tests here. +from django.core.urlresolvers import reverse + +from rest_framework import status +from rest_framework.test import APITestCase + +from distro_tracker.core.models import ActionItem +from distro_tracker.core.models import ActionItemType +from distro_tracker.core.models import SourcePackageName + + +class ActionItemListAPIViewTest(APITestCase): + """ + Test for the :class:`distro_tracker.api.views.ActionItemListAPIView`. + """ + + def setUp(self): + self.url = reverse('dtracker-api-v1-action-items') + + def test_empty_list(self): + """ + Test when the queryset is empty. + """ + response = self.client.get(self.url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + 0, + response.data['count'], + ) + + def test_account_item(self): + """ + Test with actual content. + """ + package = SourcePackageName.objects.create(name='dummy-package') + action_type = ActionItemType.objects.create( + type_name='test', + full_description_template='action-item-test.html', + ) + action_item = ActionItem.objects.create( + package=package, + item_type=action_type, + short_description="Short description of item", + ) + response = self.client.get(self.url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + 1, + response.data['count'], + ) + result = response.data['results'][0] + self.assertEqual( + 'dummy-package', + result['package_name'], + ) + + +class ActionItemDetailAPIViewTest(APITestCase): + """ + Test for the :class:`distro_tracker.api.views.ActionItemDetailAPIView`. + """ + + def setUp(self): + self.url = reverse('dtracker-api-v1-action-items', kwargs={'pk':1}) + + def test_404_on_non_existing_pk(self): + """ + Test when the pk does not return any instance. + """ + response = self.client.get(self.url) + + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_existing_instance(self): + """ + Test when the pk does return an actual instance. + """ + package = SourcePackageName.objects.create(name='dummy-package') + action_type = ActionItemType.objects.create( + type_name='test', + full_description_template='action-item-test.html', + ) + action_item = ActionItem.objects.create( + package=package, + item_type=action_type, + short_description="Short description of item", + ) + response = self.client.get(self.url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + 'dummy-package', + response.data['package_name'], + ) + + diff --git a/distro_tracker/api/tracker_urls.py b/distro_tracker/api/tracker_urls.py new file mode 100644 index 0000000..f7a15ab --- /dev/null +++ b/distro_tracker/api/tracker_urls.py @@ -0,0 +1,29 @@ +# Copyright 2014-2016 The Distro Tracker Developers +# See the COPYRIGHT file at the top-level directory of this distribution and +# at https://deb.li/DTAuthors +# +# This file is part of Distro Tracker. It is subject to the license terms +# in the LICENSE file found in the top-level directory of this +# distribution and at https://deb.li/DTLicense. No part of Distro Tracker, +# including this file, may be copied, modified, propagated, or distributed +# except according to the terms contained in the LICENSE file. + +from django.conf.urls import url + +from .views import ActionItemListAPIView +from .views import ActionItemDetailAPIView + + +urlpatterns = [ + url(r'^api/v1/action-items/?$', + ActionItemListAPIView.as_view(), + name='dtracker-api-v1-action-items'), + url(r'^api/v1/action-items/(?P<pk>[0-9]+)/?$', + ActionItemDetailAPIView.as_view(), + name='dtracker-api-v1-action-items'), +] + + +frontpagelinks = [ + ('dtracker-api-v1-action-items', 'GET API endpoint for ActionItem model instances'), +] diff --git a/distro_tracker/api/views.py b/distro_tracker/api/views.py index 91ea44a..c362258 100644 --- a/distro_tracker/api/views.py +++ b/distro_tracker/api/views.py @@ -1,3 +1,51 @@ -from django.shortcuts import render +# Copyright 2014-2016 The Distro Tracker Developers +# See the COPYRIGHT file at the top-level directory of this distribution and +# at https://deb.li/DTAuthors +# +# This file is part of Distro Tracker. It is subject to the license terms +# in the LICENSE file found in the top-level directory of this +# distribution and at https://deb.li/DTLicense. No part of Distro Tracker, +# including this file, may be copied, modified, propagated, or distributed +# except according to the terms contained in the LICENSE file. -# Create your views here. +from django.http import Http404 + +from rest_framework import status +from rest_framework import generics +from rest_framework.response import Response + +from distro_tracker.api.serializers import ActionItemSerializer +from distro_tracker.core.models import ActionItem + + +class ActionItemListAPIView(generics.ListAPIView): + """ + List all ActionItem instances. + """ + + serializer_class = ActionItemSerializer + + # this next block assume DRF 2.X (as in debian stable) + # and assume pagination will break with DRF 3.X + paginate_by = 100 + paginate_by_param = 'page_size' + max_paginate_by = 500 + + def get_queryset(self): + queryset = ActionItem.objects.all() + package_name = self.request.GET.get('package_name', None) + if package_name is not None: + queryset = queryset.filter(package__name=package_name) + return queryset + + +class ActionItemDetailAPIView(generics.RetrieveAPIView): + """ + Retrieve an ActionItem instance. + """ + + queryset = ActionItem.objects.all() + serializer_class = ActionItemSerializer + + + -- 2.1.4