Filter offers

This commit is contained in:
Jannis Portmann 2023-04-15 13:16:40 +02:00
parent cad77f6a4a
commit 1cabae10e8
4 changed files with 66 additions and 6 deletions

View file

@ -1,5 +1,6 @@
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.utils.safestring import mark_safe
from friendly_captcha.fields import FrcCaptchaField
from .models import Offer, PflaenzliUser
@ -17,3 +18,12 @@ class RegistrationForm(UserCreationForm):
fields = UserCreationForm.Meta.fields + ('email', 'zipcode',)
captcha = FrcCaptchaField()
class FilterForm(forms.Form):
text = forms.CharField(max_length=128, required=False, label=mark_safe(
'<i class="fa-solid fa-magnifying-glass"></i> Search'))
zipcode = forms.CharField(max_length=4, required=False, label=mark_safe(
'<i class="fa-solid fa-location-dot"></i> Zipcode'))
distance = forms.IntegerField(required=False, label=mark_safe(
'<i class="fa-solid fa-signs-post"></i> Distance (km)'))

View file

@ -1,10 +1,29 @@
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block title %}Offers{% endblock %}
{% block content %}
<h1>Offers</h1>
<h1 class="mt-3">
Offers
<button class="btn btn-pfl"
type="button"
data-bs-toggle="collapse"
data-bs-target="#filterCollapse"
aria-expanded="true"
aria-controls="filterCollapse">
<i class="fa-solid fa-filter"></i> Filter
</button>
</h1>
<form method="post"
enctype="multipart/form-data"
class="collapse"
id="filterCollapse">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-pfl">Filter</button>
</form>
{% if offers %}
<div class="row row-cols-1 row-cols-md-2 row-cols-xl-3 mb-3 row-gap-5">
<div class="row row-cols-1 row-cols-md-2 row-cols-xl-3 mt-3 mb-3 row-gap-5">
{% for offer in offers %}
<div class="col">
<div class="card h-100 p-0">

View file

@ -1,6 +1,7 @@
from geopy.distance import distance
import os
from pandas import read_pickle
from django.db.models import F, Func
path = os.path.dirname(os.path.abspath(__file__))
@ -9,7 +10,7 @@ df = read_pickle(os.path.join(path, 'plz.pkl'))
def calculate_distance(zip_1, zip_2):
if zip_1 == zip_2:
return None
return 0
zip_1_coords = tuple(df[df.index == zip_1].values)
zip_2_coords = tuple(df[df.index == zip_2].values)
@ -17,3 +18,12 @@ def calculate_distance(zip_1, zip_2):
dist = round(distance((zip_1_coords), (zip_2_coords)).kilometers)
return None if dist > 400 else dist
def filter_by_distance(qs, filter_zipcode, max_dist):
filtered_offers = []
for offer in qs:
d = calculate_distance(int(offer.zipcode), int(filter_zipcode))
if d is not None and d <= max_dist:
filtered_offers.append(offer)
return filtered_offers

View file

@ -5,17 +5,25 @@ from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseForbidden
from .forms import CreateOfferForm, RegistrationForm
from .forms import CreateOfferForm, RegistrationForm, FilterForm
from .models import PflaenzliUser, Offer, Wish
from .mail import send_offer_email
from .upload import generate_unique_filename
from .utils.distance import calculate_distance
from .utils.distance import calculate_distance, filter_by_distance
def list_offers(request, filters=None):
offers = Offer.objects.all()
return render(request, "offer/search.html", {"offers": offers})
if request.method == "POST":
form = FilterForm(request.POST, request.FILES)
if form.is_valid():
offers = filter_offers(offers, form)
else:
form = FilterForm()
return render(request, "offer/search.html", {"offers": offers, "form": form})
@login_required
@ -114,3 +122,16 @@ def register_user(request):
form = RegistrationForm()
return render(request, "basic_form.html", {"form": form, "button_label": "Register", "title": "Registeration"})
def filter_offers(offers, form):
if form.cleaned_data['text']:
offers = offers.filter(title__icontains=form.cleaned_data['text'])
if form.cleaned_data['zipcode']:
if form.cleaned_data['distance']:
offers = filter_by_distance(offers, form.cleaned_data['zipcode'], form.cleaned_data['distance'])
else:
offers = offers.filter(zipcode=int(form.cleaned_data['zipcode']))
return offers