Слой OpenStreetMap в обратных координатах OSMGeoAdmin

В моем приложении django у меня отображается карта, когда я нахожусь в админке, благодаря классу OSMGeoAdmin (из django.contrib.gis.admin), единственная проблема заключается в том, что эта карта меняет координаты GPS (широта, долгота).

Пример: точка (48, 2) должна указывать на Орлеан (во Франции), а не на точку (2, 48), которая находится рядом с Сомали.

Это не проблема для сервера, но это когда я хочу проверить эти координаты.

Может ли кто-нибудь помочь мне с этой проблемой, пожалуйста?


person Depado    schedule 02.09.2013    source источник
comment
Почему ты не можешь просто отменить свой чек?   -  person scai    schedule 02.09.2013
comment
Я не понимаю вашего вопроса. Карта интерпретирует координаты в неправильном порядке (долгота, широта) вместо (широта, долгота), и я не знаю, почему и как это изменить.   -  person Depado    schedule 02.09.2013
comment
Почему это плохой заказ? Различные программы имеют разные порядки. См. Предпочитаемый порядок записи кортежей широты и долготы. Вам нужно либо соответствующим образом изменить приложение django, либо источник ваших значений lat, lon.   -  person scai    schedule 02.09.2013
comment
Я понимаю. Я думал, что это стандарт использовать широту, а затем долготу. Есть ли способ заставить OpenStreetMap изменить координаты?   -  person Depado    schedule 02.09.2013
comment
Откуда именно вы берете свои координаты? OpenStreetMap - это в основном база данных, в ней нет порядка широты и долготы.   -  person scai    schedule 02.09.2013
comment
Мои координаты хранятся в моей базе данных. OpenStreetMap — это просто слой в админке Django, который отображает карту в соответствии с GPS-координатами, найденными в БД. Но я знаю, что мои координаты верны, я проверял их несколько раз раньше.   -  person Depado    schedule 02.09.2013
comment
Тогда это проблема конфигурации плагина Django OpenStreetMap (?). Вы должны спросить его авторов или исправить это самостоятельно или поменять координаты в своей БД.   -  person scai    schedule 02.09.2013


Ответы (2)


Если ваши координаты в вашей базе данных неверны, вы должны это исправить. В 1_:

from app.models import Point

for obj in Point.objects.all():
    obj.lat, obj.lng = obj.lng, obj.lat
    obj.save()

Теперь вам нужно только исправить вашу «обратную» проблему. Причина, по которой координаты хранятся неправильно, в первую очередь.

ИЗМЕНИТЬ

Если вы хотите вернуть координату только наоборот, вы можете определить пользовательский метод в модели, чтобы добавить к вашим объектам пользовательские функции «на уровне строк». См.: методы модели.

def _get_reversed_point(self):
    "Returns the reversed point (lng, lat)."
    return (self.point.lng, self.point.lat)
reversed_point = property(get_reversed_point)

Теперь вы можете нормально запрашивать свою базу данных, а при работе с обратными точками используйте obj.reversed_point, который вернет обратный кортеж.

ИЗМЕНИТЬ 2

reversed_point не является частью формы и поэтому не может использоваться в представлении изменений, если вы не добавите его самостоятельно. Это делается с помощью ModelAdmin.form< /а>. В форме вы можете (пере)определить поле и указать виджет. Создайте виджет, переопределив вырезающий виджет. Это выглядит так:

from somewhere import SomeWidget

class MyWidget(SomeWidget):
    def render(self, name, value, attrs=None):
        output = []
        template = '<p>Your html that will display a beautiful map. Point: %(lat)s %(lng)s</p>'
        output.append(template % {'lat':self.instance.point.lat, 'lng':self.instance.point.lng, })
        output.append(super(SomeWidget, self).render(name, value, attrs))
        return mark_safe(u''.join(output))


class MyForm(forms.ModelForm):
    point = forms.SomeField(widget=MyWidget)

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)

        if hasattr(self, 'instance'):
            # This gives the widget access to all fields in MyModel object.
            self.fields['point'].widget.instance = self.instance

    class Meta:
        model = MyModel
        exclude = []

class MyAdmin(admin.ModelAdmin):
    form = MyForm

GeoDjango поставляется с некоторыми виджетами. Чтение их кода — хорошая отправная точка, и вы узнаете, где виджеты применяют информацию о точках «неправильным» способом. Удачи.

person allcaps    schedule 02.09.2013
comment
Координаты указаны правильно в БД. Проблема заключается в том, что openstreetmap сначала использует долготу, а затем широту. - person Depado; 02.09.2013
comment
Нет, это должен быть какой-то инструмент или сервис, который вы используете, но с другим порядком. OSM не определяет фиксированный порядок. - person scai; 02.09.2013
comment
Ну может он не так интерпретирует? Поскольку он не определяет порядок... Все мои объекты имеют правильные свойства, что означает, что они хранятся в моей базе данных (широта, долгота). Дело в том, что я не контролирую OSM и не знаю, как изменить его работу. - person Depado; 02.09.2013
comment
Пожалуйста, не называйте его OSM, это всего лишь неофициальное расширение Django, которое не имеет ничего общего с проектом OSM. В любом случае вам придется в какой-то момент изменить свои координаты, и у @allcaps, похоже, есть правильное решение для вас. - person scai; 02.09.2013
comment
Я постараюсь это сделать. Спасибо за терпение =) - person Depado; 03.09.2013
comment
Кстати, не могли бы вы подсказать, как использовать эту функцию в админке django? Я имею в виду, что все поля, которые я отображаю в админке, определяются строками {'fields':['gps']}, и это то, что отображает карту. - person Depado; 03.09.2013
comment
Отлично, спасибо большое! Попробую. В любом случае большое спасибо за ваше время. - person Depado; 04.09.2013
comment
Да, даже если я сейчас борюсь с Джанго, ха-ха :p - person Depado; 04.09.2013
comment
точка = формы.SomeField(widget=MyWidget) Что я должен поставить вместо SomeField? я не понимаю... - person Depado; 04.09.2013
comment
Поле формы. Встроить поля формы: docs.djangoproject.com/en/1.5/ref/ формы/поля Поля Geo Django находятся в django.contrib.gis.forms.fields, например: from django.contrib.gis.forms.fields import GeometryField - person allcaps; 05.09.2013

Решил эту проблему простым тюнингом. Переопределение метода рендеринга намного проще и не требует модификации базы данных/модели. Например :

def get_map_widget(self, db_field):
    mapped = super(MissionAdmin, self).get_map_widget(db_field)

    def render(inner_self, name, value, attrs=None):
        if value and isinstance(value, Point):
            value.x, value.y = value.y, value.x
        return super(mapped, inner_self).render(name, value, attrs)

    mapped.render = render
    return mapped

Это означает, что когда карта визуализируется, непосредственно перед созданием HTML (процесс рендеринга) я просто переворачиваю точки при их отображении. Конечно, это довольно опасно, если, например, это не readonly карта. В этом случае вам нужно изменить метод save_model, чтобы снова изменить ваши координаты.

person Depado    schedule 07.02.2014
comment
И это идет в виджете или форме? - person allcaps; 07.02.2014
comment
Это относится к классу OSMGeoAdmin;) - person Depado; 07.02.2014
comment
Это своего рода быстрое и грязное исправление, хотя. Я изменю все координаты в ближайшие дни, потому что такое исправление всегда ломается в один прекрасный день. И действительно, у меня возникли некоторые проблемы с редактируемыми полями и этим методом, ха-ха - person Depado; 10.02.2014
comment
Почему бы тебе просто не подчиниться латыни и долготе порядку Джанго? Когда использование фреймворка и тривиальных вещей становится сложным, вы можете начать сомневаться в своем решении. Я думаю, что первая часть моего ответа имеет самое чистое решение. 1) Перевернуть lat lng в дб. 2) Создайте метод модели reversed_point 3) В шаблонах вашего проекта найдите и замените .point на .reversed_point. Сделанный. - person allcaps; 10.02.2014