# coding: utf-8 from tastypie.resources import ModelResource from tastypie.authentication import SessionAuthentication from tastypie import fields, utils from django.contrib.gis import geos from django.urls import reverse from .models import Lieu, Stage, Normalien, StageMatiere from .utils import approximate_distance class EnScolariteAuthentication(SessionAuthentication): def is_authenticated(self, request, **kwargs): if super().is_authenticated(request, **kwargs): return request.user.profil.en_scolarite return False # API principale pour les lieux class LieuResource(ModelResource): #stages = fields.ToManyField("avisstage.api.StageResource", # "stages", use_in="detail", full=True) class Meta: queryset = Lieu.objects.all() resource_name = "lieu" fields = ["nom", "ville", "pays", "coord", "type_lieu", "id"] #login_required authentication = SessionAuthentication() # Filtres personnalisés def build_filters(self, filters=None, **kwargs): if filters is None: filters = {} orm_filters = super(LieuResource, self).build_filters(filters, **kwargs) # Trouver les lieux à proximités d'un point donné if "lng" in filters and "lat" in filters: lat = float(filters['lat']) lng = float(filters['lng']) pt = geos.Point((lng,lat), srid=4326) self.reference_point = pt orm_filters['coord__distance_lte'] = (pt, 10000) # Filtrer les lieux qui ont déjà des stages if "has_stage" in filters: orm_filters['stages__public'] = True return orm_filters # Custom apply filters pour ajouter le "distinct" def apply_filters(self, request, applicable_filters): return self.get_object_list(request).filter(**applicable_filters).distinct() # Ajout d'informations def dehydrate(self, bundle): bundle = super(LieuResource, self).dehydrate(bundle) obj = bundle.obj bundle.data['coord'] = {'lat': float(obj.coord.y), 'lng': float(obj.coord.x)} # Distance au point recherché if "lat" in bundle.request.GET and "lng" in bundle.request.GET: bundle.data['distance'] = approximate_distance( self.reference_point, bundle.obj.coord) # Autres infos utiles bundle.data["pays_nom"] = obj.get_pays_display() bundle.data["type_lieu_nom"] = obj.type_lieu_fancy # TODO use annotate? bundle.data["num_stages"] = obj.stages.filter(public=True).count() return bundle # API sur un stage class StageResource(ModelResource): class Meta: queryset = Stage.objects.filter(public=True) resource_name = "stage" fields = ["sujet", "date_debut", "date_fin", "matieres", "id"] #login_required authentication = EnScolariteAuthentication() # Filtres personnalisés def build_filters(self, filters=None, **kwargs): if filters is None: filters = {} orm_filters = super(StageResource, self).build_filters(filters, **kwargs) # Récupération des stages à un lieu donné if "lieux" in filters: flieux = map(int, filters['lieux'].split(',')) orm_filters['lieux__id__in'] = flieux return orm_filters # Informations à ajouter def dehydrate(self, bundle): bundle = super(StageResource, self).dehydrate(bundle) obj = bundle.obj # Affichage des manytomany en condensé bundle.data['auteur'] = obj.auteur.nom bundle.data['thematiques'] = list(obj.thematiques.all().values_list("name", flat=True)) bundle.data['matieres'] = list(obj.matieres.all().values_list("nom", flat=True)) # Adresse de la fiche de stage bundle.data['url'] = reverse("avisstage:stage", kwargs={"pk": obj.id}); return bundle # Auteurs des fiches (TODO supprimer ?) class AuteurResource(ModelResource): stages = fields.ToManyField("avisstage.api.StageResource", "stages", use_in="detail") class Meta: queryset = Normalien.objects.all() resource_name = "profil" fields = ["id", "nom", "stages"] #login_required authentication = EnScolariteAuthentication()