mirror of
https://github.com/umap-project/umap.git
synced 2025-04-29 20:02:36 +02:00
235 lines
7.5 KiB
Python
235 lines
7.5 KiB
Python
import simplejson
|
|
import mimetypes
|
|
import urllib2
|
|
import socket
|
|
|
|
from urlparse import urlparse
|
|
|
|
from django.views.generic import TemplateView
|
|
from django.contrib.auth.models import User
|
|
from django.views.generic import DetailView, View
|
|
from django.db.models import Q
|
|
from django.contrib.gis.measure import D
|
|
from django.conf import settings
|
|
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
|
from django.http import HttpResponse, HttpResponseBadRequest
|
|
from django.utils.translation import ugettext as _
|
|
from django.core.urlresolvers import reverse
|
|
from django.views.decorators.http import require_GET
|
|
|
|
from sesql.shortquery import shortquery
|
|
|
|
from leaflet_storage.models import Map
|
|
from leaflet_storage.forms import DEFAULT_CENTER
|
|
|
|
|
|
class PaginatorMixin(object):
|
|
per_page = 5
|
|
|
|
def paginate(self, qs):
|
|
paginator = Paginator(qs, self.per_page)
|
|
page = self.request.GET.get('p')
|
|
try:
|
|
qs = paginator.page(page)
|
|
except PageNotAnInteger:
|
|
# If page is not an integer, deliver first page.
|
|
qs = paginator.page(1)
|
|
except EmptyPage:
|
|
# If page is out of range (e.g. 9999), deliver last page of results.
|
|
qs = paginator.page(paginator.num_pages)
|
|
return qs
|
|
|
|
|
|
class Home(TemplateView, PaginatorMixin):
|
|
template_name = "umap/home.html"
|
|
list_template_name = "leaflet_storage/map_list.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
qs = Map.public.filter(center__distance_gt=(DEFAULT_CENTER, D(km=1)))
|
|
demo_map = None
|
|
if hasattr(settings, "UMAP_DEMO_PK"):
|
|
try:
|
|
demo_map = Map.public.get(pk=settings.UMAP_DEMO_PK)
|
|
except Map.DoesNotExist:
|
|
pass
|
|
else:
|
|
qs = qs.exclude(id=demo_map.pk)
|
|
showcase_map = None
|
|
if hasattr(settings, "UMAP_SHOWCASE_PK"):
|
|
try:
|
|
showcase_map = Map.public.get(pk=settings.UMAP_SHOWCASE_PK)
|
|
except Map.DoesNotExist:
|
|
pass
|
|
else:
|
|
qs = qs.exclude(id=showcase_map.pk)
|
|
maps = qs.order_by('-modified_at')[:50]
|
|
maps = self.paginate(maps)
|
|
|
|
return {
|
|
"maps": maps,
|
|
"demo_map": demo_map,
|
|
"showcase_map": showcase_map,
|
|
"DEMO_SITE": settings.UMAP_DEMO_SITE
|
|
}
|
|
|
|
def get_template_names(self):
|
|
"""
|
|
Dispatch template according to the kind of request: ajax or normal.
|
|
"""
|
|
if self.request.is_ajax():
|
|
return [self.list_template_name]
|
|
else:
|
|
return [self.template_name]
|
|
|
|
home = Home.as_view()
|
|
|
|
|
|
class About(Home):
|
|
|
|
template_name = "umap/about.html"
|
|
|
|
about = About.as_view()
|
|
|
|
|
|
class UserMaps(DetailView, PaginatorMixin):
|
|
model = User
|
|
slug_url_kwarg = 'username'
|
|
slug_field = 'username'
|
|
list_template_name = "leaflet_storage/map_list.html"
|
|
context_object_name = "current_user"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
manager = Map.objects if self.request.user == self.object else Map.public
|
|
maps = manager.filter(Q(owner=self.object) | Q(editors=self.object)).distinct().order_by('-modified_at')[:30]
|
|
maps = self.paginate(maps)
|
|
kwargs.update({
|
|
"maps": maps
|
|
})
|
|
return super(UserMaps, self).get_context_data(**kwargs)
|
|
|
|
def get_template_names(self):
|
|
"""
|
|
Dispatch template according to the kind of request: ajax or normal.
|
|
"""
|
|
if self.request.is_ajax():
|
|
return [self.list_template_name]
|
|
else:
|
|
return super(UserMaps, self).get_template_names()
|
|
|
|
user_maps = UserMaps.as_view()
|
|
|
|
|
|
class Search(TemplateView, PaginatorMixin):
|
|
template_name = "umap/search.html"
|
|
list_template_name = "leaflet_storage/map_list.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
q = self.request.GET.get('q')
|
|
maps = []
|
|
if q:
|
|
maps = shortquery(Q(classname='Map') & Q(fulltext__containswords=q))
|
|
maps = self.paginate(maps)
|
|
kwargs.update({
|
|
'maps': maps,
|
|
'q': q
|
|
})
|
|
return kwargs
|
|
|
|
def get_template_names(self):
|
|
"""
|
|
Dispatch template according to the kind of request: ajax or normal.
|
|
"""
|
|
if self.request.is_ajax():
|
|
return [self.list_template_name]
|
|
else:
|
|
return super(Search, self).get_template_names()
|
|
|
|
search = Search.as_view()
|
|
|
|
|
|
class MapsShowCase(View):
|
|
|
|
def get(self, *args, **kwargs):
|
|
maps = Map.public.filter(center__distance_gt=(DEFAULT_CENTER, D(km=1))).order_by('-modified_at')[:2000]
|
|
|
|
def make(m):
|
|
description = m.description or ""
|
|
if m.owner:
|
|
description = u"{description}\n{by} [[{url}|{name}]]".format(
|
|
description=description,
|
|
by=_("by"),
|
|
url=reverse('user_maps', kwargs={"username": m.owner.username}),
|
|
name=m.owner,
|
|
)
|
|
description = u"{}\n[[{}|{}]]".format(description, m.get_absolute_url(), _("View the map"))
|
|
geometry = m.settings['geometry'] if "geometry" in m.settings else simplejson.loads(m.center.geojson)
|
|
return {
|
|
"type": "Feature",
|
|
"geometry": geometry,
|
|
"properties": {
|
|
"name": m.name,
|
|
"description": description
|
|
}
|
|
}
|
|
|
|
geojson = {
|
|
"type": "FeatureCollection",
|
|
"features": [make(m) for m in maps]
|
|
}
|
|
return HttpResponse(simplejson.dumps(geojson))
|
|
|
|
showcase = MapsShowCase.as_view()
|
|
|
|
|
|
from django.core.validators import URLValidator, ValidationError
|
|
|
|
|
|
def validate_url(request):
|
|
assert request.method == "GET"
|
|
assert request.is_ajax()
|
|
url = request.GET.get('url')
|
|
assert url
|
|
try:
|
|
URLValidator(url)
|
|
except ValidationError:
|
|
raise AssertionError()
|
|
assert 'HTTP_REFERER' in request.META
|
|
referer = urlparse(request.META.get('HTTP_REFERER'))
|
|
toproxy = urlparse(url)
|
|
local = urlparse(settings.SITE_URL)
|
|
assert toproxy.hostname
|
|
assert referer.hostname == local.hostname
|
|
assert toproxy.hostname != "localhost"
|
|
assert toproxy.netloc != local.netloc
|
|
# clean this when in python 3.4
|
|
ipaddress = socket.gethostbyname(toproxy.hostname)
|
|
assert not ipaddress.startswith('127.')
|
|
assert not ipaddress.startswith('192.168.')
|
|
return url
|
|
|
|
|
|
class AjaxProxy(View):
|
|
|
|
def get(self, *args, **kwargs):
|
|
# You should not use this in production (use Nginx or so)
|
|
try:
|
|
url = validate_url(self.request)
|
|
except AssertionError:
|
|
return HttpResponseBadRequest()
|
|
headers = {
|
|
'User-Agent': 'uMapProxy +http://wiki.openstreetmap.org/wiki/UMap'
|
|
}
|
|
request = urllib2.Request(url, headers=headers)
|
|
opener = urllib2.build_opener()
|
|
try:
|
|
proxied_request = opener.open(request)
|
|
except urllib2.HTTPError as e:
|
|
return HttpResponse(e.msg, status=e.code, mimetype='text/plain')
|
|
else:
|
|
status_code = proxied_request.code
|
|
mimetype = proxied_request.headers.typeheader or mimetypes.guess_type(url)
|
|
content = proxied_request.read()
|
|
# Quick hack to prevent Django from adding a Vary: Cookie header
|
|
self.request.session.accessed = False
|
|
return HttpResponse(content, status=status_code, mimetype=mimetype)
|
|
ajax_proxy = AjaxProxy.as_view()
|