[Python-modules-commits] [djangorestframework-gis] 01/05: Import djangorestframework-gis_0.9.5.orig.tar.gz

Brian May bam at moszumanska.debian.org
Fri Oct 23 08:54:21 UTC 2015


This is an automated email from the git hooks/post-receive script.

bam pushed a commit to branch master
in repository djangorestframework-gis.

commit 2e7c34d49cd13f24cc87100cfbd73ffbbbbdc7bb
Author: Brian May <bam at debian.org>
Date:   Fri Oct 23 19:05:33 2015 +1100

    Import djangorestframework-gis_0.9.5.orig.tar.gz
---
 .coveragerc                                        |   3 +
 .gitignore                                         |   4 +-
 .travis.yml                                        |  20 +-
 AUTHORS                                            |   1 +
 CHANGES.rst                                        | 104 ++++++++
 CONTRIBUTING.rst                                   |   5 +
 LICENSE                                            |   0
 MANIFEST.in                                        |   2 +-
 README.rst                                         | 263 ++++++++++++++++++---
 performance_tests.rst                              |  33 +++
 requirements-test.txt                              |   3 +-
 requirements.txt                                   |   2 +-
 rest_framework_gis/__init__.py                     |  29 ++-
 rest_framework_gis/apps.py                         |  38 +++
 rest_framework_gis/fields.py                       |  63 +++--
 rest_framework_gis/filters.py                      |  64 ++---
 rest_framework_gis/filterset.py                    |   5 +-
 rest_framework_gis/pagination.py                   |  20 ++
 rest_framework_gis/parsers.py                      |   1 -
 rest_framework_gis/serializers.py                  | 189 +++++++++------
 rest_framework_gis/tilenames.py                    |  22 +-
 rest_framework_gis/utils.py                        |   5 +
 runtests.py                                        |   4 +-
 setup.cfg                                          |   2 +
 setup.py                                           |   6 +-
 tests/__init__.py                                  |   0
 tests/django_restframework_gis_tests/admin.py      |   0
 tests/django_restframework_gis_tests/models.py     |  34 ++-
 .../django_restframework_gis_tests/serializers.py  |  83 +++++--
 tests/django_restframework_gis_tests/test_bbox.py  |  81 +++++++
 .../django_restframework_gis_tests/test_filters.py |  79 +++++--
 .../test_performance.py                            |  46 ++++
 tests/django_restframework_gis_tests/tests.py      | 213 ++++++++++++-----
 tests/django_restframework_gis_tests/urls.py       |  14 +-
 tests/django_restframework_gis_tests/views.py      |  68 +++++-
 tests/local_settings.example.py                    |  16 +-
 tests/settings.py                                  |   7 +
 tests/urls.py                                      |   0
 38 files changed, 1231 insertions(+), 298 deletions(-)

diff --git a/.coveragerc b/.coveragerc
new file mode 100644
index 0000000..2c81a86
--- /dev/null
+++ b/.coveragerc
@@ -0,0 +1,3 @@
+[run]
+omit =
+    /*/__init__.py
diff --git a/.gitignore b/.gitignore
old mode 100755
new mode 100644
index 97501e7..eb5fab7
--- a/.gitignore
+++ b/.gitignore
@@ -8,4 +8,6 @@ tests/static/
 .coverage
 *~
 ._*
-*.DS_Store
\ No newline at end of file
+*.DS_Store
+*.komodoproject
+/htmlcov
diff --git a/.travis.yml b/.travis.yml
old mode 100755
new mode 100644
index 290f598..6bb8d12
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,6 @@
+sudo: false
 language: python
+cache: pip
 
 services:
   - postgresql
@@ -6,39 +8,41 @@ services:
 python:
   - "3.4"
   - "3.3"
+  - "3.2"
   - "2.7"
   - "2.6"
 
 env:
-  - DJANGO="django==1.7.4"
-  - DJANGO="django==1.6.10"
+  - DJANGO="django==1.8.4"
+  - DJANGO="django==1.7.10"
+  - DJANGO="django==1.6.11"
   - DJANGO="django==1.5.12"
 
 matrix:
   exclude:
     - python: "2.6"
-      env: DJANGO="django==1.7.4"
+      env: DJANGO="django==1.7.10"
+    - python: "2.6"
+      env: DJANGO="django==1.8.4"
 
 branches:
   only:
     - master
-    - drf-3.0
 
 # command to install requirements
 install:
   - if [[ $TRAVIS_PYTHON_VERSION == 2.6 ]]; then pip install ordereddict; fi
   - pip install $DJANGO
   - pip install -r requirements-test.txt
-  - python setup.py -q install
+  - python setup.py -q develop
 
 before_script:
   - createdb django_restframework_gis
   - psql -U postgres -d django_restframework_gis -c "CREATE EXTENSION postgis;"
-  - psql -U postgres -d django_restframework_gis -c "CREATE EXTENSION postgis_topology;"
 
 # command to run tests, e.g. python setup.py test
 script:
-  - coverage run --source=rest_framework_gis,django_restframework_gis_tests runtests.py
+  - coverage run --source=rest_framework_gis runtests.py
 
 after_success:
-  coveralls
\ No newline at end of file
+  coveralls
diff --git a/AUTHORS b/AUTHORS
old mode 100755
new mode 100644
index 24fdf54..a4929a4
--- a/AUTHORS
+++ b/AUTHORS
@@ -8,3 +8,4 @@ Contributors
 Christoph Heer      https://github.com/jarus
 Federico Capoano    https://github.com/nemesisdesign/
 Shanto              https://github.com/Shanto
+Eric Theise         https://github.com/erictheise
diff --git a/CHANGES.rst b/CHANGES.rst
new file mode 100644
index 0000000..5b5b178
--- /dev/null
+++ b/CHANGES.rst
@@ -0,0 +1,104 @@
+Changelog
+=========
+
+Version 0.9.5 [2015-10-12]
+--------------------------
+
+- `#71 <https://github.com/djangonauts/django-rest-framework-gis/pull/71>`_: added possibility to override GeoJSON properties in ``GeoFeatureModelSerializer``
+- `52e15a5 <https://github.com/djangonauts/django-rest-framework-gis/commit/52e15a5>`_: Added default ``page_size_query_param`` in ``GeoJsonPagination``
+
+Version 0.9.4 [2015-09-08]
+--------------------------
+
+- `#68 <https://github.com/djangonauts/django-rest-framework-gis/issues/68>`_: ensure not having drf-gis in ``INSTALLED_APPS`` works anyway
+- `#76 <https://github.com/djangonauts/django-rest-framework-gis/issues/76>`_: avoid pickle errors in ``GeoJsonDict``
+- `#75 <https://github.com/djangonauts/django-rest-framework-gis/pull/75>`_: return ``GEOSGeometry`` instead of geojson property
+
+Version 0.9.3 [2015-07-22]
+--------------------------
+
+- `04fd1bf <https://github.com/djangonauts/django-rest-framework-gis/commit/04fd1bf>`_: Added ``GeoJsonPagination``
+- `fe47d86 <https://github.com/djangonauts/django-rest-framework-gis/commit/fe47d86>`_: Improved ``ValidationError`` message of ``GeometryField``
+- `a3ddd3d <https://github.com/djangonauts/django-rest-framework-gis/commit/a3ddd3d>`_: **Improved serialization performance between 25% and 29%**
+- `fb6ed36 <https://github.com/djangonauts/django-rest-framework-gis/commit/fb6ed36>`_: ``GeoModelSerializer`` deprecated because obsolete
+- `#66 <https://github.com/djangonauts/django-rest-framework-gis/pull/66>`_: geometry now allows ``None`` values according to the **GeoJSON spec**
+- `#67 <https://github.com/djangonauts/django-rest-framework-gis/pull/67>`_: discern ``False`` or empty string values from ``None`` in ``GeoFeatureModelSerializer``
+
+Version 0.9.2 [2015-07-15]
+--------------------------
+
+- `#59 <https://github.com/djangonauts/django-rest-framework-gis/pull/59>`_: Added GeometrySerializerMethodField
+- `3fa2354 <https://github.com/djangonauts/django-rest-framework-gis/commit/3fa2354>`_: removed broken/obsolete/untested code
+
+Version 0.9.1 [2015-06-28]
+--------------------------
+
+- `#63 <https://github.com/djangonauts/django-rest-framework-gis/issues/63>`_: added compatibility with python 3.2 and updated compatibility table in README
+- `#60 <https://github.com/djangonauts/django-rest-framework-gis/pull/60>`_: ensure GeoJSON is rendered correctly in browsable API when using python 2
+- `#62 <https://github.com/djangonauts/django-rest-framework-gis/issues/62>`_: updated django-rest-framework requirement to 3.1.3
+
+Version 0.9 [2015-05-31]
+------------------------
+
+- `#55 <https://github.com/djangonauts/django-rest-framework-gis/pull/55>`_: Fixed exception in ``DistanceToPointFilter`` in case of invalid point
+- `#58 <https://github.com/djangonauts/django-rest-framework-gis/pull/58>`_: Fixed handling of ``None`` values in ``GeoFeatureModelSerializer`` to avoid problems with ``FileField`` and ``ImageField``
+- `#57 <https://github.com/djangonauts/django-rest-framework-gis/pull/57>`_: Added support for GeoJSON Bounding Boxes in ``GeoFeatureModelSerializer``
+
+Version 0.8.2 [2015-04-29]
+--------------------------
+
+- `#53 <https://github.com/djangonauts/django-rest-framework-gis/pull/53>`_: Added support for PATCH requests in ``GeoFeatureModelSerializer``
+
+Version 0.8.1 [2015-03-25]
+--------------------------
+
+- Added compatibility with django-rest-framework 3.1.x
+- Added compatibility with django 1.8 (RC1)
+
+Version 0.8 [2015-03-03]
+------------------------
+
+- Added compatibility with django-rest-framework 3.x
+
+Version 0.7 [2014-10-03]
+------------------------
+
+- upgraded development status classifer to Beta
+- avoid empty string in textarea widget if value is None
+- allow field definition in GeoFeatureModelSerializer to be list
+
+Version 0.6 [2014-09-24]
+------------------------
+
+- Added compatibility to django-rest-framework 2.4.3
+
+Version 0.5 [2014-09-07]
+------------------------
+
+- added TMSTileFilter
+- added DistanceToPointFilter
+- renamed InBBOXFilter to InBBoxFilter
+- added compatibility with DRF 2.4.0
+
+Version 0.4 [2014-08-25]
+------------------------
+
+- python3 compatibility
+- improved DRF browsable API HTML widget (textarea instead of text input)
+
+Version 0.3 [2014-07-07]
+------------------------
+
+- added compatibility with DRF 2.3.14
+
+Version 0.2 [2014-03-18]
+------------------------
+
+- geofilter support
+- README in restructured text for pypi
+- updated python package info
+
+Version 0.1 [2013-12-30]
+------------------------
+
+- first release
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
new file mode 100644
index 0000000..eba575c
--- /dev/null
+++ b/CONTRIBUTING.rst
@@ -0,0 +1,5 @@
+Contributing
+============
+
+Thanks for your interest! We love contributions, so please feel free to fix bugs, improve things, provide documentation. Just `follow the
+guidelines <https://github.com/djangonauts/django-rest-framework-gis#contributing>`_ and submit a PR.
diff --git a/LICENSE b/LICENSE
old mode 100755
new mode 100644
diff --git a/MANIFEST.in b/MANIFEST.in
old mode 100755
new mode 100644
index 70f0871..f9e3fb0
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,3 @@
-include AUTHORS LICENSE README.md
+include AUTHORS LICENSE README.rst requirements.txt
 recursive-include tests *
 recursive-exclude * *.pyc *.swp
diff --git a/README.rst b/README.rst
old mode 100755
new mode 100644
index fe3986f..e0a40b1
--- a/README.rst
+++ b/README.rst
@@ -1,7 +1,7 @@
 django-rest-framework-gis
 =========================
 
-|Build Status| |Coverage Status| |Code Health| |Requirements Status| |PyPI version| |PyPI downloads|
+|Build Status| |Coverage Status| |Requirements Status| |PyPI version| |PyPI downloads|
 
 Geographic add-ons for Django Rest Framework - `Mailing
 List <http://bit.ly/1M4sLTp>`__.
@@ -20,33 +20,73 @@ Install development version
 
     pip install https://github.com/djangonauts/django-rest-framework-gis/tarball/master
 
+Setup
+-----
+
+Add ``rest_framework_gis`` in ``settings.INSTALLED_APPS``, after ``rest_framework``:
+
+.. code-block:: python
+
+    INSTALLED_APPS = [
+        # ...
+        'rest_framework',
+        'rest_framework_gis',
+        # ...
+    ]
+
 Compatibility with DRF, Django and Python
 -----------------------------------------
 
-===============  ============================ ==================== ==================
+===============  ============================ ==================== ==================================
 DRF-gis version  DRF version                  Django version       Python version
-**0.8**          **3.0.4**                    **1.5.x** to **1.7** **2.6** to **3.4**
-**0.7**          **2.4.3**                    **1.5.x** to **1.7** **2.6** to **3.4**
-**0.6**          **2.4.3**                    **1.5.x** to **1.7** **2.6** to **3.4**
-**0.5**          from **2.3.14** to **2.4.2** **1.5.x** to **1.7** **2.6** to **3.4**
-**0.4**          from **2.3.14** to **2.4.2** **1.5.x** to **1.7** **2.6** to **3.4**
+**0.9.5**        **3.1.X** to **3.2.X**       **1.5.x** to **1.8** **2.6** to **3.4**
+**0.9.4**        **3.1.X** to **3.2.X**       **1.5.x** to **1.8** **2.6** to **3.4**
+**0.9.3**        **3.1.X**                    **1.5.x** to **1.8** **2.6** to **3.4**
+**0.9.2**        **3.1.X**                    **1.5.x** to **1.8** **2.6** to **3.4**
+**0.9.1**        **3.1.X**                    **1.5.x** to **1.8** **2.6** to **3.4**
+**0.9**          **3.1.X**                    **1.5.x** to **1.8** **2.6**, **2.7**, **3.3**, **3.4**
+**0.9**          **3.1.X**                    **1.5.x** to **1.8** **2.6**, **2.7**, **3.3**, **3.4**
+**0.9**          **3.1.X**                    **1.5.x** to **1.8** **2.6**, **2.7**, **3.3**, **3.4**
+**0.8.2**        **3.0.4** to **3.1.1**       **1.5.x** to **1.8** **2.6**, **2.7**, **3.3**, **3.4**
+**0.8.1**        **3.0.4** to **3.1.1**       **1.5.x** to **1.8** **2.6**, **2.7**, **3.3**, **3.4**
+**0.8**          **3.0.4**                    **1.5.x** to **1.7** **2.6**, **2.7**, **3.3**, **3.4**
+**0.7**          **2.4.3**                    **1.5.x** to **1.7** **2.6**, **2.7**, **3.3**, **3.4**
+**0.6**          **2.4.3**                    **1.5.x** to **1.7** **2.6**, **2.7**, **3.3**, **3.4**
+**0.5**          from **2.3.14** to **2.4.2** **1.5.x** to **1.7** **2.6**, **2.7**, **3.3**, **3.4**
+**0.4**          from **2.3.14** to **2.4.2** **1.5.x** to **1.7** **2.6**, **2.7**, **3.3**, **3.4**
 **0.3**          from **2.3.14** to **2.4.2** **1.5.x**, **1.6.x** **2.6**, **2.7**
 **0.2**          from **2.2.2** to **2.3.13** **1.5.x**, **1.6.x** **2.6**, **2.7**
-===============  ============================ ==================== ==================
+===============  ============================ ==================== ==================================
 
 Fields
 ------
 
-Provides a GeometryField, which is a subclass of Django Rest Framework
+GeometryField
+~~~~~~~~~~~~~
+
+Provides a ``GeometryField``, which is a subclass of Django Rest Framework
 (from now on **DRF**) ``WritableField``. This field handles GeoDjango
 geometry fields, providing custom ``to_native`` and ``from_native``
 methods for GeoJSON input/output.
 
+**New in 0.9.3:** there is no need to define this field explicitly in your serializer,
+it's mapped automatically during initialization in ``rest_framework_gis.apps.AppConfig.ready()``.
+
+GeometrySerializerMethodField
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Provides a ``GeometrySerializerMethodField``, which is a subclass of DRF
+``SerializerMethodField`` and handles values which are computed with a serializer
+method and are used as a ``geo_field``. `See example below <https://github.com/djangonauts/django-rest-framework-gis#using-geometryserializermethodfield-as-geo_field>`__.
+
 Serializers
 -----------
 
-GeoModelSerializer
-~~~~~~~~~~~~~~~~~~
+GeoModelSerializer (DEPRECATED)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Deprecated, will be removed in 1.0**: Using this serializer is not needed anymore since 0.9.3 if you add
+``rest_framework_gis`` in ``settings.INSTALLED_APPS``
 
 Provides a ``GeoModelSerializer``, which is a sublass of DRF
 ``ModelSerializer``. This serializer updates the field\_mapping
@@ -96,7 +136,7 @@ In contrast, the ``GeoModelSerializer`` will output:
 GeoFeatureModelSerializer
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-``GeoFeatureModelSerializer`` is a subclass of ``GeoModelSerializer``
+``GeoFeatureModelSerializer`` is a subclass of ``rest_framework.ModelSerializer``
 which will output data in a format that is **GeoJSON** compatible. Using
 the above example, the ``GeoFeatureModelSerializer`` will output:
 
@@ -121,9 +161,6 @@ the above example, the ``GeoFeatureModelSerializer`` will output:
 If you are serializing an object list, ``GeoFeatureModelSerializer``
 will create a ``FeatureCollection``:
 
-(**NOTE:** This currenty does not work with the default pagination
-serializer)
-
 .. code-block:: javascript
 
     {
@@ -161,7 +198,10 @@ serializer)
         }
     }
 
-``GeoFeatureModelSerializer`` requires you to define a **``geo_field``**
+Specifying the geometry field: "geo_field"
+##########################################
+
+``GeoFeatureModelSerializer`` requires you to define a ``geo_field``
 to be serialized as the "geometry". For example:
 
 .. code-block:: python
@@ -179,9 +219,38 @@ to be serialized as the "geometry". For example:
             # as with a ModelSerializer.
             fields = ('id', 'address', 'city', 'state')
 
+Using GeometrySerializerMethodField as "geo_field"
+##################################################
+
+``geo_field`` may also be an instance of ``GeometrySerializerMethodField``.
+In this case you can compute its value during serialization. For example:
+
+.. code-block:: python
+
+    from django.contrib.gis.geos import Point
+    from rest_framework_gis.serializers import GeoFeatureModelSerializer, GeometrySerializerMethodField
+
+    class LocationSerializer(GeoFeatureModelSerializer):
+        """ A class to serialize locations as GeoJSON compatible data """
+
+        # a field which contains a geometry value and can be used as geo_field
+        other_point = GeometrySerializerMethodField()
+
+        def get_other_point(self, obj):
+            return Point(obj.point.lat / 2, obj.point.lon / 2)
+
+        class Meta:
+            model = Location
+            geo_field = 'other_point'
+
+Serializer for ``geo_field`` may also return ``None`` value, which will translate to ``null`` value for geojson ``geometry`` field.
+
+Specifying the ID: "id_field"
+#############################
+
 The primary key of the model (usually the "id" attribute) is
 automatically put outside the "properties" object (before "type") unless
-**``id_field``** is set to False:
+``id_field`` is set to False:
 
 .. code-block:: python
 
@@ -195,7 +264,7 @@ automatically put outside the "properties" object (before "type") unless
             id_field = False
             fields = ('id', 'address', 'city', 'state')
 
-You could also set the **``id_field``** to some other unique field in
+You could also set the ``id_field`` to some other unique field in
 your model, like **"slug"**:
 
 .. code-block:: python
@@ -206,10 +275,152 @@ your model, like **"slug"**:
 
         class Meta:
             model = Location
-            geo_field = "point"
-            id_field = "slug"
+            geo_field = 'point'
+            id_field = 'slug'
             fields = ('slug', 'address', 'city', 'state')
 
+Bounding Box: "auto_bbox" and "bbox_geo_field"
+##############################################
+
+The GeoJSON specification allows a feature to contain a
+`boundingbox of a feature <http://geojson.org/geojson-spec.html#geojson-objects>`__.
+``GeoFeatureModelSerializer`` allows two different ways to fill this property. The first
+is using the ``geo_field`` to calculate the bounding box of a feature. This only allows
+read access for a REST client and can be achieved using ``auto_bbox``. Example:
+
+.. code-block:: python
+
+    from rest_framework_gis.serializers import GeoFeatureModelSerializer
+
+    class LocationSerializer(GeoFeatureModelSerializer):
+        class Meta:
+            model = Location
+            geo_field = 'geometry'
+            auto_bbox = True
+
+
+The second approach uses the ``bbox_geo_field`` to specify an addional
+GeometryField of the model which will be used to calculate the bounding box. This allows
+boundingboxes differ from the exact extent of a features geometry. Additionally this
+enables read and write access for the REST client. Bounding boxes send from the client will
+be saved as Polygons. Example:
+
+.. code-block:: python
+
+    from rest_framework_gis.serializers import GeoFeatureModelSerializer
+
+    class LocationSerializer(GeoFeatureModelSerializer):
+
+        class Meta:
+            model = BoxedLocation
+            geo_field = 'geometry'
+            bbox_geo_field = 'bbox_geometry'
+
+
+Custom GeoJSON properties source
+################################
+
+In GeoJSON each feature can have a ``properties`` member containing the
+attributes of the feature. By default this field is filled with the
+attributes from your Django model, excluding the id, geometry and bounding
+box fields. It's possible to override this behaviour and implement a custom
+source for the ``properties`` member.
+
+The following example shows how to use a PostgreSQL HStore field as a source for
+the ``properties`` member:
+
+.. code-block:: python
+
+    # models.py
+    class Link(models.Model):
+        """
+        Metadata is stored in a PostgreSQL HStore field, which allows us to
+        store arbitrary key-value pairs with a link record.
+        """
+        metadata = HStoreField(blank=True, null=True, default={})
+        geo = models.LineStringField()
+        objects = models.GeoManager()
+
+    # serializers.py
+    class NetworkGeoSerializer(GeoFeatureModelSerializer):
+        class Meta:
+            model = models.Link
+            geo_field = 'geo'
+            auto_bbox = True
+
+        def get_properties(self, instance, fields):
+            # This is a PostgreSQL HStore field, which django maps to a dict
+            return instance.metadata
+
+        def unformat_geojson(self, feature):
+            attrs = {
+                self.Meta.geo_field: feature["geometry"],
+                "metadata": feature["properties"]
+            }
+
+            if self.Meta.bbox_geo_field and "bbox" in feature:
+                attrs[self.Meta.bbox_geo_field] = Polygon.from_bbox(feature["bbox"])
+
+            return attrs
+
+When the serializer renders GeoJSON, it calls the method
+``get_properties`` for each object in the database. This function
+should return a dictionary containing the attributes for the feature. In the
+case of a HStore field, this function is easily implemented.
+
+The reverse is also required: mapping a GeoJSON formatted structure to
+attributes of your model. This task is done by ``unformat_geojson``. It should
+return a dictionary with your model attributes as keys, and the corresponding
+values retrieved from the GeoJSON feature data.
+
+Pagination
+----------
+
+We provide a ``GeoJsonPagination`` class.
+
+GeoJsonPagination
+~~~~~~~~~~~~~~~~~
+
+Based on ``rest_framework.pagination.PageNumberPagination``.
+
+Code example:
+
+.. code-block:: python
+
+    from rest_framework_gis.pagination import GeoJsonPagination
+    # --- other omitted imports --- #
+
+    class GeojsonLocationList(generics.ListCreateAPIView):
+        # -- other omitted view attributes --- #
+        pagination_class = GeoJsonPagination
+
+Example result response (cut to one element only instead of 10):
+
+.. code-block:: javascript
+
+    {
+        "type": "FeatureCollection",
+        "count": 25,
+        "next": "http://localhost:8000/geojson/?page=2",
+        "previous": null,
+        "features": [
+            {
+                "type": "Feature",
+                "geometry": {
+                    "type": "Point",
+                    "coordinates": [
+                        42.0,
+                        50.0
+                    ]
+                },
+                "properties": {
+                    "name": "test"
+                }
+            }
+        ]
+    }
+
+
 Filters
 -------
 
@@ -402,15 +613,13 @@ Contributing
 8. Document your changes
 9. Send pull request
 
-.. |Build Status| image:: https://travis-ci.org/djangonauts/django-rest-framework-gis.png?branch=master
+.. |Build Status| image:: https://travis-ci.org/djangonauts/django-rest-framework-gis.svg?branch=master
    :target: https://travis-ci.org/djangonauts/django-rest-framework-gis
-.. |Coverage Status| image:: https://coveralls.io/repos/djangonauts/django-rest-framework-gis/badge.png
+.. |Coverage Status| image:: https://coveralls.io/repos/djangonauts/django-rest-framework-gis/badge.svg
    :target: https://coveralls.io/r/djangonauts/django-rest-framework-gis
-.. |Code Health| image:: https://landscape.io/github/djangonauts/django-rest-framework-gis/master/landscape.png
-   :target: https://landscape.io/github/djangonauts/django-rest-framework-gis/master
-.. |Requirements Status| image:: https://requires.io/github/djangonauts/django-rest-framework-gis/requirements.png?branch=master
+.. |Requirements Status| image:: https://requires.io/github/djangonauts/django-rest-framework-gis/requirements.svg?branch=master
    :target: https://requires.io/github/djangonauts/django-rest-framework-gis/requirements/?branch=master
-.. |PyPI version| image:: https://badge.fury.io/py/djangorestframework-gis.png
+.. |PyPI version| image:: https://badge.fury.io/py/djangorestframework-gis.svg
    :target: http://badge.fury.io/py/djangorestframework-gis
-.. |PyPI downloads| image:: https://pypip.in/d/djangorestframework-gis/badge.png
+.. |PyPI downloads| image:: https://img.shields.io/pypi/dm/djangorestframework-gis.svg
     :target: http://badge.fury.io/py/djangorestframework-gis
diff --git a/performance_tests.rst b/performance_tests.rst
new file mode 100644
index 0000000..7764725
--- /dev/null
+++ b/performance_tests.rst
@@ -0,0 +1,33 @@
+Average of 5 measurements for python2 and python3.
+
+Launch the performance test with::
+
+    cd tests
+    django test --keepdb django_restframework_gis_tests.test_performance
+
+For more information regarding how the measurement is performed read the code in
+`test_performance.py <https://github.com/djangonauts/django-rest-framework-gis/blob/master/tests/django_restframework_gis_tests/test_performance.py>`__.
+
+0.9.2
+=====
+
+- **py2**: 6.304474401472
+- **py3**: 6.952443096001661
+
+0.9.3
+=====
+
+- **py2**: 4.462462759018 (**29.2%** improvement)
+- **py3**: 5.217188624000118 (**25%** improvement)
+
+0.9.4
+=====
+
+- **py2**: 4.227859210966
+- **py3**: 5.00467809599977
+
+0.9.5
+=====
+
+- **py2**: 4.193417596816
+- **py3**: 4.89978777600045
diff --git a/requirements-test.txt b/requirements-test.txt
index e05118e..1d80ace 100644
--- a/requirements-test.txt
+++ b/requirements-test.txt
@@ -1,5 +1,6 @@
 psycopg2
 djangorestframework>=3.0.4
-coverage
+coverage==3.7.1  # rq.filter: >=3,<4
 coveralls
 django-filter
+contexttimer
diff --git a/requirements.txt b/requirements.txt
old mode 100755
new mode 100644
index 5874df2..c6c4f3f
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1 @@
-djangorestframework>=3.0.4
+djangorestframework>=3.0.4,<3.3
diff --git a/rest_framework_gis/__init__.py b/rest_framework_gis/__init__.py
old mode 100755
new mode 100644
index 173f52c..343f1bf
--- a/rest_framework_gis/__init__.py
+++ b/rest_framework_gis/__init__.py
@@ -1,4 +1,4 @@
-VERSION = (0, 8, 0, 'final')
+VERSION = (0, 9, 5, 'final')
 __version__ = VERSION  # alias
 
 
@@ -12,3 +12,30 @@ def get_version():
         if VERSION[3] != 'final':
             version = '%s %s' % (version, VERSION[3])
     return version
+
+
+default_app_config = 'rest_framework_gis.apps.AppConfig'
+
+# maintain support for django 1.5 and 1.6
+# TODO: remove in version 1.0
+try:
+    import os
+    import django
+
+    if os.environ.get('DJANGO_SETTINGS_MODULE'):
+        from django.conf import settings
+        from .apps import AppConfig
+
+        if 'rest_framework_gis' not in settings.INSTALLED_APPS:
+            import warnings
+            warnings.simplefilter('always', DeprecationWarning)
+            warnings.warn('\nGeoModelSerializer is deprecated, '
+                          'add "rest_framework_gis" to settings.INSTALLED_APPS and use '
+                          '"rest_framework.ModelSerializer" instead',
+                          DeprecationWarning)
+
+        if django.get_version() < '1.7' or 'rest_framework_gis' not in settings.INSTALLED_APPS:
+            import rest_framework_gis
+            AppConfig('rest_framework_gis', rest_framework_gis).ready()
+except ImportError:
+    pass
diff --git a/rest_framework_gis/apps.py b/rest_framework_gis/apps.py
new file mode 100644
index 0000000..43767c7
--- /dev/null
+++ b/rest_framework_gis/apps.py
@@ -0,0 +1,38 @@
+try:
+    from django.apps import AppConfig as BaseConfig
+except ImportError:  # pragma: nocover
+    # django <= 1.6
+    class BaseConfig(object):
+        def __init__(self, *args):
+            pass
+
+
+class AppConfig(BaseConfig):
+    name = 'rest_framework_gis'
+
+    def ready(self):
+        """
+        update Django Rest Framework serializer mappings
+        """
+        from django.contrib.gis.db import models
+        from rest_framework.serializers import ModelSerializer
+        from .fields import GeometryField
+
+        try:
+            # drf 3.0
+            field_mapping = ModelSerializer._field_mapping.mapping
+        except AttributeError:
+            # drf 3.1
+            field_mapping = ModelSerializer.serializer_field_mapping
+
+        # map GeoDjango fields to drf-gis GeometryField
+        field_mapping.update({
+            models.GeometryField: GeometryField,
+            models.PointField: GeometryField,
+            models.LineStringField: GeometryField,
+            models.PolygonField: GeometryField,
+            models.MultiPointField: GeometryField,
+            models.MultiLineStringField: GeometryField,
+            models.MultiPolygonField: GeometryField,
+            models.GeometryCollectionField: GeometryField
+        })
diff --git a/rest_framework_gis/fields.py b/rest_framework_gis/fields.py
old mode 100755
new mode 100644
index 11b2e62..027b01f
--- a/rest_framework_gis/fields.py
+++ b/rest_framework_gis/fields.py
@@ -1,15 +1,15 @@
-# rest_framework_gis/fields.py
-
-try:
-    import simplejson as json
-except ImportError:
-    import json
+import json
 
 from django.contrib.gis.geos import GEOSGeometry, GEOSException
 from django.contrib.gis.gdal import OGRException
 from django.core.exceptions import ValidationError
 from django.utils.translation import ugettext_lazy as _
-from rest_framework.fields import Field
+from rest_framework.fields import Field, SerializerMethodField
+
+from .utils import OrderedDict
+
+
+__all__ = ['GeometryField', 'GeometrySerializerMethodField']
 
 
 class GeometryField(Field):
@@ -25,24 +25,55 @@ class GeometryField(Field):
     def to_representation(self, value):
         if isinstance(value, dict) or value is None:
             return value
-
-        # Get GeoDjango geojson serialization and then convert it _back_ to
-        # a Python object
-        return json.loads(GEOSGeometry(value).geojson)
+        # we expect value to be a GEOSGeometry instance
+        return GeoJsonDict((
+            ('type', value.geom_type),
+            ('coordinates', value.coords),
+        ))
 
     def to_internal_value(self, value):
         if value == '' or value is None:
             return value
-
+        if isinstance(value, GEOSGeometry):
+            # value already has the correct representation
+            return value
         if isinstance(value, dict):
             value = json.dumps(value)
-
         try:
-            return GEOSGeometry(value).geojson
+            return GEOSGeometry(value)
         except (ValueError, GEOSException, OGRException, TypeError):
-            raise ValidationError(_('Invalid format: string or unicode input unrecognized as WKT EWKT, and HEXEWKB.'))
+            raise ValidationError(_('Invalid format: string or unicode input unrecognized as GeoJSON, WKT EWKT or HEXEWKB.'))
 
     def validate_empty_values(self, data):
-        if data in [u'']:
+        if data == '':
             self.fail('required')
         return super(GeometryField, self).validate_empty_values(data)
+
+
+class GeometrySerializerMethodField(SerializerMethodField):
+    def to_representation(self, value):
+        value = super(GeometrySerializerMethodField, self).to_representation(value)
+        if value is not None:
+            # we expect value to be a GEOSGeometry instance
+            return GeoJsonDict((
+                ('type', value.geom_type),
+                ('coordinates', value.coords),
+            ))
+        else:
+            return None
+
+
+class GeoJsonDict(OrderedDict):
+    """
+    Used for serializing GIS values to GeoJSON values
+    TODO: remove this when support for python 2.6/2.7 will be dropped
+    """
+
+    def __str__(self):
+        """
+        Avoid displaying strings like
+        ``{ 'type': u'Point', 'coordinates': [12, 32] }``
+        in DRF browsable UI inputs (python 2.6/2.7)
+        see: https://github.com/djangonauts/django-rest-framework-gis/pull/60
+        """
+        return json.dumps(self)
diff --git a/rest_framework_gis/filters.py b/rest_framework_gis/filters.py
old mode 100755
new mode 100644
index ab3d6ca..2232b4b
--- a/rest_framework_gis/filters.py
+++ b/rest_framework_gis/filters.py
@@ -1,3 +1,5 @@
+from math import cos, pi
+
 from django.db.models import Q
 from django.core.exceptions import ImproperlyConfigured
 from django.contrib.gis.db import models
@@ -6,18 +8,24 @@ from django.contrib.gis import forms
 
 from rest_framework.filters import BaseFilterBackend
 from rest_framework.exceptions import ParseError
-from math import cos, pi 
 
 from .tilenames import tile_edges
 
 try:
     import django_filters
-except ImportError:
+except ImportError:  # pragma: no cover
     raise ImproperlyConfigured(
         'restframework-gis filters depend on package "django-filter" '
         'which is missing. Install with "pip install django-filter".'
     )
 
+try:  # pragma: no cover
+    # django >= 1.8
+    from django.contrib.gis.db.models.lookups import gis_lookups
+except ImportError:  # pragma: no cover
+    # django <= 1.7
+    gis_lookups = models.sql.query.ALL_TERMS
+
 
 __all__ = [
     'InBBoxFilter',
@@ -33,15 +41,14 @@ class InBBoxFilter(BaseFilterBackend):
     bbox_param = 'in_bbox'  # The URL query parameter which contains the bbox.
 
     def get_filter_bbox(self, request):
-        bbox_string = request.QUERY_PARAMS.get(self.bbox_param, None)
+        bbox_string = request.query_params.get(self.bbox_param, None)
         if not bbox_string:
             return None
 
         try:
             p1x, p1y, p2x, p2y = (float(n) for n in bbox_string.split(','))
         except ValueError:
-            raise ParseError("Not valid bbox string in parameter %s."
-                             % self.bbox_param)
+            raise ParseError('Invalid bbox string supplied for parameter {0}'.format(self.bbox_param))
 
         x = Polygon.from_bbox((p1x, p1y, p2x, p2y))
         return x
@@ -78,23 +85,22 @@ class GeoFilterSet(django_filters.FilterSet):
 
     def __new__(cls, *args, **kwargs):
         cls.filter_overrides.update(cls.GEOFILTER_FOR_DBFIELD_DEFAULTS)
-        cls.LOOKUP_TYPES = sorted(models.sql.query.ALL_TERMS)
+        cls.LOOKUP_TYPES = sorted(gis_lookups)
         return super(GeoFilterSet, cls).__new__(cls)
 
 
 class TMSTileFilter(InBBoxFilter):
-    tile_param = 'tile' # The URL query paramater which contains the tile address
+    tile_param = 'tile'  # The URL query paramater which contains the tile address
 
     def get_filter_bbox(self, request):
-        tile_string = request.QUERY_PARAMS.get(self.tile_param, None)
+        tile_string = request.query_params.get(self.tile_param, None)
         if not tile_string:
             return None
 
         try:
             z, x, y = (int(n) for n in tile_string.split('/'))
         except ValueError:
-            raise ParseError("Not valid tile string in parameter %s."
-                             % self.tile_param)
+            raise ParseError('Invalid tile string supplied for parameter {0}'.format(self.tile_param))
 
         bbox = Polygon.from_bbox(tile_edges(x, y, z))
         return bbox
@@ -102,50 +108,49 @@ class TMSTileFilter(InBBoxFilter):
 
 class DistanceToPointFilter(BaseFilterBackend):
     dist_param = 'dist'
-    point_param = 'point'  # The URL query parameter which contains the 
+    point_param = 'point'  # The URL query parameter which contains the
 
     def get_filter_point(self, request):
-        point_string = request.QUERY_PARAMS.get(self.point_param, None)
+        point_string = request.query_params.get(self.point_param, None)
         if not point_string:
             return None
 
         try:
-            (x,y) = (float(n) for n in point_string.split(','))
+            (x, y) = (float(n) for n in point_string.split(','))
         except ValueError:
-            raise ParseError("Not valid geometry string in parameter %s."
-                             % self.point_string)
+            raise ParseError('Invalid geometry string supplied for parameter {0}'.format(self.point_param))
 
-        p = Point(x,y)
+        p = Point(x, y)
         return p
 
     def dist_to_deg(self, distance, latitude):
         """
         distance = distance in meters
-        latitude = latitude in degrees 
+        latitude = latitude in degrees
 
         at the equator, the distance of one degree is equal in latitude and longitude.
         at higher latitudes, a degree longitude is shorter in length, proportional to cos(latitude)
         http://en.wikipedia.org/wiki/Decimal_degrees
 
         This function is part of a distance filter where the database 'distance' is in degrees.
-        There's no good single-valued answer to this problem. 
-        The distance/ degree is quite constant N/S around the earth (latitude), 
+        There's no good single-valued answer to this problem.
... 1647 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/djangorestframework-gis.git



More information about the Python-modules-commits mailing list