feat: Auto-add location to adoption notice
This commit is contained in:
parent
c8f65c9c54
commit
2a9dc337d2
@ -40,6 +40,7 @@ class AdoptionNoticeForm(forms.ModelForm):
|
||||
'name',
|
||||
'group_only',
|
||||
'searching_since',
|
||||
'location_string',
|
||||
'description',
|
||||
'further_information',
|
||||
),
|
||||
@ -47,7 +48,7 @@ class AdoptionNoticeForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = AdoptionNotice
|
||||
fields = ['name', "group_only", "further_information", "description", "searching_since"]
|
||||
fields = ['name', "group_only", "further_information", "description", "searching_since", "location_string"]
|
||||
|
||||
|
||||
class AnimalForm(forms.ModelForm):
|
||||
|
@ -0,0 +1,81 @@
|
||||
# Generated by Django 5.0.6 on 2024-06-05 13:19
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("fellchensammlung", "0006_announcement_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="location",
|
||||
name="country",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="location",
|
||||
name="description",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="location",
|
||||
name="postcode",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="adoptionnotice",
|
||||
name="location",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="fellchensammlung.location",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="adoptionnotice",
|
||||
name="location_string",
|
||||
field=models.CharField(
|
||||
default="72072", max_length=200, verbose_name="Ortsangabe"
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="location",
|
||||
name="latitude",
|
||||
field=models.FloatField(default=47),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="location",
|
||||
name="longitude",
|
||||
field=models.FloatField(default=9),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="location",
|
||||
name="osm_id",
|
||||
field=models.IntegerField(default=1),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="location",
|
||||
name="place_id",
|
||||
field=models.IntegerField(default=1),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="rescueorganization",
|
||||
name="location_string",
|
||||
field=models.CharField(
|
||||
default="72072", max_length=200, verbose_name="Ort der Organisation"
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="location",
|
||||
name="name",
|
||||
field=models.CharField(max_length=2000),
|
||||
),
|
||||
]
|
@ -66,19 +66,11 @@ class Location(models.Model):
|
||||
def __str__(self):
|
||||
return f"{self.name}"
|
||||
|
||||
GERMANY = "DE"
|
||||
AUSTRIA = "AT"
|
||||
SWITZERLAND = "CH"
|
||||
COUNTRIES_CHOICES = {
|
||||
GERMANY: "Germany",
|
||||
AUSTRIA: "Austria",
|
||||
SWITZERLAND: "Switzerland"
|
||||
}
|
||||
|
||||
name = models.CharField(max_length=200)
|
||||
postcode = models.CharField(max_length=200)
|
||||
country = models.CharField(max_length=20, choices=COUNTRIES_CHOICES)
|
||||
description = models.TextField(null=True, blank=True, verbose_name=_('Beschreibung'))
|
||||
place_id = models.IntegerField()
|
||||
osm_id = models.IntegerField()
|
||||
latitude = models.FloatField()
|
||||
longitude = models.FloatField()
|
||||
name = models.CharField(max_length=2000)
|
||||
|
||||
|
||||
class RescueOrganization(models.Model):
|
||||
@ -87,6 +79,7 @@ class RescueOrganization(models.Model):
|
||||
|
||||
name = models.CharField(max_length=200)
|
||||
trusted = models.BooleanField(default=False, verbose_name=_('Vertrauenswürdig'))
|
||||
location_string = models.CharField(max_length=200, verbose_name=_("Ort der Organisation"))
|
||||
location = models.ForeignKey(Location, on_delete=models.PROTECT)
|
||||
instagram = models.URLField(null=True, blank=True, verbose_name=_('Instagram Profil'))
|
||||
facebook = models.URLField(null=True, blank=True, verbose_name=_('Facebook Profil'))
|
||||
@ -112,6 +105,8 @@ class AdoptionNotice(models.Model):
|
||||
further_information = models.URLField(null=True, blank=True, verbose_name=_('Link zu mehr Informationen'))
|
||||
group_only = models.BooleanField(default=False, verbose_name=_('Ausschließlich Gruppenadoption'))
|
||||
photos = models.ManyToManyField(Image, blank=True)
|
||||
location_string = models.CharField(max_length=200, verbose_name=_("Ortsangabe"))
|
||||
location = models.ForeignKey(Location, blank=True, null=True, on_delete=models.SET_NULL,)
|
||||
|
||||
@property
|
||||
def animals(self):
|
||||
|
@ -1,6 +1,7 @@
|
||||
import requests
|
||||
import json
|
||||
from notfellchen import __version__ as nf_version
|
||||
from fellchensammlung.models import Location
|
||||
|
||||
from math import radians, sqrt, sin, cos, atan2
|
||||
|
||||
@ -21,13 +22,15 @@ def calculate_distance_between_coordinates(position1, position2):
|
||||
distance_lat = radians(latitude2 - latitude1)
|
||||
distance_long = radians(longitude2 - longitude1)
|
||||
|
||||
a = pow(sin(distance_lat / 2), 2) + cos(radians(latitude1)) * cos(radians(latitude2)) * pow(sin(distance_long / 2), 2)
|
||||
a = pow(sin(distance_lat / 2), 2) + cos(radians(latitude1)) * cos(radians(latitude2)) * pow(sin(distance_long / 2),
|
||||
2)
|
||||
c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
||||
|
||||
distance_in_km = earth_radius_km * c
|
||||
|
||||
return distance_in_km
|
||||
|
||||
|
||||
class ResponseMock:
|
||||
content = b'[{"place_id":138181499,"licence":"Data \xc2\xa9 OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright","osm_type":"relation","osm_id":1247237,"lat":"48.4949904","lon":"9.040330235970146","category":"boundary","type":"postal_code","place_rank":21, "importance":0.12006895017929346,"addresstype":"postcode","name":"72072","display_name":"72072, Derendingen, T\xc3\xbcbingen, Landkreis T\xc3\xbcbingen, Baden-W\xc3\xbcrttemberg, Deutschland", "boundingbox":["48.4949404","48.4950404","9.0402802","9.0403802"]}]'
|
||||
status_code = 200
|
||||
@ -43,21 +46,33 @@ class RequestMock:
|
||||
|
||||
|
||||
class GeoAPI:
|
||||
api_url = "https://nominatim.openstreetmap.org/search"
|
||||
headers = {
|
||||
'User-Agent': f"Notfellchen {nf_version}",
|
||||
'From': 'info@notfellchen.org' # This is another valid field
|
||||
}
|
||||
|
||||
def __init__(self, debug=True):
|
||||
self.api_url = "https://nominatim.openstreetmap.org/search"
|
||||
if debug:
|
||||
self.requests = RequestMock
|
||||
else:
|
||||
self.requests = requests
|
||||
|
||||
def get_coordinates_from_postcode(self, postcode):
|
||||
headers = {
|
||||
'User-Agent': f"Notfellchen {nf_version}",
|
||||
'From': 'info@notfellchen.org' # This is another valid field
|
||||
}
|
||||
result = self.requests.get(self.api_url, {"q": postcode, "format": "jsonv2"}, headers=headers).json()[0]
|
||||
result = self.requests.get(self.api_url, {"q": postcode, "format": "jsonv2"}, headers=self.headers).json()[0]
|
||||
return result["lat"], result["lon"]
|
||||
|
||||
def get_location_from_string(self, location_string):
|
||||
result = self.requests.get(self.api_url, {"q": location_string, "format": "jsonv2"}, headers=self.headers).json()[0]
|
||||
location = Location.objects.create(
|
||||
place_id=result["place_id"],
|
||||
osm_id=result["osm_id"],
|
||||
latitude=result["lat"],
|
||||
longitude=result["lon"],
|
||||
name=result["name"],
|
||||
)
|
||||
return location
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
geo = GeoAPI(debug=True)
|
||||
|
@ -27,7 +27,7 @@ urlpatterns = [
|
||||
# ex: /search/
|
||||
path("suchen/", views.search, name="search"),
|
||||
# ex: /vermitteln/
|
||||
path("vermitteln/", views.add_adoption, name="add-adoption"),
|
||||
path("vermitteln/", views.add_adoption_notice, name="add-adoption"),
|
||||
|
||||
path("ueber-uns/", views.about, name="about"),
|
||||
|
||||
|
@ -15,6 +15,7 @@ from fellchensammlung.models import AdoptionNotice, Text, Animal, Rule, Image, R
|
||||
Member
|
||||
from .forms import AdoptionNoticeForm, ImageForm, ReportAdoptionNoticeForm, CommentForm, ReportCommentForm, AnimalForm
|
||||
from .models import Language, Announcement
|
||||
from .tools.geo import GeoAPI
|
||||
|
||||
|
||||
def index(request):
|
||||
@ -93,12 +94,19 @@ def search(request):
|
||||
|
||||
|
||||
@login_required
|
||||
def add_adoption(request):
|
||||
def add_adoption_notice(request):
|
||||
if request.method == 'POST':
|
||||
form = AdoptionNoticeForm(request.POST, request.FILES, in_adoption_notice_creation_flow=True)
|
||||
|
||||
if form.is_valid():
|
||||
instance = form.save()
|
||||
|
||||
"""Search the location given in the location string and add it to the adoption notice"""
|
||||
geo_api = GeoAPI(debug=True)
|
||||
location = geo_api.get_location_from_string(instance.location_string)
|
||||
instance.location = location
|
||||
instance.save()
|
||||
|
||||
return redirect(reverse("adoption-notice-add-animal", args=[instance.pk]))
|
||||
else:
|
||||
form = AdoptionNoticeForm(in_adoption_notice_creation_flow=True)
|
||||
|
Loading…
Reference in New Issue
Block a user