From a88e364c6f7d7a70ba029bee62f6a898b84d5530 Mon Sep 17 00:00:00 2001 From: Dimas Date: Fri, 15 Sep 2023 10:06:39 +0700 Subject: [PATCH] Update add site visit api to accept occurrence photos --- bims/admin.py | 7 ++++ ...nimage_owner_taxonimage_survey_and_more.py | 36 +++++++++++++++++++ bims/models/taxonomy.py | 26 ++++++++++++++ mobile/api_views/add_site_visit.py | 25 +++++++++++++ mobile/api_views/river.py | 6 ++-- mobile/api_views/wetland.py | 4 ++- 6 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 bims/migrations/0348_taxonimage_date_taxonimage_owner_taxonimage_survey_and_more.py diff --git a/bims/admin.py b/bims/admin.py index b2a393e7b..dfd28ec97 100644 --- a/bims/admin.py +++ b/bims/admin.py @@ -1735,6 +1735,11 @@ def get_users(self, obj): filter_horizontal = ('users',) +class TaxonImageAdmin(admin.ModelAdmin): + list_display = ('taxonomy', 'source', 'date') + raw_id_fields = ('taxonomy', 'uploader', 'owner', 'survey') + + # Re-register GeoNode's Profile page admin.site.unregister(Profile) admin.site.register(Profile, CustomUserAdmin) @@ -1791,6 +1796,8 @@ def get_users(self, obj): admin.site.register(RequestLog, RequestLogAdmin) admin.site.register(IngestedData, IngestedDataAdmin) +admin.site.register(TaxonImage, TaxonImageAdmin) + admin.site.register(LocationContextGroup, LocationContextGroupAdmin) admin.site.register( LocationContextFilterGroupOrder, LocationContextFilterGroupOrderAdmin) diff --git a/bims/migrations/0348_taxonimage_date_taxonimage_owner_taxonimage_survey_and_more.py b/bims/migrations/0348_taxonimage_date_taxonimage_owner_taxonimage_survey_and_more.py new file mode 100644 index 000000000..43daa20b3 --- /dev/null +++ b/bims/migrations/0348_taxonimage_date_taxonimage_owner_taxonimage_survey_and_more.py @@ -0,0 +1,36 @@ +# Generated by Django 4.1.10 on 2023-09-15 02:48 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('bims', '0347_locationsite_hydrogeomorphic_type_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='taxonimage', + name='date', + field=models.DateField(blank=True, null=True), + ), + migrations.AddField( + model_name='taxonimage', + name='owner', + field=models.ForeignKey(blank=True, help_text='Owner of the taxon image (Optional)', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='taxon_image_owner', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='taxonimage', + name='survey', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='bims.survey'), + ), + migrations.AddField( + model_name='taxonimage', + name='uploader', + field=models.ForeignKey(blank=True, help_text='User who uploaded the taxon image (Optional)', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='taxon_image_uploader', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/bims/models/taxonomy.py b/bims/models/taxonomy.py index 7879dafa9..092359409 100644 --- a/bims/models/taxonomy.py +++ b/bims/models/taxonomy.py @@ -443,6 +443,32 @@ class TaxonImage(models.Model): blank=True, default='' ) + uploader = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.SET_NULL, + null=True, + blank=True, + help_text='User who uploaded the taxon image (Optional)', + related_name='taxon_image_uploader' + ) + owner = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.SET_NULL, + null=True, + blank=True, + help_text='Owner of the taxon image (Optional)', + related_name='taxon_image_owner' + ) + date = models.DateField( + null=True, + blank=True + ) + survey = models.ForeignKey( + 'bims.Survey', + null=True, + blank=True, + on_delete=models.CASCADE + ) def check_taxa_duplicates(taxon_name, taxon_rank): diff --git a/mobile/api_views/add_site_visit.py b/mobile/api_views/add_site_visit.py index 5d335033e..2bebcb776 100644 --- a/mobile/api_views/add_site_visit.py +++ b/mobile/api_views/add_site_visit.py @@ -3,6 +3,7 @@ from bims.models.chemical_record import ChemicalRecord from bims.models.survey import Survey +from bims.models.taxonomy import TaxonImage from django.core.files.base import ContentFile from django.http import Http404 from rest_framework.permissions import IsAuthenticated @@ -77,6 +78,30 @@ def post(self, request, *args, **kwargs): survey.mobile = True survey.save() + occurrence_photos = post_data.get('occurrence_photos', None) + if occurrence_photos: + for occurrence_photo in occurrence_photos: + occurrence_photo_file_name = ( + f'{post_data["date"]}_{request.user.id}_' + f'{occurrence_photo["id"]}.jpeg' + ) + base_64_string = occurrence_photo['base64Image'] + header, image_data = base_64_string.split(",")[0], base_64_string.split(",")[1] + occurrence_photo_file = ContentFile( + base64.b64decode( + image_data, + ), + name=occurrence_photo_file_name + ) + TaxonImage.objects.create( + taxonomy_id=occurrence_photo['id'], + survey_id=survey.id, + taxon_image=occurrence_photo_file, + date=post_data.get('date'), + uploader=request.user, + source='Mobile App' + ) + process_abiotic_data( survey, post_data.get('abiotic', []) diff --git a/mobile/api_views/river.py b/mobile/api_views/river.py index b2d1eddc5..c49ce03a2 100644 --- a/mobile/api_views/river.py +++ b/mobile/api_views/river.py @@ -1,4 +1,4 @@ -from guardian.mixins import LoginRequiredMixin +from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView @@ -6,7 +6,9 @@ from sass.models import River -class FetchRiverName(LoginRequiredMixin, APIView): +class FetchRiverName(APIView): + permission_classes = (IsAuthenticated,) + def get(self, request, *args): lat = request.GET.get('lat', '') lon = request.GET.get('lon', '') diff --git a/mobile/api_views/wetland.py b/mobile/api_views/wetland.py index 04dd3d069..7379fb98a 100644 --- a/mobile/api_views/wetland.py +++ b/mobile/api_views/wetland.py @@ -1,6 +1,7 @@ from typing import Union, Dict from guardian.mixins import LoginRequiredMixin +from rest_framework.permissions import IsAuthenticated from rest_framework.views import APIView from rest_framework.response import Response @@ -46,7 +47,8 @@ def fetch_wetland_data(latitude: float, longitude: float) -> Union[Dict, None]: return wetland -class FetchWetland(LoginRequiredMixin, APIView): +class FetchWetland(APIView): + permission_classes = (IsAuthenticated,) def get(self, request, *args): lat = float(request.GET.get('lat', '0'))