[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#824912: tracker.d.o: add an API for action items



Hi,


Raphael Hertzog <hertzog@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 <pabs@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 <efkin@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 <efkin@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 <efkin@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 <pabs@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


Reply to: