Compare commits
10 Commits
3eb7dbe984
...
8de5f162eb
Author | SHA1 | Date | |
---|---|---|---|
8de5f162eb | |||
dc3859d589 | |||
b4f52c7876 | |||
885622e581 | |||
a42a3fa177 | |||
27541c6fb6 | |||
14547ad621 | |||
8d2d80c30e | |||
e6f5a42d15 | |||
052e42f76a |
@ -1,7 +1,7 @@
|
||||
from django import forms
|
||||
|
||||
from .models import AdoptionNotice, Animal, Image, ReportAdoptionNotice, ReportComment, ModerationAction, User, Species, \
|
||||
Comment
|
||||
Comment, SexChoicesWithAll
|
||||
from django_registration.forms import RegistrationForm
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import Submit, Layout, Fieldset, HTML, Row, Column, Field, Hidden
|
||||
@ -66,7 +66,8 @@ class AdoptionNoticeForm(forms.ModelForm):
|
||||
class AdoptionNoticeFormWithDateWidget(AdoptionNoticeForm):
|
||||
class Meta:
|
||||
model = AdoptionNotice
|
||||
fields = ['name', "group_only", "further_information", "description", "searching_since", "location_string", "organization"]
|
||||
fields = ['name', "group_only", "further_information", "description", "searching_since", "location_string",
|
||||
"organization"]
|
||||
widgets = {
|
||||
'searching_since': DateInput(),
|
||||
}
|
||||
@ -185,5 +186,7 @@ def _get_distances():
|
||||
|
||||
|
||||
class AdoptionNoticeSearchForm(forms.Form):
|
||||
location = forms.CharField(max_length=20, label=_("Stadt"))
|
||||
location = forms.CharField(max_length=20, label=_("Stadt"), required=False)
|
||||
max_distance = forms.ChoiceField(choices=_get_distances, label=_("Max. Distanz"))
|
||||
sex = forms.ChoiceField(choices=SexChoicesWithAll, label=_("Geschlecht"), required=False,
|
||||
initial=SexChoicesWithAll.ALL)
|
||||
|
18
src/fellchensammlung/migrations/0024_alter_animal_sex.py
Normal file
18
src/fellchensammlung/migrations/0024_alter_animal_sex.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.1 on 2024-11-21 19:34
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('fellchensammlung', '0023_user_email_notifications'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='animal',
|
||||
name='sex',
|
||||
field=models.CharField(choices=[('M_N', 'neutered male'), ('M', 'male'), ('F_N', 'neutered female'), ('F', 'female'), ('I', 'intersex')], max_length=20),
|
||||
),
|
||||
]
|
18
src/fellchensammlung/migrations/0025_alter_animal_sex.py
Normal file
18
src/fellchensammlung/migrations/0025_alter_animal_sex.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.1 on 2024-11-21 19:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('fellchensammlung', '0024_alter_animal_sex'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='animal',
|
||||
name='sex',
|
||||
field=models.CharField(choices=[('F', 'Weiblich'), ('M', 'Männlich'), ('M_N', 'Männlich, kastriert'), ('F_N', 'Weiblich Kastriert'), ('I', 'Intersex')], max_length=20),
|
||||
),
|
||||
]
|
18
src/fellchensammlung/migrations/0026_alter_animal_sex.py
Normal file
18
src/fellchensammlung/migrations/0026_alter_animal_sex.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.1 on 2024-11-21 21:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('fellchensammlung', '0025_alter_animal_sex'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='animal',
|
||||
name='sex',
|
||||
field=models.CharField(choices=[('F', 'Weiblich'), ('M', 'Männlich'), ('M_N', 'Männlich, kastriert'), ('F_N', 'Weiblich, kastriert'), ('I', 'Intergeschlechtlich')], max_length=20),
|
||||
),
|
||||
]
|
@ -240,15 +240,18 @@ class AdoptionNotice(models.Model):
|
||||
def sexes(self):
|
||||
sexes = set()
|
||||
for animal in self.animals:
|
||||
sexes.update(animal.sex)
|
||||
sexes.add(animal.sex)
|
||||
return sexes
|
||||
|
||||
def sex_code(self):
|
||||
# Treat Intersex as mixed in order to increase their visibility
|
||||
if len(self.sexes) > 1:
|
||||
return "mixed"
|
||||
elif self.sexes.pop() == Animal.MALE:
|
||||
|
||||
sex = self.sexes.pop()
|
||||
if sex == SexChoices.MALE:
|
||||
return "male"
|
||||
elif self.sexes.pop() == Animal.FEMALE:
|
||||
elif sex == SexChoices.FEMALE:
|
||||
return "female"
|
||||
else:
|
||||
return "mixed"
|
||||
@ -348,18 +351,26 @@ class AdoptionNotice(models.Model):
|
||||
def set_closed(self):
|
||||
self.last_checked = timezone.now()
|
||||
self.adoptionnoticestatus.set_closed()
|
||||
self.save()
|
||||
|
||||
def set_active(self):
|
||||
self.last_checked = timezone.now()
|
||||
if not hasattr(self, 'adoptionnoticestatus'):
|
||||
AdoptionNoticeStatus.create_other(self)
|
||||
self.adoptionnoticestatus.set_active()
|
||||
self.save()
|
||||
|
||||
def set_unchecked(self):
|
||||
self.last_checked = timezone.now()
|
||||
if not hasattr(self, 'adoptionnoticestatus'):
|
||||
AdoptionNoticeStatus.create_other(self)
|
||||
self.adoptionnoticestatus.set_unchecked()
|
||||
self.save()
|
||||
|
||||
for subscription in self.get_subscriptions():
|
||||
notification_title = _("Vermittlung deaktiviert:") + f" {self}"
|
||||
text = _("Die folgende Vermittlung wurde deaktiviert: ") + f"{self.name}, {self.get_absolute_url()}"
|
||||
BaseNotification.objects.create(user=subscription.owner, text=text, title=notification_title)
|
||||
|
||||
|
||||
class AdoptionNoticeStatus(models.Model):
|
||||
@ -457,24 +468,33 @@ class AdoptionNoticeStatus(models.Model):
|
||||
self.save()
|
||||
|
||||
|
||||
class Animal(models.Model):
|
||||
MALE_NEUTERED = "M_N"
|
||||
MALE = "M"
|
||||
FEMALE_NEUTERED = "F_N"
|
||||
FEMALE = "F"
|
||||
SEX_CHOICES = {
|
||||
MALE_NEUTERED: "neutered male",
|
||||
MALE: "male",
|
||||
FEMALE_NEUTERED: "neutered female",
|
||||
FEMALE: "female",
|
||||
}
|
||||
class SexChoices(models.TextChoices):
|
||||
FEMALE = "F", _("Weiblich")
|
||||
MALE = "M", _("Männlich")
|
||||
MALE_NEUTERED = "M_N", _("Männlich, kastriert")
|
||||
FEMALE_NEUTERED = "F_N", _("Weiblich, kastriert")
|
||||
INTER = "I", _("Intergeschlechtlich")
|
||||
|
||||
|
||||
class SexChoicesWithAll(models.TextChoices):
|
||||
FEMALE = "F", _("Weiblich")
|
||||
MALE = "M", _("Männlich")
|
||||
MALE_NEUTERED = "M_N", _("Männlich, kastriert")
|
||||
FEMALE_NEUTERED = "F_N", _("Weiblich Kastriert")
|
||||
INTER = "I", _("Intergeschlechtlich")
|
||||
ALL = "A", _("Alle")
|
||||
|
||||
|
||||
class Animal(models.Model):
|
||||
date_of_birth = models.DateField(verbose_name=_('Geburtsdatum'))
|
||||
name = models.CharField(max_length=200)
|
||||
description = models.TextField(null=True, blank=True, verbose_name=_('Beschreibung'))
|
||||
species = models.ForeignKey(Species, on_delete=models.PROTECT)
|
||||
photos = models.ManyToManyField(Image, blank=True)
|
||||
sex = models.CharField(max_length=20, choices=SEX_CHOICES, )
|
||||
sex = models.CharField(
|
||||
max_length=20,
|
||||
choices=SexChoices.choices,
|
||||
)
|
||||
adoption_notice = models.ForeignKey(AdoptionNotice, on_delete=models.CASCADE)
|
||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
@ -16,7 +16,7 @@ from notfellchen import settings
|
||||
from fellchensammlung import logger
|
||||
from .models import AdoptionNotice, Text, Animal, Rule, Image, Report, ModerationAction, \
|
||||
User, Location, AdoptionNoticeStatus, Subscriptions, CommentNotification, BaseNotification, RescueOrganization, \
|
||||
Species, Log, Timestamp, TrustLevel
|
||||
Species, Log, Timestamp, TrustLevel, SexChoicesWithAll
|
||||
from .forms import AdoptionNoticeForm, AdoptionNoticeFormWithDateWidget, ImageForm, ReportAdoptionNoticeForm, \
|
||||
CommentForm, ReportCommentForm, AnimalForm, \
|
||||
AdoptionNoticeSearchForm, AnimalFormWithDateWidget, AdoptionNoticeFormWithDateWidgetAutoAnimal
|
||||
@ -169,27 +169,34 @@ def animal_detail(request, animal_id):
|
||||
|
||||
def search(request):
|
||||
place_not_found = None
|
||||
latest_adoption_list = AdoptionNotice.objects.order_by("-created_at")
|
||||
active_adoptions = [adoption for adoption in latest_adoption_list if adoption.is_active]
|
||||
if request.method == 'POST':
|
||||
latest_adoption_list = AdoptionNotice.objects.order_by("-created_at")
|
||||
active_adoptions = [adoption for adoption in latest_adoption_list if adoption.is_active]
|
||||
|
||||
sex = request.POST.get("sex")
|
||||
if sex != SexChoicesWithAll.ALL:
|
||||
active_adoptions = [adoption for adoption in active_adoptions if sex in adoption.sexes]
|
||||
|
||||
search_form = AdoptionNoticeSearchForm(request.POST)
|
||||
max_distance = int(request.POST.get('max_distance'))
|
||||
if max_distance == "":
|
||||
max_distance = None
|
||||
geo_api = GeoAPI()
|
||||
search_position = geo_api.get_coordinates_from_query(request.POST['location'])
|
||||
if search_position is None:
|
||||
place_not_found = True
|
||||
search_form.is_valid()
|
||||
if search_form.cleaned_data["location"] == "":
|
||||
adoption_notices_in_distance = active_adoptions
|
||||
place_not_found = False
|
||||
else:
|
||||
adoption_notices_in_distance = [a for a in active_adoptions if a.in_distance(search_position, max_distance)]
|
||||
max_distance = int(request.POST.get('max_distance'))
|
||||
if max_distance == "":
|
||||
max_distance = None
|
||||
geo_api = GeoAPI()
|
||||
search_position = geo_api.get_coordinates_from_query(request.POST['location'])
|
||||
if search_position is None:
|
||||
place_not_found = True
|
||||
adoption_notices_in_distance = active_adoptions
|
||||
else:
|
||||
adoption_notices_in_distance = [a for a in active_adoptions if a.in_distance(search_position, max_distance)]
|
||||
|
||||
context = {"adoption_notices": adoption_notices_in_distance, "search_form": search_form,
|
||||
"place_not_found": place_not_found}
|
||||
else:
|
||||
latest_adoption_list = AdoptionNotice.objects.order_by("-created_at")
|
||||
active_adoptions = [adoption for adoption in latest_adoption_list if adoption.is_active]
|
||||
search_form = AdoptionNoticeSearchForm()
|
||||
context = {"adoption_notices": active_adoptions, "search_form": search_form}
|
||||
return render(request, 'fellchensammlung/search.html', context=context)
|
||||
|
@ -120,7 +120,7 @@ class SearchTest(TestCase):
|
||||
self.assertNotContains(response, "TestAdoption2")
|
||||
|
||||
def test_plz_search(self):
|
||||
response = self.client.post(reverse('search'), {"max_distance": 100, "location": "Berlin"})
|
||||
response = self.client.post(reverse('search'), {"max_distance": 100, "location": "Berlin", "sex": "A"})
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "TestAdoption1")
|
||||
self.assertNotContains(response, "TestAdoption3")
|
||||
|
Loading…
Reference in New Issue
Block a user