""" Vues de l'application LOGIS. """ import logging import datetime from django.conf import settings from django.core.mail import send_mail from django.http import JsonResponse from django.template.loader import render_to_string from django.utils import timezone from django.utils.translation import gettext as _ from django.views.generic import ListView, DetailView, View from .forms import ContactForm from .models import Property, ContactRequest logger = logging.getLogger(__name__) class PropertyListView(ListView): """Page d'accueil — liste des biens immobiliers actifs.""" model = Property template_name = 'index.html' context_object_name = 'properties' def get_queryset(self): """Retourne les biens actifs avec leurs relations préchargées.""" return ( Property.objects.filter(is_active=True) .prefetch_related('photos', 'features') .select_related('environment') ) class PropertyDetailView(DetailView): """Page de détail d'un bien immobilier.""" model = Property template_name = 'properties/detail.html' context_object_name = 'property' def get_queryset(self): """Retourne uniquement les biens actifs.""" return ( Property.objects.filter(is_active=True) .prefetch_related('photos', 'rooms__photos', 'features') .select_related('environment') ) def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) prop = self.object context['contact_form'] = ContactForm( initial={'property_id': prop.pk} ) context['rooms_with_photos'] = prop.rooms.prefetch_related('photos').all() context['general_photos'] = prop.photos.filter(room__isnull=True) return context class ContactView(View): """Endpoint AJAX pour le formulaire de contact.""" def post(self, request, *args, **kwargs): # Accepte uniquement les requêtes AJAX if not request.headers.get('X-Requested-With') == 'XMLHttpRequest': return JsonResponse({'success': False}, status=400) form = ContactForm(request.POST) if not form.is_valid(): return JsonResponse({'success': False, 'errors': form.errors}) # Vérification honeypot : si rempli, c'est un robot if form.cleaned_data.get('website'): return JsonResponse({'success': True}) # Limitation de débit : 5 minutes entre deux envois par session last_contact = request.session.get('last_contact') if last_contact: try: last_time = datetime.datetime.fromisoformat(last_contact) if timezone.is_naive(last_time): last_time = timezone.make_aware(last_time) elapsed = (timezone.now() - last_time).total_seconds() if elapsed < 300: remaining = int((300 - elapsed) / 60) + 1 return JsonResponse({ 'success': False, 'error': str(_( 'Merci de patienter encore %(min)s minute(s) avant d\'envoyer un nouveau message.' ) % {'min': remaining}), }) except (ValueError, TypeError): pass # Récupération du bien concerné property_obj = None pid = form.cleaned_data.get('property_id') if pid: try: property_obj = Property.objects.get(pk=pid, is_active=True) except Property.DoesNotExist: pass # Enregistrement en base contact = ContactRequest.objects.create( property=property_obj, name=form.cleaned_data['name'], email=form.cleaned_data['email'], phone=form.cleaned_data.get('phone', ''), message=form.cleaned_data['message'], ip_address=self._get_client_ip(request), ) # Envoi de l'email à l'administrateur try: ctx = {'contact': contact, 'property': property_obj} subject = render_to_string('emails/contact_subject.txt', ctx).strip() body_text = render_to_string('emails/contact_body.txt', ctx) body_html = render_to_string('emails/contact_body.html', ctx) send_mail( subject=subject, message=body_text, from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=[settings.ADMIN_EMAIL], html_message=body_html, fail_silently=False, ) except Exception as exc: # L'email échoue mais le contact est enregistré en base logger.error('Échec envoi email contact #%s : %s', contact.pk, exc) request.session['last_contact'] = timezone.now().isoformat() return JsonResponse({ 'success': True, 'message': str(_('Votre message a bien été envoyé. Nous vous répondrons dans les plus brefs délais.')), }) def _get_client_ip(self, request): """Extrait l'adresse IP réelle du client derrière un proxy.""" forwarded = request.META.get('HTTP_X_FORWARDED_FOR') if forwarded: return forwarded.split(',')[0].strip() return request.META.get('REMOTE_ADDR')