Skip to content
Extraits de code Groupes Projets
views.py 8,28 ko
Newer Older
  • Learn to ignore specific revisions
  • import mimetypes
    
    import socket
    
    
    try:
        # python3
        from urllib.parse import urlparse
        from urllib.request import Request, build_opener
        from urllib.error import HTTPError
    except ImportError:
        from urlparse import urlparse
        from urllib2 import Request, HTTPError, build_opener
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
    from django.views.generic import TemplateView
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
    from django.contrib.auth import get_user_model
    
    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.core.validators import URLValidator, ValidationError
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
    
    
    from leaflet_storage.models import Map
    
    from leaflet_storage.forms import DEFAULT_CENTER
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
    
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
    User = get_user_model()
    
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
    
    
    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"
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
    
        def get_context_data(self, **kwargs):
    
            if 'spatialite' not in settings.DATABASES['default']['ENGINE']:
    
                # Unsupported query type for sqlite.
                qs = qs.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)
    
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
            return {
    
                "demo_map": demo_map,
    
                "showcase_map": showcase_map,
    
                "DEMO_SITE": settings.UMAP_DEMO_SITE
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
            }
    
    
        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]
    
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
    home = Home.as_view()
    
    class About(Home):
    
        template_name = "umap/about.html"
    
    about = About.as_view()
    
    
    class UserMaps(DetailView, PaginatorMixin):
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
        model = User
        slug_url_kwarg = 'username'
        slug_field = 'username'
    
        list_template_name = "leaflet_storage/map_list.html"
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
        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))
            maps = maps.distinct().order_by('-modified_at')[:50]
    
            maps = self.paginate(maps)
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
            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')
    
                where = "to_tsvector(name) @@ to_tsquery(%s)"
    
                if getattr(settings, 'UMAP_USE_UNACCENT', False):
    
                    where = "to_tsvector(unaccent(name)) @@ to_tsquery(unaccent(%s))"  # noqa
                results = Map.objects.filter(share_status=Map.PUBLIC)
                results = results.extra(where=[where], params=[q])
                results = results.order_by('-modified_at')
                print(results.query)
    
                results = self.paginate(results)
    
            kwargs.update({
    
                'maps': results,
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
            })
    
            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()
    
        def get(self, *args, **kwargs):
    
            maps = Map.public.filter(center__distance_gt=(DEFAULT_CENTER, D(km=1)))
            maps = maps.order_by('-modified_at')[:2500]
    
                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}),
    
                description = u"{}\n[[{}|{}]]".format(
                    description, m.get_absolute_url(), _("View the map"))
                geometry = m.settings.get('geometry', json.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(json.dumps(geojson))
    
    
    showcase = MapsShowCase.as_view()
    
    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
    
        try:
            # clean this when in python 3.4
            ipaddress = socket.gethostbyname(toproxy.hostname)
        except:
            raise AssertionError()
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
        assert not ipaddress.startswith('127.')
        assert not ipaddress.startswith('192.168.')
    
    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 as e:
    
                return HttpResponseBadRequest()
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
            headers = {
                'User-Agent': 'uMapProxy +http://wiki.openstreetmap.org/wiki/UMap'
            }
    
            request = Request(url, headers=headers)
            opener = build_opener()
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
                proxied_request = opener.open(request)
    
            except HTTPError as e:
                return HttpResponse(e.msg, status=e.code,
                                    content_type='text/plain')
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
                status_code = proxied_request.code
    
                mimetype = proxied_request.headers.get('Content-Type') or mimetypes.guess_type(url)  # noqa
    
    Yohan Boniface's avatar
    Yohan Boniface a validé
                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,
                                    content_type=mimetype)
    
    ajax_proxy = AjaxProxy.as_view()