From 949b7d715e68d976892d0c4764bb78ec5439a698 Mon Sep 17 00:00:00 2001 From: Wille Marcel Date: Tue, 28 Nov 2023 10:59:38 -0300 Subject: [PATCH] Remove feature app --- config/settings/common.py | 1 - .../management/commands/migrate_features.py | 109 ---- .../migrations/0030_auto_20170201_1617.py | 1 - .../migrations/0040_auto_20170328_1350.py | 4 - .../migrations/0045_auto_20170410_1218.py | 1 - osmchadjango/feature/__init__.py | 0 osmchadjango/feature/admin.py | 3 - osmchadjango/feature/filters.py | 211 -------- .../feature/migrations/0001_initial.py | 39 -- .../migrations/0002_remove_feature_osm_id.py | 19 - .../migrations/0003_auto_20161017_0655.py | 44 -- .../migrations/0004_auto_20161019_0645.py | 27 - .../migrations/0005_auto_20161114_0543.py | 21 - .../migrations/0005_feature_osm_compare.py | 20 - .../migrations/0006_auto_20161026_1323.py | 24 - .../migrations/0007_merge_20161122_0858.py | 16 - .../migrations/0008_auto_20161124_0742.py | 20 - .../0009_remove_feature_user_detail.py | 19 - .../migrations/0010_auto_20170207_1728.py | 25 - .../migrations/0011_remove_feature_score.py | 19 - .../0012_feature_harmful_reasons.py | 21 - .../migrations/0013_auto_20170410_1218.py | 24 - .../migrations/0014_auto_20170417_1740.py | 36 -- .../migrations/0015_auto_20170421_1939.py | 21 - .../migrations/0016_auto_20180307_1417.py | 20 - osmchadjango/feature/migrations/__init__.py | 0 osmchadjango/feature/models.py | 96 ---- osmchadjango/feature/serializers.py | 68 --- .../templates/feature/confirm_modify.html | 17 - .../templates/feature/feature_detail.html | 467 ------------------ .../templates/feature/feature_list.html | 224 --------- .../templates/feature/not_allowed.html | 9 - osmchadjango/feature/urls.py | 48 -- osmchadjango/feature/views.py | 403 --------------- osmchadjango/supervise/models.py | 13 - 35 files changed, 2090 deletions(-) delete mode 100644 osmchadjango/changeset/management/commands/migrate_features.py delete mode 100644 osmchadjango/feature/__init__.py delete mode 100644 osmchadjango/feature/admin.py delete mode 100644 osmchadjango/feature/filters.py delete mode 100644 osmchadjango/feature/migrations/0001_initial.py delete mode 100644 osmchadjango/feature/migrations/0002_remove_feature_osm_id.py delete mode 100644 osmchadjango/feature/migrations/0003_auto_20161017_0655.py delete mode 100644 osmchadjango/feature/migrations/0004_auto_20161019_0645.py delete mode 100644 osmchadjango/feature/migrations/0005_auto_20161114_0543.py delete mode 100644 osmchadjango/feature/migrations/0005_feature_osm_compare.py delete mode 100644 osmchadjango/feature/migrations/0006_auto_20161026_1323.py delete mode 100644 osmchadjango/feature/migrations/0007_merge_20161122_0858.py delete mode 100644 osmchadjango/feature/migrations/0008_auto_20161124_0742.py delete mode 100644 osmchadjango/feature/migrations/0009_remove_feature_user_detail.py delete mode 100644 osmchadjango/feature/migrations/0010_auto_20170207_1728.py delete mode 100644 osmchadjango/feature/migrations/0011_remove_feature_score.py delete mode 100644 osmchadjango/feature/migrations/0012_feature_harmful_reasons.py delete mode 100644 osmchadjango/feature/migrations/0013_auto_20170410_1218.py delete mode 100644 osmchadjango/feature/migrations/0014_auto_20170417_1740.py delete mode 100644 osmchadjango/feature/migrations/0015_auto_20170421_1939.py delete mode 100644 osmchadjango/feature/migrations/0016_auto_20180307_1417.py delete mode 100644 osmchadjango/feature/migrations/__init__.py delete mode 100644 osmchadjango/feature/models.py delete mode 100644 osmchadjango/feature/serializers.py delete mode 100644 osmchadjango/feature/templates/feature/confirm_modify.html delete mode 100644 osmchadjango/feature/templates/feature/feature_detail.html delete mode 100644 osmchadjango/feature/templates/feature/feature_list.html delete mode 100644 osmchadjango/feature/templates/feature/not_allowed.html delete mode 100644 osmchadjango/feature/urls.py delete mode 100644 osmchadjango/feature/views.py diff --git a/config/settings/common.py b/config/settings/common.py index 6aa95334..9fc34679 100644 --- a/config/settings/common.py +++ b/config/settings/common.py @@ -64,7 +64,6 @@ LOCAL_APPS = ( 'osmchadjango.users', # custom users app 'osmchadjango.changeset', - 'osmchadjango.feature', 'osmchadjango.supervise', 'osmchadjango.frontend', 'osmchadjango.roulette_integration', diff --git a/osmchadjango/changeset/management/commands/migrate_features.py b/osmchadjango/changeset/management/commands/migrate_features.py deleted file mode 100644 index 60d6f493..00000000 --- a/osmchadjango/changeset/management/commands/migrate_features.py +++ /dev/null @@ -1,109 +0,0 @@ -import json -from datetime import date, timedelta - -from django.core.management.base import BaseCommand -from django.db import transaction -from django.utils import timezone - -from ...models import Changeset - - -class Command(BaseCommand): - help = '''Convert the features of the changesets to the new JSONField - format. The changesets will be filtered according to the informed start - and end dates. - ''' - - def add_arguments(self, parser): - parser.add_argument('start_date', nargs='+', type=str) - parser.add_argument('end_date', nargs='+', type=str) - - def handle(self, *args, **options): - start_date = options['start_date'][0] - end_date = options['end_date'][0] - migrate_features(start_date, end_date) - - -def filtered_json(feature): - PRIMARY_TAGS = [ - 'aerialway', - 'aeroway', - 'amenity', - 'barrier', - 'boundary', - 'building', - 'craft', - 'emergency', - 'geological', - 'highway', - 'historic', - 'landuse', - 'leisure', - 'man_made', - 'military', - 'natural', - 'office', - 'place', - 'power', - 'public_transport', - 'railway', - 'route', - 'shop', - 'tourism', - 'waterway' - ] - data = { - "osm_id": feature.osm_id, - "url": "{}-{}".format(feature.osm_type, feature.osm_id), - "version": feature.osm_version, - "reasons": [reason.id for reason in feature.reasons.all()] - } - - - try: - if 'properties' in json.loads(feature.geojson).keys(): - properties = json.loads(feature.geojson)['properties'] - if 'name' in properties.keys(): - data['name'] = properties['name'] - - [ - properties.pop(key) for key in list(properties.keys()) - if key not in PRIMARY_TAGS - ] - data['primary_tags'] = properties - except TypeError: - if 'properties' in feature.geojson.keys(): - properties = feature.geojson['properties'] - if 'name' in properties.keys(): - data['name'] = properties['name'] - - [ - properties.pop(key) for key in list(properties.keys()) - if key not in PRIMARY_TAGS - ] - data['primary_tags'] = properties - - return data - - -def migrate_features(start_date, end_date): - last_changeset_date = Changeset.objects.order_by('-date')[0].date - changesets = Changeset.objects.filter( - features__isnull=False, - date__gte=start_date, - date__lte=end_date, - new_features=[] - ).prefetch_related('features').order_by('id').distinct() - changeset_count = changesets.count() - migrated = 0 - print('{} changesets to migrate'.format(changesets.count())) - while migrated < changeset_count: - with transaction.atomic(): - for changeset in changesets[migrated : migrated + 1000]: - new_features_data = [ - filtered_json(feature) for feature in changeset.features.all() - ] - changeset.new_features = new_features_data - changeset.save(update_fields=['new_features']) - print('{}-{} changesets migrated'.format(migrated, migrated + 1000)) - migrated += 1000 diff --git a/osmchadjango/changeset/migrations/0030_auto_20170201_1617.py b/osmchadjango/changeset/migrations/0030_auto_20170201_1617.py index 3c661b1c..545379b3 100644 --- a/osmchadjango/changeset/migrations/0030_auto_20170201_1617.py +++ b/osmchadjango/changeset/migrations/0030_auto_20170201_1617.py @@ -8,7 +8,6 @@ class Migration(migrations.Migration): dependencies = [ - ('feature', '0009_remove_feature_user_detail'), ('changeset', '0029_suspiciousfeature_timestamp'), ] diff --git a/osmchadjango/changeset/migrations/0040_auto_20170328_1350.py b/osmchadjango/changeset/migrations/0040_auto_20170328_1350.py index c4defbd5..a9c5333b 100644 --- a/osmchadjango/changeset/migrations/0040_auto_20170328_1350.py +++ b/osmchadjango/changeset/migrations/0040_auto_20170328_1350.py @@ -14,13 +14,9 @@ def merge_suspicionreasons(apps, schema_editor): if same_reasons.count() > 0: for same_reason in same_reasons: changesets = same_reason.changesets.all() - features = same_reason.features.all() for c in changesets: c.reasons.remove(same_reason) c.reasons.add(reason) - for f in features: - f.reasons.remove(same_reason) - f.reasons.add(reason) print("deleting %s" % same_reason.name) same_reason.delete() diff --git a/osmchadjango/changeset/migrations/0045_auto_20170410_1218.py b/osmchadjango/changeset/migrations/0045_auto_20170410_1218.py index 3b3ad87c..0d23faab 100644 --- a/osmchadjango/changeset/migrations/0045_auto_20170410_1218.py +++ b/osmchadjango/changeset/migrations/0045_auto_20170410_1218.py @@ -9,7 +9,6 @@ class Migration(migrations.Migration): dependencies = [ ('changeset', '0044_merge_20170330_1409'), - ('feature', '0012_feature_harmful_reasons'), ] operations = [ diff --git a/osmchadjango/feature/__init__.py b/osmchadjango/feature/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/osmchadjango/feature/admin.py b/osmchadjango/feature/admin.py deleted file mode 100644 index 8c38f3f3..00000000 --- a/osmchadjango/feature/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/osmchadjango/feature/filters.py b/osmchadjango/feature/filters.py deleted file mode 100644 index 497a2397..00000000 --- a/osmchadjango/feature/filters.py +++ /dev/null @@ -1,211 +0,0 @@ -from django.db.models import Count - -from rest_framework_gis.filterset import GeoFilterSet -from rest_framework_gis.filters import GeometryFilter -from django_filters import filters -from django_filters.widgets import BooleanWidget - -from .models import Feature - - -class FeatureFilter(GeoFilterSet): - """Filter Feature model objects.""" - geometry = GeometryFilter( - name='geometry', - lookup_expr='intersects', - help_text="""Geospatial filter of features whose geometry intersects with - another geometry. You can use any geometry type in this filter.""" - ) - checked = filters.BooleanFilter( - widget=BooleanWidget(), - help_text="""Filter features that were checked or not. Use true/false or - 1/0 values.""" - ) - changeset_checked = filters.BooleanFilter( - name='changeset__checked', - widget=BooleanWidget(), - help_text="""Filter features whose changeset is checked or not. Use - true/false or 1/0 values.""" - ) - harmful = filters.BooleanFilter( - widget=BooleanWidget(), - help_text="""Filter features that were marked as harmful or not harmful. - Use true/false or 1/0 values.""" - ) - users = filters.CharFilter( - name='changeset__user', - method='filter_changeset_users', - help_text="""Filter features whose last edit was made by a user. Use - commas to search for more than one username.""" - ) - uids = filters.CharFilter( - name='changeset__uid', - method='filter_changeset_uid', - help_text="""Filter features whose last edit was made by a user. Use - commas to search for more than one user uid. The uid is a unique - identifier of a OSM user.""" - ) - checked_by = filters.CharFilter( - name='check_user', - method='filter_check_users', - help_text="""Filter features that were checked by a user. Use commas to - search for more than one user.""" - ) - order_by = filters.CharFilter( - name=None, - method='order_queryset', - help_text="""Order the Features by one of the following fields: id, - osm_id, changeset__date, changeset_id, check_date or number_reasons. - Use a minus sign (-) before the field name to reverse the ordering. - Default ordering is '-changeset_id'.""" - ) - changeset_ids = filters.CharFilter( - name='changeset__id', - method='filter_changeset_ids', - help_text="""Filter features by its changeset id. Send the ids separated - by commas.""" - ) - osm_version__gte = filters.NumberFilter( - name='osm_version', - lookup_expr='gte', - help_text="""Filter items whose osm_version is greater than or equal to - a number.""" - ) - osm_version__lte = filters.NumberFilter( - name='osm_version', - lookup_expr='lte', - help_text="""Filter items whose osm_version is lower than or equal to a - number.""" - ) - osm_type = filters.CharFilter( - name='osm_type', - lookup_expr='exact', - help_text="""Filter features by its osm_type. The value options are node, - way or relation.""" - ) - date__gte = filters.DateTimeFilter( - name='changeset__date', - lookup_expr='gte', - help_text="""Filter features whose changeset date is greater than or - equal to a date or a datetime.""" - ) - date__lte = filters.DateTimeFilter( - name='changeset__date', - lookup_expr='lte', - help_text="""Filter features whose changeset date is lower than or equal - to a date or a datetime.""" - ) - check_date__gte = filters.DateTimeFilter( - name='check_date', - lookup_expr='gte', - help_text="""Filter features whose check_date is greater than or equal - to a date or a datetime.""" - ) - check_date__lte = filters.DateTimeFilter( - name='check_date', - lookup_expr='lte', - help_text="""Filter features whose check_date is lower than or equal to - a date or a datetime.""" - ) - editor = filters.CharFilter( - name='changeset__editor', - lookup_expr='icontains', - help_text="""Filter features that were created or last modified with a - software editor. The lookup expression used is 'icontains', so a - query for 'josm' will get features created or last modified with - all JOSM versions. - """ - ) - reasons = filters.CharFilter( - name='reasons', - method='filter_any_reasons', - help_text="""Filter features that have one or more of the Suspicion - Reasons. Inform the Suspicion Reasons ids separated by commas.""" - ) - all_reasons = filters.CharFilter( - name='reasons', - method='filter_all_reasons', - help_text="""Filter features that have ALL the Suspicion Reasons of a - list. Inform the Suspicion Reasons ids separated by commas.""" - ) - number_reasons__gte = filters.NumberFilter( - name='number_reasons', - method='filter_number_reasons', - help_text="""Filter features whose number of Suspicion Reasons is - equal or greater than a value.""" - ) - tags = filters.CharFilter( - name='tags', - method='filter_any_reasons', - help_text="""Filter features that have one or more of the Tags. Inform - the Tags ids separated by commas.""" - ) - all_tags = filters.CharFilter( - name='tags', - method='filter_all_reasons', - help_text="""Filter features that have ALL the Tags of a list. Inform - the Tags ids separated by commas.""" - ) - - def filter_changeset_users(self, queryset, name, value): - if (self.request is None or self.request.user.is_authenticated) and value: - lookup = '__'.join([name, 'in']) - users_array = [t.strip() for t in value.split(',')] - return queryset.filter(**{lookup: users_array}) - else: - return queryset - - def filter_changeset_uid(self, queryset, name, value): - if (self.request is None or self.request.user.is_authenticated) and value: - lookup = '__'.join([name, 'in']) - uids_array = [t.strip() for t in value.split(',')] - return queryset.filter(**{lookup: uids_array}) - else: - return queryset - - def filter_check_users(self, queryset, name, value): - if (self.request is None or self.request.user.is_authenticated) and value: - lookup = '__'.join([name, 'name', 'in']) - check_users_array = [t.strip() for t in value.split(',')] - return queryset.filter(**{lookup: check_users_array}) - else: - return queryset - - def filter_any_reasons(self, queryset, name, value): - lookup = '__'.join([name, 'id', 'in']) - values = [int(t) for t in value.split(',')] - return queryset.filter(**{lookup: values}).distinct() - - def filter_all_reasons(self, queryset, name, value): - lookup = '__'.join([name, 'id']) - values = [int(t) for t in value.split(',')] - for term in values: - queryset = queryset.filter(**{lookup: term}) - return queryset - - def filter_number_reasons(self, queryset, name, value): - lookup = '__'.join([name, 'gte']) - queryset = queryset.annotate(number_reasons=Count('reasons')) - return queryset.filter(**{lookup: value}) - - def order_queryset(self, queryset, name, value): - allowed_fields = [ - '-id', 'id', '-osm_id', 'osm_id', 'changeset__date', - '-changeset__date', 'changeset_id', 'check_date', '-check_date', - 'number_reasons', '-number_reasons' - ] - if value in allowed_fields: - if value in ['number_reasons', '-number_reasons']: - queryset = queryset.annotate(number_reasons=Count('reasons')) - return queryset.order_by(value) - else: - return queryset - - def filter_changeset_ids(self, queryset, name, value): - lookup = '__'.join([name, 'in']) - values = [int(t) for t in value.split(',')] - return queryset.filter(**{lookup: values}) - - class Meta: - model = Feature - fields = [] diff --git a/osmchadjango/feature/migrations/0001_initial.py b/osmchadjango/feature/migrations/0001_initial.py deleted file mode 100644 index 0e4dc6ae..00000000 --- a/osmchadjango/feature/migrations/0001_initial.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-10-05 12:31 -from __future__ import unicode_literals - -from django.conf import settings -import django.contrib.gis.db.models.fields -import django.contrib.postgres.fields.jsonb -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('changeset', '0029_suspiciousfeature_timestamp'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Feature', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('osm_id', models.IntegerField()), - ('geometry', django.contrib.gis.db.models.fields.GeometryField(srid=4326)), - ('geojson', django.contrib.postgres.fields.jsonb.JSONField()), - ('harmful', models.NullBooleanField()), - ('checked', models.BooleanField(default=False)), - ('check_date', models.DateTimeField(blank=True, null=True)), - ('score', models.IntegerField(blank=True, null=True)), - ('changeset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='changeset.Changeset')), - ('check_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ('reasons', models.ManyToManyField(related_name='features', to='changeset.SuspicionReasons')), - ('user_detail', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='changeset.UserDetail')), - ], - ), - ] diff --git a/osmchadjango/feature/migrations/0002_remove_feature_osm_id.py b/osmchadjango/feature/migrations/0002_remove_feature_osm_id.py deleted file mode 100644 index a2f9d2cc..00000000 --- a/osmchadjango/feature/migrations/0002_remove_feature_osm_id.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-10-07 10:50 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0001_initial'), - ] - - operations = [ - migrations.RemoveField( - model_name='feature', - name='osm_id', - ), - ] diff --git a/osmchadjango/feature/migrations/0003_auto_20161017_0655.py b/osmchadjango/feature/migrations/0003_auto_20161017_0655.py deleted file mode 100644 index d0393ee4..00000000 --- a/osmchadjango/feature/migrations/0003_auto_20161017_0655.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-10-17 06:55 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('changeset', '0029_suspiciousfeature_timestamp'), - ('feature', '0002_remove_feature_osm_id'), - ] - - operations = [ - migrations.AddField( - model_name='feature', - name='osm_id', - field=models.IntegerField(default=1234), - preserve_default=False, - ), - migrations.AddField( - model_name='feature', - name='osm_type', - field=models.CharField(default='way', max_length=1000), - preserve_default=False, - ), - migrations.AddField( - model_name='feature', - name='osm_version', - field=models.IntegerField(default=3), - preserve_default=False, - ), - migrations.AddField( - model_name='feature', - name='url', - field=models.SlugField(default='way-1234', max_length=1000), - preserve_default=False, - ), - migrations.AlterUniqueTogether( - name='feature', - unique_together=set([('changeset', 'osm_id', 'osm_type')]), - ), - ] diff --git a/osmchadjango/feature/migrations/0004_auto_20161019_0645.py b/osmchadjango/feature/migrations/0004_auto_20161019_0645.py deleted file mode 100644 index 4fa67ac5..00000000 --- a/osmchadjango/feature/migrations/0004_auto_20161019_0645.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-10-19 06:45 -from __future__ import unicode_literals - -import django.contrib.gis.db.models.fields -import django.contrib.postgres.fields.jsonb -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0003_auto_20161017_0655'), - ] - - operations = [ - migrations.AddField( - model_name='feature', - name='oldGeojson', - field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True), - ), - migrations.AddField( - model_name='feature', - name='oldGeometry', - field=django.contrib.gis.db.models.fields.GeometryField(blank=True, null=True, srid=4326), - ), - ] diff --git a/osmchadjango/feature/migrations/0005_auto_20161114_0543.py b/osmchadjango/feature/migrations/0005_auto_20161114_0543.py deleted file mode 100644 index 2a8b11de..00000000 --- a/osmchadjango/feature/migrations/0005_auto_20161114_0543.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-11-14 05:43 -from __future__ import unicode_literals - -import django.contrib.gis.db.models.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0004_auto_20161019_0645'), - ] - - operations = [ - migrations.AlterField( - model_name='feature', - name='geometry', - field=django.contrib.gis.db.models.fields.GeometryField(blank=True, null=True, srid=4326), - ), - ] diff --git a/osmchadjango/feature/migrations/0005_feature_osm_compare.py b/osmchadjango/feature/migrations/0005_feature_osm_compare.py deleted file mode 100644 index 33611307..00000000 --- a/osmchadjango/feature/migrations/0005_feature_osm_compare.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-10-26 11:17 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0004_auto_20161019_0645'), - ] - - operations = [ - migrations.AddField( - model_name='feature', - name='osm_compare', - field=models.CharField(blank=True, max_length=1000, null=True), - ), - ] diff --git a/osmchadjango/feature/migrations/0006_auto_20161026_1323.py b/osmchadjango/feature/migrations/0006_auto_20161026_1323.py deleted file mode 100644 index 9802f50f..00000000 --- a/osmchadjango/feature/migrations/0006_auto_20161026_1323.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-10-26 13:23 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0005_feature_osm_compare'), - ] - - operations = [ - migrations.RemoveField( - model_name='feature', - name='osm_compare', - ), - migrations.AddField( - model_name='feature', - name='comparator_version', - field=models.CharField(blank=True, max_length=1000, null=True), - ), - ] diff --git a/osmchadjango/feature/migrations/0007_merge_20161122_0858.py b/osmchadjango/feature/migrations/0007_merge_20161122_0858.py deleted file mode 100644 index ad5a51a7..00000000 --- a/osmchadjango/feature/migrations/0007_merge_20161122_0858.py +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-11-22 08:58 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0005_auto_20161114_0543'), - ('feature', '0006_auto_20161026_1323'), - ] - - operations = [ - ] diff --git a/osmchadjango/feature/migrations/0008_auto_20161124_0742.py b/osmchadjango/feature/migrations/0008_auto_20161124_0742.py deleted file mode 100644 index 7fe6151a..00000000 --- a/osmchadjango/feature/migrations/0008_auto_20161124_0742.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2016-11-24 07:42 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0007_merge_20161122_0858'), - ] - - operations = [ - migrations.AlterField( - model_name='feature', - name='osm_id', - field=models.BigIntegerField(), - ), - ] diff --git a/osmchadjango/feature/migrations/0009_remove_feature_user_detail.py b/osmchadjango/feature/migrations/0009_remove_feature_user_detail.py deleted file mode 100644 index cbc19ac1..00000000 --- a/osmchadjango/feature/migrations/0009_remove_feature_user_detail.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2017-02-01 16:17 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0008_auto_20161124_0742'), - ] - - operations = [ - migrations.RemoveField( - model_name='feature', - name='user_detail', - ), - ] diff --git a/osmchadjango/feature/migrations/0010_auto_20170207_1728.py b/osmchadjango/feature/migrations/0010_auto_20170207_1728.py deleted file mode 100644 index da20df29..00000000 --- a/osmchadjango/feature/migrations/0010_auto_20170207_1728.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2017-02-07 17:28 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0009_remove_feature_user_detail'), - ] - - operations = [ - migrations.RenameField( - model_name='feature', - old_name='oldGeojson', - new_name='old_geojson', - ), - migrations.RenameField( - model_name='feature', - old_name='oldGeometry', - new_name='old_geometry', - ), - ] diff --git a/osmchadjango/feature/migrations/0011_remove_feature_score.py b/osmchadjango/feature/migrations/0011_remove_feature_score.py deleted file mode 100644 index 8a01a73d..00000000 --- a/osmchadjango/feature/migrations/0011_remove_feature_score.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2017-02-07 17:30 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0010_auto_20170207_1728'), - ] - - operations = [ - migrations.RemoveField( - model_name='feature', - name='score', - ), - ] diff --git a/osmchadjango/feature/migrations/0012_feature_harmful_reasons.py b/osmchadjango/feature/migrations/0012_feature_harmful_reasons.py deleted file mode 100644 index 91c85d06..00000000 --- a/osmchadjango/feature/migrations/0012_feature_harmful_reasons.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2017-02-24 20:45 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('changeset', '0038_changeset_harmful_reasons'), - ('feature', '0011_remove_feature_score'), - ] - - operations = [ - migrations.AddField( - model_name='feature', - name='harmful_reasons', - field=models.ManyToManyField(related_name='features', to='changeset.HarmfulReason'), - ), - ] diff --git a/osmchadjango/feature/migrations/0013_auto_20170410_1218.py b/osmchadjango/feature/migrations/0013_auto_20170410_1218.py deleted file mode 100644 index 362ce9e2..00000000 --- a/osmchadjango/feature/migrations/0013_auto_20170410_1218.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2017-04-10 12:18 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0012_feature_harmful_reasons'), - ] - - operations = [ - migrations.AlterModelOptions( - name='feature', - options={'ordering': ['-changeset_id']}, - ), - migrations.RenameField( - model_name='feature', - old_name='harmful_reasons', - new_name='tags', - ), - ] diff --git a/osmchadjango/feature/migrations/0014_auto_20170417_1740.py b/osmchadjango/feature/migrations/0014_auto_20170417_1740.py deleted file mode 100644 index 2f18a60e..00000000 --- a/osmchadjango/feature/migrations/0014_auto_20170417_1740.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10 on 2017-04-17 17:40 -from __future__ import unicode_literals - -import django.contrib.gis.db.models.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0013_auto_20170410_1218'), - ] - - operations = [ - migrations.AlterField( - model_name='feature', - name='check_date', - field=models.DateTimeField(blank=True, db_index=True, null=True), - ), - migrations.AlterField( - model_name='feature', - name='checked', - field=models.BooleanField(db_index=True, default=False), - ), - migrations.AlterField( - model_name='feature', - name='geometry', - field=django.contrib.gis.db.models.fields.GeometryField(blank=True, null=True, srid=4326), - ), - migrations.AlterField( - model_name='feature', - name='harmful', - field=models.NullBooleanField(db_index=True), - ), - ] diff --git a/osmchadjango/feature/migrations/0015_auto_20170421_1939.py b/osmchadjango/feature/migrations/0015_auto_20170421_1939.py deleted file mode 100644 index c57e5327..00000000 --- a/osmchadjango/feature/migrations/0015_auto_20170421_1939.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.7 on 2017-04-21 19:39 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0014_auto_20170417_1740'), - ] - - operations = [ - migrations.AlterField( - model_name='feature', - name='changeset', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='features', to='changeset.Changeset'), - ), - ] diff --git a/osmchadjango/feature/migrations/0016_auto_20180307_1417.py b/osmchadjango/feature/migrations/0016_auto_20180307_1417.py deleted file mode 100644 index 18f147be..00000000 --- a/osmchadjango/feature/migrations/0016_auto_20180307_1417.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.0.3 on 2018-03-07 14:17 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('feature', '0015_auto_20170421_1939'), - ] - - operations = [ - migrations.AlterField( - model_name='feature', - name='check_user', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/osmchadjango/feature/migrations/__init__.py b/osmchadjango/feature/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/osmchadjango/feature/models.py b/osmchadjango/feature/models.py deleted file mode 100644 index e71a7802..00000000 --- a/osmchadjango/feature/models.py +++ /dev/null @@ -1,96 +0,0 @@ -from django.contrib.gis.db import models -from django.utils.translation import ugettext, ugettext_lazy as _ -from django.contrib.postgres.fields import JSONField - -from ..users.models import User - - -class Feature(models.Model): - changeset = models.ForeignKey( - 'changeset.Changeset', on_delete=models.CASCADE, related_name='features' - ) - osm_id = models.BigIntegerField() - osm_type = models.CharField(max_length=1000) - osm_version = models.IntegerField() - geometry = models.GeometryField(null=True, blank=True) - old_geometry = models.GeometryField(null=True, blank=True) - geojson = JSONField() - old_geojson = JSONField(null=True, blank=True) - reasons = models.ManyToManyField( - 'changeset.SuspicionReasons', related_name='features') - tags = models.ManyToManyField( - 'changeset.Tag', related_name='features') - harmful = models.NullBooleanField(db_index=True) - checked = models.BooleanField(default=False, db_index=True) - check_user = models.ForeignKey( - User, on_delete=models.SET_NULL, null=True, blank=True, db_index=True - ) - check_date = models.DateTimeField(null=True, blank=True, db_index=True) - url = models.SlugField(max_length=1000, db_index=True) - comparator_version = models.CharField(max_length=1000, blank=True, null=True) - - class Meta: - unique_together = ('changeset', 'osm_id', 'osm_type',) - ordering = ['-changeset_id'] - - def __str__(self): - return '{} {} v{}'.format(self.osm_type, self.osm_id, self.osm_version) - - def osm_link(self): - """Return the link to the feature page on OSM website.""" - return 'https://www.openstreetmap.org/%s/%s' % (self.osm_type, self.osm_id) - - @property - def all_tags(self): - geojson = self.geojson - tags = [] - for key, value in geojson['properties'].items(): - record = {} - record["tag"] = key - record["Value"] = value - tags.append(record) - return tags - - @property - def diff_tags(self): - geojson = self.geojson - old_geojson = self.old_geojson - modified_tags = [] - deleted_tags = [] - added_tags = [] - unmodified_tags = [] - tags = {} - if old_geojson and old_geojson['properties']: - old_props = old_geojson['properties'] - else: - old_props = {} - for key, value in old_props.items(): - if 'osm:' not in key and 'result:' not in key: - if key in geojson['properties']: - record = {} - record["tag"] = key - record["oldValue"] = value - record["newValue"] = geojson['properties'][key] - if value != geojson['properties'][key]: - modified_tags.append(record) - else: - unmodified_tags.append(record) - else: - record = {} - record["tag"] = key - record["Value"] = value - deleted_tags.append(record) - - for key, value in geojson['properties'].items(): - if 'osm:' not in key and 'result:' not in key: - if key not in old_props: - record = {} - record["tag"] = key - record["Value"] = value - added_tags.append(record) - - tags["modified"] = modified_tags - tags["deleted"] = deleted_tags - tags["added"] = added_tags - tags["unmodified"] = unmodified_tags - return tags diff --git a/osmchadjango/feature/serializers.py b/osmchadjango/feature/serializers.py deleted file mode 100644 index b7e8f96f..00000000 --- a/osmchadjango/feature/serializers.py +++ /dev/null @@ -1,68 +0,0 @@ -from rest_framework.fields import ReadOnlyField, SerializerMethodField -from rest_framework.serializers import ( - ModelSerializer, PrimaryKeyRelatedField - ) -from rest_framework_gis.serializers import GeoFeatureModelSerializer - -from ..changeset.models import Tag -from ..changeset.serializers import ( - BasicTagSerializer, BasicSuspicionReasonsSerializer - ) -from .models import Feature - - -class FeatureSerializerToStaff(GeoFeatureModelSerializer): - check_user = ReadOnlyField(source='check_user.name', default=None) - changeset = ReadOnlyField(source='changeset.id') - date = ReadOnlyField(source='changeset.date') - source = ReadOnlyField(source='changeset.source') - imagery_used = ReadOnlyField(source='changeset.imagery_used') - editor = ReadOnlyField(source='changeset.editor') - comment = ReadOnlyField(source='changeset.comment') - reasons = BasicSuspicionReasonsSerializer(many=True, read_only=True) - tags = BasicTagSerializer(many=True, read_only=True) - osm_link = SerializerMethodField() - - class Meta: - model = Feature - geo_field = 'geometry' - exclude = ('comparator_version',) - - def get_osm_link(self, obj): - return obj.osm_link() - - -class FeatureSerializer(FeatureSerializerToStaff): - reasons = SerializerMethodField() - tags = SerializerMethodField() - - def get_reasons(self, obj): - return BasicSuspicionReasonsSerializer( - obj.reasons.filter(is_visible=True), - many=True, - read_only=True - ).data - - def get_tags(self, obj): - return BasicTagSerializer( - obj.tags.filter(is_visible=True), - many=True, - read_only=True - ).data - - -class FeatureSerializerToUnauthenticated(FeatureSerializer): - check_user = None - - class Meta: - model = Feature - geo_field = 'geometry' - exclude = ('comparator_version', 'check_user') - - -class FeatureTagsSerializer(ModelSerializer): - tags = PrimaryKeyRelatedField(many=True, queryset=Tag.objects.all()) - - class Meta: - model = Feature - fields = ('tags',) diff --git a/osmchadjango/feature/templates/feature/confirm_modify.html b/osmchadjango/feature/templates/feature/confirm_modify.html deleted file mode 100644 index 89720b65..00000000 --- a/osmchadjango/feature/templates/feature/confirm_modify.html +++ /dev/null @@ -1,17 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} - -{% block title %}{% blocktrans %}OSMCHA - Mark Feature {{ feature }} as {{ modification }}?{% endblocktrans %}{% endblock %} - -{% block content %} -

{% blocktrans %}Do you really want to mark the feature {{ feature }} as {{ modification }}?{% endblocktrans %}

- {% if modification == 'harmful' %} - - {% endif %} -
{% csrf_token %} - - {% trans "No, don't mark it as" %} {{ modification }} -
-{% endblock content %} diff --git a/osmchadjango/feature/templates/feature/feature_detail.html b/osmchadjango/feature/templates/feature/feature_detail.html deleted file mode 100644 index aa2d8637..00000000 --- a/osmchadjango/feature/templates/feature/feature_detail.html +++ /dev/null @@ -1,467 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load i18n %} - -{% block title %}OSMCHA - Feature {{ feature.osm_id }}{% endblock %} - -{% block content %} -
-
-

Feature {{ feature.osm_id }} by {{ feature.changeset.user }} on {{ feature.changeset.date }}

-

Changeset #{{ feature.changeset.id }} -

-
-
-

- {% for reason in feature.reasons.all %} - {{ reason.name|capfirst }} - {% endfor %} -

-
-
-
-
-
- - {% trans 'Open in JOSM' %} - - - -
- - {% trans 'HDYC' %} - - {% if feature.checked %} - {% if feature.harmful %} - - {% blocktrans with check_user=feature.check_user.name%} - Verified by {{ check_user }} and marked as harmful - {% endblocktrans %} - {% else %} - - {% blocktrans with check_user=feature.check_user.name%} - Verified by {{ check_user }} and marked as good - {% endblocktrans %} - {% endif %} - {% else %} -
- - -
- {% endif %} -
-
-
-
-
-
-
-

{% trans 'Version' %}

-

{{ feature.osm_version }}

-
-
-

{% trans 'Source' %}

-

{{ feature.changeset.source }}

-
-
-

{% trans 'Comment' %}

-

{{ feature.changeset.comment }}

-
-
-

{% trans 'Imagery used' %}

-

{{ feature.changeset.imagery_used }}

-
-
-

{% trans 'Editor' %}

-

{{ feature.changeset.editor }}

-
-
-
-
-
-
-
-
- - - - - - - - - - {% for record in feature.diff_tags.added %} - - - - - - {% endfor %} - {% for record in feature.diff_tags.deleted %} - - - - - - {% endfor %} - {% for record in feature.diff_tags.modified %} - - - - - - {% endfor %} - -
{% trans 'Tags' %}{% trans '' %}{% trans '' %}
- {{record.tag}} - {{record.Value}}ADDED
- {{record.tag}} - {{record.Value}}DELETED
- {{record.tag}} - {{record.oldValue}}{{record.newValue}}
-
-
- -
-
- - - {% for record in feature.diff_tags.unmodified %} - - - - - - {% endfor %} - -
- {{record.tag}} - {{record.oldValue}}{{record.newValue}}
-
-
-
-
-
-
-
-
-

- -

-
-
- {% if request.user.is_authenticated and not feature.checked %} - - - - {% endif %} - -{% endblock content %} - -{% block javascript %} - {{ block.super }} - - - - - - - -{% endblock javascript %} diff --git a/osmchadjango/feature/templates/feature/feature_list.html b/osmchadjango/feature/templates/feature/feature_list.html deleted file mode 100644 index 1788dea7..00000000 --- a/osmchadjango/feature/templates/feature/feature_list.html +++ /dev/null @@ -1,224 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% load i18n %} -{% load cache %} - -{% block title %}{% trans 'OSMCHA - Feature List' %}{% endblock %} - -{% block content %} - - {% with cache_timeout=user.is_authenticated|yesno:"0,300" %} - {% cache cache_timeout features user.is_authenticated request.get_full_path %} - {% if search_title %} -

{{ search_title }}

- {% endif %} - {% if not hide_filters %} - -
-
- -
- -
-
- -
- - -
-
-
- -
- -
-
- -
- -
- -
- -
- -
-
- -
- -
- -
- -
- -
-
- -
- -
- - -
- -
- - - -
-
- -
- -
- -
- -
- -
-
- -
-
- -
-
-
-
- - {% endif %} - {% if features %} -
- - - - - - - - - - - - - - {% for feature in features %} - - - - - - - - - - {% endfor %} - -
{% trans 'ID' %}{% trans 'Version' %}{% trans 'Date' %}{% trans 'User' %}{% trans 'Reasons' %}{% trans 'Verified' %}
- {{ feature.osm_id }} - {{ feature.osm_version }}{{ feature.changeset.date }} - - {{ feature.changeset.user }} - - {{ feature.changeset.reasons.all|join:", "|capfirst }} - {% if feature.checked %} - - {% if feature.harmful %} - - {% else %} - - {% endif %} - {% else %} - - {% endif %} -
-
- {% else %} -
{% trans 'No features found.' %}
- {% endif %} - - {% load query_parameters %} - {% if paginator %} -

- {% trans 'Page' %} {{ page_obj.number }} {% trans 'of' %} {{ page_obj.paginator.num_pages }} -

- - {% endif %} - {% endcache %} - {% endwith %} -{% endblock content %} - -{% block javascript %} - - {{ block.super }} - - - -{% endblock %} diff --git a/osmchadjango/feature/templates/feature/not_allowed.html b/osmchadjango/feature/templates/feature/not_allowed.html deleted file mode 100644 index 11cc1d7d..00000000 --- a/osmchadjango/feature/templates/feature/not_allowed.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} - -{% block title %}OSMCHA - Operation Not Allowed{% endblock %} - -{% block content %} -

{% trans 'Not Allowed' %}

-

{% trans 'You are the author of this feature, so you can not verify this feature' %}

-{% endblock content %} diff --git a/osmchadjango/feature/urls.py b/osmchadjango/feature/urls.py deleted file mode 100644 index a145c547..00000000 --- a/osmchadjango/feature/urls.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -from django.conf.urls import re_path - -from . import views - - -app_name = 'feature' -urlpatterns = [ - re_path( - r'^features/$', - view=views.FeatureListAPIView.as_view(), - name='list' - ), - re_path( - r'^features/(?P\d+)-(?P[a-zA-Z0-9-]+)/$', - view=views.FeatureDetailAPIView.as_view(), - name='detail' - ), - # re_path( - # r'^features/create/$', - # view=views.create_feature, - # name='create' - # ), - re_path( - r'^features/(?P\d+)-(?P[a-zA-Z0-9-]+)/set-harmful/$', - view=views.CheckFeature.as_view({'put': 'set_harmful'}), - name='set-harmful' - ), - re_path( - r'^features/(?P\d+)-(?P[a-zA-Z0-9-]+)/set-good/$', - view=views.CheckFeature.as_view({'put': 'set_good'}), - name='set-good' - ), - re_path( - r'^features/(?P\d+)-(?P[a-zA-Z0-9-]+)/uncheck/$', - view=views.uncheck_feature, - name='uncheck' - ), - re_path( - r'^features/(?P\d+)-(?P[a-zA-Z0-9-]+)/tags/(?P\w+)/$', - view=views.AddRemoveFeatureTagsAPIView.as_view( - {'post': 'add_tag', 'delete': 'remove_tag'} - ), - name='tags' - ), -] diff --git a/osmchadjango/feature/views.py b/osmchadjango/feature/views.py deleted file mode 100644 index 1aa3cda6..00000000 --- a/osmchadjango/feature/views.py +++ /dev/null @@ -1,403 +0,0 @@ -import json -from datetime import datetime - -from django.utils import timezone -from django.db import IntegrityError -from django.contrib.gis.geos import GEOSGeometry -from django.contrib.gis.gdal.error import GDALException - -import django_filters.rest_framework -from rest_framework.generics import ( - ListAPIView, RetrieveAPIView, get_object_or_404 - ) -from rest_framework.decorators import ( - api_view, parser_classes, permission_classes, action, throttle_classes - ) -from rest_framework.parsers import JSONParser, MultiPartParser, FormParser -from rest_framework.permissions import IsAuthenticated, IsAdminUser -from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer -from rest_framework.response import Response -from rest_framework.viewsets import ModelViewSet -from rest_framework import status -from rest_framework_gis.filters import InBBoxFilter - -from ..changeset import models as changeset_models -from ..changeset.views import ( - StandardResultsSetPagination, PaginatedCSVRenderer, NonStaffUserThrottle - ) - -from .models import Feature -from .filters import FeatureFilter -from .serializers import ( - FeatureSerializer, FeatureSerializerToStaff, FeatureTagsSerializer, - FeatureSerializerToUnauthenticated - ) - - -class FeatureListAPIView(ListAPIView): - """List Features. It can be filtered using the 'location' parameter, which can - receive any valid geometry, or using the 'in_bbox' filter, which must receive - the min Lat, min Lon, max Lat, max Lon values. It's also possible to filter - using other fields. The default pagination returns 50 objects by page. - """ - queryset = Feature.objects.all().select_related( - 'check_user', 'changeset' - ).prefetch_related('reasons', 'tags') - serializer_class = FeatureSerializer - pagination_class = StandardResultsSetPagination - renderer_classes = (JSONRenderer, BrowsableAPIRenderer, PaginatedCSVRenderer) - bbox_filter_field = 'geometry' - filter_backends = ( - InBBoxFilter, - django_filters.rest_framework.DjangoFilterBackend, - ) - bbox_filter_include_overlapping = True - filter_class = FeatureFilter - - def get_serializer_class(self): - if self.request.user.is_staff: - return FeatureSerializerToStaff - elif self.request.user.is_authenticated: - return FeatureSerializer - else: - return FeatureSerializerToUnauthenticated - - -class FeatureDetailAPIView(RetrieveAPIView): - '''Get details of a Feature object. Type: GeoJSON''' - queryset = Feature.objects.all().select_related( - 'check_user', 'changeset' - ).prefetch_related('reasons', 'tags') - - def get_object(self): - changeset = self.kwargs['changeset'] - url = self.kwargs['slug'] - return get_object_or_404(Feature, changeset=changeset, url=url) - - def get_serializer_class(self): - if self.request.user.is_staff: - return FeatureSerializerToStaff - elif self.request.user.is_authenticated: - return FeatureSerializer - else: - return FeatureSerializerToUnauthenticated - - -@api_view(['POST']) -@throttle_classes((NonStaffUserThrottle,)) -@parser_classes((JSONParser, MultiPartParser, FormParser)) -@permission_classes((IsAuthenticated, IsAdminUser)) -def create_feature(request): - '''Create Suspicion Features. It was designed to receive vandalism-dynamosm - json output. Only staff users have permissions to create features. You can - use the django admin to get a Token to the user you want to use to created - features. - ''' - feature = request.data - - if 'properties' not in feature.keys(): - return Response( - {'detail': 'Expecting a single GeoJSON feature.'}, - status=status.HTTP_400_BAD_REQUEST - ) - properties = feature.get('properties', {}) - changeset_id = properties.get('osm:changeset') - - if not changeset_id: - return Response( - {'detail': 'osm:changeset field is missing.'}, - status=status.HTTP_400_BAD_REQUEST - ) - - defaults = { - 'osm_id': properties['osm:id'], - 'osm_type': properties['osm:type'], - 'url': '{}-{}' .format(properties['osm:type'], properties['osm:id']), - 'osm_version': properties['osm:version'], - 'comparator_version': feature.get('comparator_version'), - } - - try: - defaults['geometry'] = GEOSGeometry(json.dumps(feature['geometry'])) - except (GDALException, ValueError, TypeError) as e: - return Response( - {'detail': '{} in geometry field of feature {}'.format(e, properties['osm:id'])}, - status=status.HTTP_400_BAD_REQUEST - ) - - if 'oldVersion' in properties.keys(): - try: - defaults['old_geometry'] = GEOSGeometry( - json.dumps(properties['oldVersion']['geometry']) - ) - except (GDALException, ValueError, TypeError, KeyError) as e: - print( - '{} in oldVersion.geometry field of feature {}'.format( - e, properties['osm:id'] - ) - ) - defaults['old_geojson'] = feature['properties'].pop('oldVersion') - - # Each changed feature should have a 'suspicions' array of objects in its properties - print( - 'Creating feature {} of changeset {}.'.format( - properties['osm:id'], changeset_id - ) - ) - suspicions = feature['properties'].pop('suspicions') - has_visible_features = False - if suspicions: - reasons = set() - for suspicion in suspicions: - if suspicion.get('is_visible') is False: - is_visible = False - else: - has_visible_features = True - is_visible = True - reason, created = changeset_models.SuspicionReasons.objects.get_or_create( - name=suspicion['reason'], - defaults={'is_visible': is_visible} - ) - reasons.add(reason) - - changeset_defaults = { - 'date': datetime.utcfromtimestamp(properties.get('osm:timestamp') / 1000), - 'uid': properties.get('osm:uid'), - 'is_suspect': has_visible_features - } - - changeset, created = changeset_models.Changeset.objects.get_or_create( - id=changeset_id, - defaults=changeset_defaults - ) - - if not changeset.is_suspect and has_visible_features: - changeset.is_suspect = True - changeset.save(update_fields=['is_suspect']) - - print( - 'Changeset {} {}'.format(changeset_id, 'created' if created else 'updated') - ) - - try: - changeset.reasons.add(*reasons) - except IntegrityError: - # This most often happens due to a race condition, - # where two processes are saving to the same changeset - # In this case, we can safely ignore this attempted DB Insert, - # since what we wanted inserted has already been done through - # a separate web request. - print('IntegrityError with changeset %s' % changeset_id) - except ValueError as e: - print('ValueError with changeset %s' % changeset_id) - - defaults['geojson'] = feature - suspicious_feature, created = Feature.objects.get_or_create( - osm_id=properties['osm:id'], - changeset=changeset, - defaults=defaults - ) - print( - 'Feature {} {}.'.format( - properties['osm:id'], 'created' if created else 'updated' - ) - ) - - try: - suspicious_feature.reasons.add(*reasons) - except IntegrityError: - # This most often happens due to duplicates in dynamosm stream - print('Integrity error with feature %s' % suspicious_feature.osm_id) - except ValueError as e: - print('Value error with feature %s' % suspicious_feature.osm_id) - - return Response( - {'detail': 'Feature created.'}, - status=status.HTTP_201_CREATED - ) - - -class CheckFeature(ModelViewSet): - queryset = Feature.objects.all() - serializer_class = FeatureTagsSerializer - permission_classes = (IsAuthenticated,) - throttle_classes = (NonStaffUserThrottle,) - - def update_feature(self, feature, request, harmful): - """Update the feature fields and return a 200 Response """ - feature.checked = True - feature.harmful = harmful - feature.check_user = request.user - feature.check_date = timezone.now() - feature.save( - update_fields=['checked', 'harmful', 'check_user', 'check_date'] - ) - return Response( - {'detail': 'Feature marked as {}.'.format('harmful' if harmful else 'good')}, - status=status.HTTP_200_OK - ) - - @action(detail=True, methods=['put']) - def set_harmful(self, request, changeset, slug): - """Mark a feature as harmful. You can set the tags of the feature by sending - a list of tag ids inside a field named 'tags' in the request data. If - you don't want to set the 'tags', you don't need to send data, just - make an empty PUT request. - """ - feature = get_object_or_404(Feature, changeset=changeset, url=slug) - if feature.checked: - return Response( - {'detail': 'Feature was already checked.'}, - status=status.HTTP_403_FORBIDDEN - ) - if feature.changeset.uid in request.user.social_auth.values_list('uid', flat=True): - return Response( - {'detail': 'User can not check his own feature.'}, - status=status.HTTP_403_FORBIDDEN - ) - if request.data: - serializer = FeatureTagsSerializer(data=request.data) - if serializer.is_valid(): - feature.tags.set(serializer.data['tags']) - else: - return Response( - serializer.errors, - status=status.HTTP_400_BAD_REQUEST - ) - return self.update_feature(feature, request, harmful=True) - - @action(detail=True, methods=['put']) - def set_good(self, request, changeset, slug): - """Mark a feature as good. You can set the tags of the feature by sending - a list of tag ids inside a field named 'tags' in the request data. If - you don't want to set the 'tags', you don't need to send data, just - make an empty PUT request. - """ - feature = get_object_or_404(Feature, changeset=changeset, url=slug) - if feature.checked: - return Response( - {'detail': 'Feature was already checked.'}, - status=status.HTTP_403_FORBIDDEN - ) - if feature.changeset.uid in request.user.social_auth.values_list('uid', flat=True): - return Response( - {'detail': 'User can not check his own feature.'}, - status=status.HTTP_403_FORBIDDEN - ) - if request.data: - serializer = FeatureTagsSerializer(data=request.data) - if serializer.is_valid(): - feature.tags.set(serializer.data['tags']) - else: - return Response( - serializer.errors, - status=status.HTTP_400_BAD_REQUEST - ) - return self.update_feature(feature, request, harmful=False) - - -@api_view(['PUT']) -@parser_classes((JSONParser, MultiPartParser, FormParser)) -@permission_classes((IsAuthenticated,)) -def uncheck_feature(request, changeset, slug): - """Mark a feature as unchecked. You don't need to send data, just an empty - PUT request. - """ - instance = get_object_or_404(Feature, changeset=changeset, url=slug) - if instance.checked is False: - return Response( - {'detail': 'Feature is not checked.'}, - status=status.HTTP_403_FORBIDDEN - ) - elif request.user == instance.check_user or request.user.is_staff: - instance.checked = False - instance.harmful = None - instance.check_user = None - instance.check_date = None - instance.save( - update_fields=['checked', 'harmful', 'check_user', 'check_date'] - ) - return Response( - {'detail': 'Feature marked as unchecked.'}, - status=status.HTTP_200_OK - ) - else: - return Response( - {'detail': 'User does not have permission to uncheck this feature.'}, - status=status.HTTP_403_FORBIDDEN - ) - - -class AddRemoveFeatureTagsAPIView(ModelViewSet): - queryset = Feature.objects.all() - permission_classes = (IsAuthenticated,) - # The serializer is not used in this view. It's here only to avoid errors in - # docs schema generation. - serializer_class = FeatureTagsSerializer - - @action(detail=True, methods=['post']) - def add_tag(self, request, changeset, slug, tag_pk): - """Add a tag to a feature. If the feature is unchecked, any user can - add and remove tags. After the feature got checked, only staff users - and the user that checked it can add and remove tags. The user that - created the feature can't add or remove tags. - """ - feature = get_object_or_404( - Feature.objects.all(), - changeset=changeset, - url=slug - ) - tag = get_object_or_404( - changeset_models.Tag.objects.filter(for_feature=True), - pk=tag_pk - ) - - if feature.changeset.uid in request.user.social_auth.values_list('uid', flat=True): - return Response( - {'detail': 'User can not add tags to his own feature.'}, - status=status.HTTP_403_FORBIDDEN - ) - if feature.checked and ( - request.user != feature.check_user and not request.user.is_staff): - return Response( - {'detail': 'User can not add tags to a feature checked by another user.'}, - status=status.HTTP_403_FORBIDDEN - ) - - feature.tags.add(tag) - return Response( - {'detail': 'Tag added to the feature.'}, - status=status.HTTP_200_OK - ) - - @action(detail=True, methods=['delete']) - def remove_tag(self, request, changeset, slug, tag_pk): - """Remove a tag from a feature. If the feature is unchecked, any user can - add and remove tags. After the feature got checked, only staff users - and the user that checked it can add and remove tags. The user that - created the feature can't add or remove tags. - """ - feature = get_object_or_404( - Feature.objects.all(), - changeset=changeset, - url=slug - ) - tag = get_object_or_404(changeset_models.Tag.objects.all(), pk=tag_pk) - - if feature.changeset.uid in request.user.social_auth.values_list('uid', flat=True): - return Response( - {'detail': 'User can not remove tags from his own feature.'}, - status=status.HTTP_403_FORBIDDEN - ) - if feature.checked and ( - request.user != feature.check_user and not request.user.is_staff): - return Response( - {'detail': 'User can not remove tags of a feature checked by another user.'}, - status=status.HTTP_403_FORBIDDEN - ) - - feature.tags.remove(tag) - return Response( - {'detail': 'Tag removed from the feature.'}, - status=status.HTTP_200_OK - ) diff --git a/osmchadjango/supervise/models.py b/osmchadjango/supervise/models.py index be4545e9..6e8c1a90 100644 --- a/osmchadjango/supervise/models.py +++ b/osmchadjango/supervise/models.py @@ -5,7 +5,6 @@ from django.http.request import HttpRequest from osmchadjango.changeset.filters import ChangesetFilter -from osmchadjango.feature.filters import FeatureFilter from ..users.models import User @@ -36,18 +35,6 @@ def changesets(self, request=None): else: return qs - def features(self): - """Return the features that match the filters, including the geometry - of the AreaOfInterest. - """ - qs = FeatureFilter(self.filters).qs - if self.geometry is not None: - return qs.filter( - geometry__intersects=self.geometry - ) - else: - return qs - class Meta: unique_together = ('user', 'name',) ordering = ['-date']