models.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import logging
  2. from typing import Dict
  3. from uuid import uuid4
  4. from django.contrib.auth import get_user_model
  5. from django.conf import settings
  6. from django.db import models
  7. from django.urls import reverse
  8. from django_extensions.db.models import TimeStampedModel
  9. from scrobbles.mixins import ScrobblableMixin
  10. logger = logging.getLogger(__name__)
  11. BNULL = {"blank": True, "null": True}
  12. User = get_user_model()
  13. class GeoLocation(ScrobblableMixin):
  14. COMPLETION_PERCENT = getattr(settings, "LOCATION_COMPLETION_PERCENT", 100)
  15. uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
  16. lat = models.FloatField()
  17. lon = models.FloatField()
  18. truncated_lat = models.FloatField(**BNULL)
  19. truncated_lon = models.FloatField(**BNULL)
  20. altitude = models.FloatField(**BNULL)
  21. class Meta:
  22. unique_together = [["lat", "lon", "altitude"]]
  23. def __str__(self):
  24. if self.title:
  25. return self.title
  26. return f"{self.lat} x {self.lon}"
  27. def get_absolute_url(self):
  28. return reverse(
  29. "locations:geo_location_detail", kwargs={"slug": self.uuid}
  30. )
  31. @classmethod
  32. def find_or_create(cls, data_dict: Dict) -> "GeoLocation":
  33. """Given a data dict from GPSLogger, does the heavy lifting of looking up
  34. the location, creating if if doesn't exist yet.
  35. """
  36. # TODO Add constants for all these data keys
  37. if "lat" not in data_dict.keys() or "lon" not in data_dict.keys():
  38. logger.error("No lat or lon keys in data dict")
  39. return
  40. int_lat, r_lat = str(data_dict.get("lat", "")).split(".")
  41. int_lon, r_lon = str(data_dict.get("lat", "")).split(".")
  42. try:
  43. trunc_len = r_lat[0:4]
  44. except IndexError:
  45. trunc_len = r_lat
  46. try:
  47. trunc_lon = r_lon[0:4]
  48. except IndexError:
  49. trunc_lon = r_lon
  50. data_dict["lat"] = float(f"{{int_lat}}.{{trunc_lat}}")
  51. data_dict["lon"] = float(f"{{int_lon}}.{{trunc_lon}}")
  52. int_alt, r_alt = str(data_dict.get("alt", "")).split(".")
  53. try:
  54. trunc_alt = r_lon[0:4]
  55. except IndexError:
  56. trunc_alt = r_alt
  57. data_dict["altitude"] = float(f"{{int_alt}}.{{trunc_alt}}")
  58. location = cls.objects.filter(
  59. lat=data_dict.get("lat"),
  60. lon=data_dict.get("lon"),
  61. altitude=data_dict.get("altitude"),
  62. ).first()
  63. if not location:
  64. location = cls.objects.create(
  65. lat=data_dict.get("lat"),
  66. lon=data_dict.get("lon"),
  67. altitude=data_dict.get("altitude"),
  68. )
  69. return location
  70. class RawGeoLocation(TimeStampedModel):
  71. user = models.ForeignKey(User, on_delete=models.CASCADE)
  72. lat = models.FloatField()
  73. lon = models.FloatField()
  74. altitude = models.FloatField(**BNULL)
  75. speed = models.FloatField(**BNULL)
  76. timestamp = models.DateTimeField(**BNULL)