Ограничение базы данных на широту и долготу поля PointField с помощью бэкенда MySQL

У меня есть следующая модель Django:

class Place(models.Model):
    location = models.PointField(geography=True)

Поле location, похоже, с радостью принимает любое произвольное число для широты и долготы. Даже за пределами +-180 и +-90. Мои исследования говорят, что это происходит из-за того, что SRID не задан в колонке базы данных, хотя база данных была сгенерирована Django. Я считаю, что бэкенд MySQL просто не поддерживает правильную установку SRID на уровне базы данных.

Чтобы предотвратить возникновение проблем, я пытаюсь написать ограничения на поле. Однако, похоже, мне не удается сгенерировать рабочий объект ограничений. Идеальным результатом была бы проверка того, что lat & lng находятся в диапазоне поля extent объекта PointField, но я с радостью соглашусь и на жестко закодированные ограничения.

Альтернативное решение, позволяющее заставить базу данных соблюдать правильные ограничения lat & lng без каких-либо дополнительных ограничений Django, было бы очень признательно.

Я перепробовал множество итераций чего-то подобного. Я не нашел комбинации, которая сделала бы счастливыми и python, и MySQL.

class GeometryPointFunc(Func):
    template = "%(function)s(%(expressions)s::geometry)"

    def __init__(self, expression: any) -> None:
        super().__init__(expression, output_field=FloatField())


class Latitude(GeometryPointFunc):
    function = "ST_Y"


class Longitude(GeometryPointFunc):
    function = "ST_X"

...

class Meta:
    constraints = [models.CheckConstraint(condition=models.Q(Latitude("location")__lte=90), name="lat_lte_extent_lat")]
class Meta:
    constraints = [models.CheckConstraint(condition=models.Q(Latitude("location")<=90), name="lat_lte_extent_lat")]
class Meta:
    constraints = [models.CheckConstraint(condition=models.Q(90__gte=Latitude("location"), name="lat_lte_extent_lat")]

Если вы напишете Q(foo__lte=bar), то компилятор Django ORM в конечном итоге перепишет это в LessThanOrEqual(F('foo'), bar), поэтому мы можем использовать это для работы с ограничениями, которые не могут быть (легко) выражены с помощью Q объектов [Django-doc], мы можем использовать это, чтобы переписать ограничение в:

from django.db.models.lookups import LessThanOrEqual


class Place(models.Model):
    # …

    class Meta:
        constraints = [
            models.CheckConstraint(
                condition=LessThanOrEqual(Latitude('location'), 90),
                name='lat_lte_extent_lat',
            )
        ]
Вернуться на верх