From 422e92d9ceaa07444d8fd6de00a526c72bf8e9ca Mon Sep 17 00:00:00 2001 From: Mehdi Pourfar Date: Sun, 3 Dec 2017 19:00:19 +0330 Subject: [PATCH] support django 2 --- .travis.yml | 5 ++ cities/conf.py | 3 + cities/migrations/0001_initial.py | 16 ++-- cities/migrations/0011_auto_20180108_0706.py | 70 ++++++++++++++++ cities/models.py | 85 +++++++++++++++----- test_project/test_app/urls.py | 32 ++++++-- tox.ini | 2 + 7 files changed, 178 insertions(+), 35 deletions(-) create mode 100644 cities/migrations/0011_auto_20180108_0706.py diff --git a/.travis.yml b/.travis.yml index f3df805a..86d205d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,7 @@ env: - DJANGO_VERSION='Django>=1.9,<1.10' - DJANGO_VERSION='Django>=1.10,<1.11' - DJANGO_VERSION='Django>=1.11,<2.0' + - DJANGO_VERSION='Django>=2.0,<2.1' - DJANGO_VERSION='https://github.com/django/django/archive/master.tar.gz' matrix: @@ -36,6 +37,10 @@ matrix: env: DJANGO_VERSION='Django>=1.10,<1.11' - python: "3.3" env: DJANGO_VERSION='Django>=1.11,<2.0' + - python: "2.7" + env: DJANGO_VERSION='Django>=2.0,<2.1' + - python: "3.3" + env: DJANGO_VERSION='Django>=2.0,<2.1' - python: "2.7" env: DJANGO_VERSION='https://github.com/django/django/archive/master.tar.gz' - python: "3.3" diff --git a/cities/conf.py b/cities/conf.py index 5cc68449..87041cad 100644 --- a/cities/conf.py +++ b/cities/conf.py @@ -2,6 +2,8 @@ from importlib import import_module from collections import defaultdict + +import django from django.conf import settings as django_settings from django.core.exceptions import ImproperlyConfigured from django.utils.translation import ugettext_lazy as _ @@ -363,3 +365,4 @@ def create_plugins(): # Users who want better postal codes can flip this on (developers of # django-cities itself probably will), but most probably won't want to VALIDATE_POSTAL_CODES = getattr(django_settings, 'CITIES_VALIDATE_POSTAL_CODES', False) +DJANGO_VERSION = float('.'.join(map(str, django.VERSION[:2]))) diff --git a/cities/migrations/0001_initial.py b/cities/migrations/0001_initial.py index a6f6d964..0c063254 100644 --- a/cities/migrations/0001_initial.py +++ b/cities/migrations/0001_initial.py @@ -6,6 +6,8 @@ import swapper +from cities.models import SET_NULL_OR_CASCADE + class Migration(migrations.Migration): @@ -81,7 +83,7 @@ class Migration(migrations.Migration): ('location', django.contrib.gis.db.models.fields.PointField(srid=4326)), ('population', models.IntegerField()), ('alt_names', models.ManyToManyField(to='cities.AlternativeName')), - ('city', models.ForeignKey(to=swapper.get_model_name('cities', 'City'))), + ('city', models.ForeignKey(to=swapper.get_model_name('cities', 'City'), on_delete=SET_NULL_OR_CASCADE)), ], options={ 'abstract': False, @@ -99,7 +101,7 @@ class Migration(migrations.Migration): ('subregion_name', models.CharField(max_length=100, db_index=True)), ('district_name', models.CharField(max_length=100, db_index=True)), ('alt_names', models.ManyToManyField(to='cities.AlternativeName')), - ('country', models.ForeignKey(related_name='postal_codes', to=swapper.get_model_name('cities', 'Country'))), + ('country', models.ForeignKey(related_name='postal_codes', to=swapper.get_model_name('cities', 'Country'), on_delete=SET_NULL_OR_CASCADE)), ], options={ 'abstract': False, @@ -114,7 +116,7 @@ class Migration(migrations.Migration): ('name_std', models.CharField(max_length=200, verbose_name='standard name', db_index=True)), ('code', models.CharField(max_length=200, db_index=True)), ('alt_names', models.ManyToManyField(to='cities.AlternativeName')), - ('country', models.ForeignKey(to=swapper.get_model_name('cities', 'Country'))), + ('country', models.ForeignKey(to=swapper.get_model_name('cities', 'Country'), on_delete=SET_NULL_OR_CASCADE)), ], options={ 'abstract': False, @@ -129,7 +131,7 @@ class Migration(migrations.Migration): ('name_std', models.CharField(max_length=200, verbose_name='standard name', db_index=True)), ('code', models.CharField(max_length=200, db_index=True)), ('alt_names', models.ManyToManyField(to='cities.AlternativeName')), - ('region', models.ForeignKey(to='cities.Region')), + ('region', models.ForeignKey(to='cities.Region', on_delete=SET_NULL_OR_CASCADE)), ], options={ 'abstract': False, @@ -138,16 +140,16 @@ class Migration(migrations.Migration): migrations.AddField( model_name='city', name='country', - field=models.ForeignKey(to=swapper.get_model_name('cities', 'Country')), + field=models.ForeignKey(to=swapper.get_model_name('cities', 'Country'), on_delete=SET_NULL_OR_CASCADE), ), migrations.AddField( model_name='city', name='region', - field=models.ForeignKey(blank=True, to='cities.Region', null=True), + field=models.ForeignKey(blank=True, to='cities.Region', null=True, on_delete=SET_NULL_OR_CASCADE), ), migrations.AddField( model_name='city', name='subregion', - field=models.ForeignKey(blank=True, to='cities.Subregion', null=True), + field=models.ForeignKey(blank=True, to='cities.Subregion', null=True, on_delete=SET_NULL_OR_CASCADE), ), ] diff --git a/cities/migrations/0011_auto_20180108_0706.py b/cities/migrations/0011_auto_20180108_0706.py new file mode 100644 index 00000000..b8278d7d --- /dev/null +++ b/cities/migrations/0011_auto_20180108_0706.py @@ -0,0 +1,70 @@ +# Generated by Django 2.0 on 2018-01-08 07:06 + +import cities.models +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cities', '0010_adjust_unique_attributes'), + ] + + operations = [ + migrations.AlterField( + model_name='city', + name='country', + field=models.ForeignKey(on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='cities', to=settings.CITIES_COUNTRY_MODEL), + ), + migrations.AlterField( + model_name='city', + name='region', + field=models.ForeignKey(blank=True, null=True, on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='cities', to='cities.Region'), + ), + migrations.AlterField( + model_name='city', + name='subregion', + field=models.ForeignKey(blank=True, null=True, on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='cities', to='cities.Subregion'), + ), + migrations.AlterField( + model_name='country', + name='continent', + field=models.ForeignKey(null=True, on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='countries', to=settings.CITIES_CONTINENT_MODEL), + ), + migrations.AlterField( + model_name='district', + name='city', + field=models.ForeignKey(on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='districts', to=settings.CITIES_CITY_MODEL), + ), + migrations.AlterField( + model_name='postalcode', + name='city', + field=models.ForeignKey(blank=True, null=True, on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='postal_codes', to=settings.CITIES_CITY_MODEL), + ), + migrations.AlterField( + model_name='postalcode', + name='district', + field=models.ForeignKey(blank=True, null=True, on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='postal_codes', to='cities.District'), + ), + migrations.AlterField( + model_name='postalcode', + name='region', + field=models.ForeignKey(blank=True, null=True, on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='postal_codes', to='cities.Region'), + ), + migrations.AlterField( + model_name='postalcode', + name='subregion', + field=models.ForeignKey(blank=True, null=True, on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='postal_codes', to='cities.Subregion'), + ), + migrations.AlterField( + model_name='region', + name='country', + field=models.ForeignKey(on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='regions', to=settings.CITIES_COUNTRY_MODEL), + ), + migrations.AlterField( + model_name='subregion', + name='region', + field=models.ForeignKey(on_delete=cities.models.SET_NULL_OR_CASCADE, related_name='subregions', to='cities.Region'), + ), + ] diff --git a/cities/models.py b/cities/models.py index ba8aafb4..841bdcad 100644 --- a/cities/models.py +++ b/cities/models.py @@ -8,13 +8,14 @@ from django.db import transaction from django.utils.encoding import python_2_unicode_compatible -from django.contrib.gis.db import models +from django.contrib.gis.db.models import PointField +from django.db import models from django.contrib.gis.geos import Point from model_utils import Choices import swapper -from .conf import (ALTERNATIVE_NAME_TYPES, SLUGIFY_FUNCTION) +from .conf import (ALTERNATIVE_NAME_TYPES, SLUGIFY_FUNCTION, DJANGO_VERSION) from .managers import AlternativeNameManager from .util import unicode_func @@ -24,9 +25,21 @@ ] +if DJANGO_VERSION < 2: + from django.contrib.gis.db.models import GeoManager +else: + from django.db.models import Manager as GeoManager + slugify_func = SLUGIFY_FUNCTION +def SET_NULL_OR_CASCADE(collector, field, sub_objs, using): + if field.null is True: + models.SET_NULL(collector, field, sub_objs, using) + else: + models.CASCADE(collector, field, sub_objs, using) + + class SlugModel(models.Model): slug = models.CharField(blank=True, max_length=255, null=True) @@ -64,7 +77,7 @@ class Place(models.Model): name = models.CharField(max_length=200, db_index=True, verbose_name="ascii name") alt_names = models.ManyToManyField('AlternativeName') - objects = models.GeoManager() + objects = GeoManager() class Meta: abstract = True @@ -117,7 +130,9 @@ class BaseCountry(Place, SlugModel): language_codes = models.CharField(max_length=250, null=True) phone = models.CharField(max_length=20) continent = models.ForeignKey(swapper.get_model_name('cities', 'Continent'), - null=True, related_name='countries') + null=True, + related_name='countries', + on_delete=SET_NULL_OR_CASCADE) tld = models.CharField(max_length=5, verbose_name='TLD') postal_code_format = models.CharField(max_length=127) postal_code_regex = models.CharField(max_length=255) @@ -152,7 +167,8 @@ class Region(Place, SlugModel): name_std = models.CharField(max_length=200, db_index=True, verbose_name="standard name") code = models.CharField(max_length=200, db_index=True) country = models.ForeignKey(swapper.get_model_name('cities', 'Country'), - related_name='regions') + related_name='regions', + on_delete=SET_NULL_OR_CASCADE) class Meta: unique_together = (('country', 'name'),) @@ -175,7 +191,9 @@ class Subregion(Place, SlugModel): name_std = models.CharField(max_length=200, db_index=True, verbose_name="standard name") code = models.CharField(max_length=200, db_index=True) - region = models.ForeignKey(Region, related_name='subregions') + region = models.ForeignKey(Region, + related_name='subregions', + on_delete=SET_NULL_OR_CASCADE) class Meta: unique_together = (('region', 'id', 'name'),) @@ -198,10 +216,19 @@ class BaseCity(Place, SlugModel): name_std = models.CharField(max_length=200, db_index=True, verbose_name="standard name") country = models.ForeignKey(swapper.get_model_name('cities', 'Country'), - related_name='cities') - region = models.ForeignKey(Region, null=True, blank=True, related_name='cities') - subregion = models.ForeignKey(Subregion, null=True, blank=True, related_name='cities') - location = models.PointField() + related_name='cities', + on_delete=SET_NULL_OR_CASCADE) + region = models.ForeignKey(Region, + null=True, + blank=True, + related_name='cities', + on_delete=SET_NULL_OR_CASCADE) + subregion = models.ForeignKey(Subregion, + null=True, + blank=True, + related_name='cities', + on_delete=SET_NULL_OR_CASCADE) + location = PointField() population = models.IntegerField() elevation = models.IntegerField(null=True) kind = models.CharField(max_length=10) # http://www.geonames.org/export/codes.html @@ -232,9 +259,11 @@ class District(Place, SlugModel): name_std = models.CharField(max_length=200, db_index=True, verbose_name="standard name") code = models.CharField(blank=True, db_index=True, max_length=200, null=True) - location = models.PointField() + location = PointField() population = models.IntegerField() - city = models.ForeignKey(swapper.get_model_name('cities', 'City'), related_name='districts') + city = models.ForeignKey(swapper.get_model_name('cities', 'City'), + related_name='districts', + on_delete=SET_NULL_OR_CASCADE) class Meta: unique_together = (('city', 'name'),) @@ -279,23 +308,39 @@ class PostalCode(Place, SlugModel): slug_contains_id = True code = models.CharField(max_length=20) - location = models.PointField() + location = PointField() country = models.ForeignKey(swapper.get_model_name('cities', 'Country'), - related_name='postal_codes') + related_name='postal_codes', + on_delete=SET_NULL_OR_CASCADE) # Region names for each admin level, region may not exist in DB region_name = models.CharField(max_length=100, db_index=True) subregion_name = models.CharField(max_length=100, db_index=True) district_name = models.CharField(max_length=100, db_index=True) - region = models.ForeignKey(Region, blank=True, null=True, related_name='postal_codes') - subregion = models.ForeignKey(Subregion, blank=True, null=True, related_name='postal_codes') + region = models.ForeignKey(Region, + blank=True, + null=True, + related_name='postal_codes', + on_delete=SET_NULL_OR_CASCADE) + subregion = models.ForeignKey(Subregion, + blank=True, + null=True, + related_name='postal_codes', + on_delete=SET_NULL_OR_CASCADE) city = models.ForeignKey(swapper.get_model_name('cities', 'City'), - blank=True, null=True, related_name='postal_codes') - district = models.ForeignKey(District, blank=True, null=True, related_name='postal_codes') - - objects = models.GeoManager() + blank=True, + null=True, + related_name='postal_codes', + on_delete=SET_NULL_OR_CASCADE) + district = models.ForeignKey(District, + blank=True, + null=True, + related_name='postal_codes', + on_delete=SET_NULL_OR_CASCADE) + + objects = GeoManager() class Meta: unique_together = ( diff --git a/test_project/test_app/urls.py b/test_project/test_app/urls.py index cc4ed62c..0dc7b800 100644 --- a/test_project/test_app/urls.py +++ b/test_project/test_app/urls.py @@ -1,14 +1,30 @@ -from django.conf.urls import include, url +from django.conf.urls import url from django.contrib import admin +from django.core.exceptions import ImproperlyConfigured from cities.util import patterns -urlpatterns = patterns( - '', - # Examples: - # url(r'^$', 'test_project.views.home', name='home'), - # url(r'^blog/', include('blog.urls')), +app_name = "test_app" - url(r'^admin/', include(admin.site.urls)), -) +try: + from django.conf.urls import include + # Django < 2.0 + urlpatterns = patterns( + '', + # Examples: + # url(r'^$', 'test_project.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), + ) +except ImproperlyConfigured: + # Django >= 2.0 + urlpatterns = patterns( + '', + # Examples: + # url(r'^$', 'test_project.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', admin.site.urls), + ) diff --git a/tox.ini b/tox.ini index 474aa130..9171f756 100644 --- a/tox.ini +++ b/tox.ini @@ -2,6 +2,7 @@ envlist = py33-dj1.8, py{27,34,35,36}-dj1.{8,9,10,11} + py{34,35,36}-dj2.0 [testenv] commands=python {toxinidir}/test_project/manage.py test {posargs:test_app} --noinput @@ -13,5 +14,6 @@ deps = dj1.9: Django ~=1.9.0 dj1.10: Django ~=1.10.0 dj1.11: Django ~=1.11.0 + dj2.0: Django ~=2.0.0 psycopg2