Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.0.2 on 2026-02-13 23:08

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("market", "0004_rename_address_sublet_street_address_and_more"),
]

operations = [
migrations.AddField(
model_name="sublet",
name="latitude",
field=models.FloatField(blank=True, null=True),
),
migrations.AddField(
model_name="sublet",
name="longitude",
field=models.FloatField(blank=True, null=True),
),
]
46 changes: 45 additions & 1 deletion backend/market/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import hashlib
import math

from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator
Expand Down Expand Up @@ -42,7 +45,6 @@ class Meta:
def __str__(self):
return f"Offer for {self.listing} made by {self.user}"


class Category(models.Model):
name = models.CharField(max_length=100, unique=True)

Expand Down Expand Up @@ -131,11 +133,53 @@ class Sublet(Listing):
start_date = models.DateField()
end_date = models.DateField()

Comment thread
alisx255 marked this conversation as resolved.
Outdated
latitude = models.FloatField(null=True, blank=True)
longitude = models.FloatField(null=True, blank=True)


def clean(self):
super().clean()
if self.start_date and self.end_date and self.start_date >= self.end_date:
raise ValidationError({"end_date": "End date must be after start date"})

def _calculate_approximate_location(self, latitude, longitude):


if latitude is None or longitude is None:
Comment thread
alisx255 marked this conversation as resolved.
Outdated
return None, None

lat_str = f"{float(latitude):.9f}"
lon_str = f"{float(longitude):.9f}"
seed = hashlib.md5(f"{lat_str}{lon_str}".encode()).hexdigest()

offset_factor = int(seed[:8], 16) / 0xFFFFFFFF

offset_distance = 0.0005 + (offset_factor * 0.0013)
angle = offset_factor * 2 * math.pi

lat_offset = offset_distance * math.sin(angle)
lon_offset = offset_distance * math.cos(angle)

approx_lat = float(latitude) + lat_offset
approx_lon = float(longitude) + lon_offset
return approx_lat, approx_lon

@property
def approximate_latitude(self):
if self.latitude and self.longitude:
Comment thread
alisx255 marked this conversation as resolved.
Outdated
approximate_latitude, _ = self._calculate_approximate_location(
self.latitude, self.longitude)
return approximate_latitude
return None

@property
def approximate_longitude(self):
if self.latitude and self.longitude:
_, approximate_lon = self._calculate_approximate_location(
self.latitude, self.longitude)
return approximate_lon
return None

Comment thread
alisx255 marked this conversation as resolved.
def save(self, *args, **kwargs):
self.full_clean()
super().save(*args, **kwargs)
31 changes: 30 additions & 1 deletion backend/market/serializers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError as ModelValidationError
from profanity_check import predict
Expand Down Expand Up @@ -98,10 +99,23 @@ def get_condition(self, obj):


class SubletDataSerializer(ModelSerializer):
latitude = SerializerMethodField()
longitude = SerializerMethodField()

class Meta:
model = Sublet
fields = ["street_address", "beds", "baths", "start_date", "end_date"]
fields = ["street_address", "beds", "baths", "start_date", "end_date",
"latitude", "longitude"]

def get_latitude(self, obj):
if obj.approximate_latitude:
return float(obj.approximate_latitude)
return None

def get_longitude(self, obj):
if obj.approximate_longitude:
return float(obj.approximate_longitude)
return None

# Unified serializer for all listing types (Items and Sublets); used for CRUD operations
class ListingSerializer(ListingTypeMixin, ModelSerializer):
Expand Down Expand Up @@ -257,12 +271,23 @@ def _create_item(self, validated_data, additional_data):
def _create_sublet(self, validated_data, additional_data):
tags = validated_data.pop("tags", None)

latitude = additional_data.get("latitude")
longitude = additional_data.get("longitude")


if latitude is not None:
latitude = float(latitude)
if longitude is not None:
longitude = float(longitude)

sublet = Sublet.objects.create(
street_address=additional_data.get("street_address"),
beds=additional_data.get("beds"),
baths=additional_data.get("baths"),
start_date=additional_data.get("start_date"),
end_date=additional_data.get("end_date"),
latitude=latitude,
longitude=longitude,
**validated_data,
)

Expand Down Expand Up @@ -319,6 +344,10 @@ def _update_sublet(self, instance, additional_data):
for field in sublet_fields:
if field in additional_data:
setattr(sublet, field, additional_data[field])
if "latitude" in additional_data:
sublet.latitude = float(additional_data["latitude"])
if "longitude" in additional_data:
sublet.longitude = float(additional_data["longitude"])
sublet.full_clean()
Comment thread
alisx255 marked this conversation as resolved.
Outdated
sublet.save()

Expand Down