[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