diff --git a/notfellchen.cfg b/notfellchen.cfg index b0049eb..9fe9e69 100644 --- a/notfellchen.cfg +++ b/notfellchen.cfg @@ -12,4 +12,7 @@ debug=True backend=sqlite3 name=notfellchen +[locations] +media=./media + diff --git a/src/fellchensammlung/management/commands/populate_db.py b/src/fellchensammlung/management/commands/populate_db.py index 1ad28b7..7280091 100644 --- a/src/fellchensammlung/management/commands/populate_db.py +++ b/src/fellchensammlung/management/commands/populate_db.py @@ -11,15 +11,6 @@ class Command(BaseCommand): @staticmethod def populate_db(): - rat1 = baker.make_recipe( - 'fellchensammlung.rat' - ) - rat2 = baker.make_recipe( - 'fellchensammlung.rat' - ) - cat = baker.make_recipe( - 'fellchensammlung.cat' - ) rescue1 = baker.make_recipe( 'fellchensammlung.rescue_org' ) @@ -27,9 +18,13 @@ class Command(BaseCommand): 'fellchensammlung.rescue_org' ) - baker.make(AdoptionNotice, name="Vermittung1", animals=[rat1, rat2], organization=rescue1) + adoption1 = baker.make(AdoptionNotice, name="Vermittung1", organization=rescue1) - baker.make(AdoptionNotice, name="Vermittung2", animals=[cat], organization=rescue2) + adoption2 = baker.make(AdoptionNotice, name="Vermittung2", organization=rescue2) + + rat1 = baker.make(Animal, name="Rat1", adoption_notice=adoption1) + rat2 = baker.make(Animal, name="Rat2", adoption_notice=adoption1) + cat1 = baker.make(Animal, name="Cat1", adoption_notice=adoption1) User.objects.create_user('test', password='foobar') User.objects.create_superuser(username="admin", password="admin") diff --git a/src/fellchensammlung/migrations/0001_initial.py b/src/fellchensammlung/migrations/0001_initial.py deleted file mode 100644 index 06e4a03..0000000 --- a/src/fellchensammlung/migrations/0001_initial.py +++ /dev/null @@ -1,73 +0,0 @@ -# Generated by Django 5.0.3 on 2024-03-17 22:05 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='Location', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=200)), - ('postcode', models.CharField(max_length=200)), - ('country', models.CharField(choices=[('DE', 'Germany'), ('AT', 'Austria'), ('CH', 'Switzerland')], max_length=20)), - ('description', models.TextField(blank=True, null=True, verbose_name='Description')), - ], - ), - migrations.CreateModel( - name='Species', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(help_text='Enter a animal species', max_length=200, verbose_name='Name')), - ], - options={ - 'verbose_name': 'Species', - 'verbose_name_plural': 'Species', - }, - ), - migrations.CreateModel( - name='RescueOrganization', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=200)), - ('trusted', models.BooleanField(default=False, verbose_name='Trusted')), - ('instagram', models.URLField(blank=True, null=True, verbose_name='Instagram profile')), - ('facebook', models.URLField(blank=True, null=True, verbose_name='Facebook profile')), - ('fediverse_profile', models.URLField(blank=True, null=True, verbose_name='Fediverse profile')), - ('website', models.URLField(blank=True, null=True, verbose_name='Website')), - ('location', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='fellchensammlung.location')), - ], - ), - migrations.CreateModel( - name='AdoptionNotice', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_at', models.DateField(verbose_name='Created at')), - ('searching_since', models.DateField(verbose_name='Searching for a home since')), - ('name', models.CharField(max_length=200)), - ('description', models.TextField(blank=True, null=True, verbose_name='Description')), - ('further_information', models.URLField(blank=True, null=True, verbose_name='Link to further information')), - ('group_only', models.BooleanField(default=False, verbose_name='Only group adoption')), - ('organization', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='fellchensammlung.rescueorganization', verbose_name='Organization')), - ], - ), - migrations.CreateModel( - name='Animal', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('date_of_birth', models.DateField(blank=True, null=True, verbose_name='Date of birth')), - ('name', models.CharField(max_length=200)), - ('description', models.TextField(blank=True, null=True, verbose_name='Description')), - ('adoption_notice', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fellchensammlung.adoptionnotice')), - ('species', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='fellchensammlung.species')), - ], - ), - ] diff --git a/src/fellchensammlung/migrations/0002_remove_animal_adoption_notice_adoptionnotice_animals.py b/src/fellchensammlung/migrations/0002_remove_animal_adoption_notice_adoptionnotice_animals.py deleted file mode 100644 index 1b72b69..0000000 --- a/src/fellchensammlung/migrations/0002_remove_animal_adoption_notice_adoptionnotice_animals.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 5.0.3 on 2024-03-18 09:33 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('fellchensammlung', '0001_initial'), - ] - - operations = [ - migrations.RemoveField( - model_name='animal', - name='adoption_notice', - ), - migrations.AddField( - model_name='adoptionnotice', - name='animals', - field=models.ManyToManyField(to='fellchensammlung.animal'), - ), - ] diff --git a/src/fellchensammlung/migrations/0003_markdowncontent.py b/src/fellchensammlung/migrations/0003_markdowncontent.py deleted file mode 100644 index ad5b9f2..0000000 --- a/src/fellchensammlung/migrations/0003_markdowncontent.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 5.0.3 on 2024-03-18 13:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('fellchensammlung', '0002_remove_animal_adoption_notice_adoptionnotice_animals'), - ] - - operations = [ - migrations.CreateModel( - name='MarkdownContent', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=100)), - ('content', models.TextField()), - ], - options={ - 'verbose_name_plural': 'Markdown content', - }, - ), - ] diff --git a/src/fellchensammlung/migrations/0004_image_adoptionnotice_photos_animal_photos.py b/src/fellchensammlung/migrations/0004_image_adoptionnotice_photos_animal_photos.py deleted file mode 100644 index 0320358..0000000 --- a/src/fellchensammlung/migrations/0004_image_adoptionnotice_photos_animal_photos.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 5.0.3 on 2024-03-18 16:08 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('fellchensammlung', '0003_markdowncontent'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Image', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=200)), - ('image', models.ImageField(upload_to='images')), - ('alt_text', models.TextField(max_length=2000)), - ('uploaded_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.AddField( - model_name='adoptionnotice', - name='photos', - field=models.ManyToManyField(blank=True, to='fellchensammlung.image'), - ), - migrations.AddField( - model_name='animal', - name='photos', - field=models.ManyToManyField(blank=True, to='fellchensammlung.image'), - ), - ] diff --git a/src/fellchensammlung/migrations/0005_animal_sex.py b/src/fellchensammlung/migrations/0005_animal_sex.py deleted file mode 100644 index 206afbf..0000000 --- a/src/fellchensammlung/migrations/0005_animal_sex.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.0.3 on 2024-03-19 04:50 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('fellchensammlung', '0004_image_adoptionnotice_photos_animal_photos'), - ] - - operations = [ - migrations.AddField( - model_name='animal', - name='sex', - field=models.CharField(choices=[('M_N', 'male_neutered'), ('M', 'male'), ('F_N', 'female_neutered'), ('F', 'female')], default='female', max_length=20), - preserve_default=False, - ), - ] diff --git a/src/fellchensammlung/migrations/0006_alter_animal_date_of_birth.py b/src/fellchensammlung/migrations/0006_alter_animal_date_of_birth.py deleted file mode 100644 index 51dd8ca..0000000 --- a/src/fellchensammlung/migrations/0006_alter_animal_date_of_birth.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 5.0.3 on 2024-03-19 04:51 - -import datetime -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('fellchensammlung', '0005_animal_sex'), - ] - - operations = [ - migrations.AlterField( - model_name='animal', - name='date_of_birth', - field=models.DateField(default=datetime.datetime(2024, 3, 19, 4, 51, 44, 367516, tzinfo=datetime.timezone.utc), verbose_name='Date of birth'), - preserve_default=False, - ), - ] diff --git a/src/fellchensammlung/models.py b/src/fellchensammlung/models.py index ca6fe39..c6498f6 100644 --- a/src/fellchensammlung/models.py +++ b/src/fellchensammlung/models.py @@ -63,6 +63,25 @@ class RescueOrganization(models.Model): website = models.URLField(null=True, blank=True, verbose_name=_('Website')) +class AdoptionNotice(models.Model): + def __str__(self): + return f"{self.name}" + + created_at = models.DateField(verbose_name=_('Created at'), default=datetime.now) + searching_since = models.DateField(verbose_name=_('Searching for a home since')) + name = models.CharField(max_length=200) + description = models.TextField(null=True, blank=True, verbose_name=_('Description')) + organization = models.ForeignKey(RescueOrganization, blank=True, null=True, on_delete=models.SET_NULL, + verbose_name=_('Organization')) + further_information = models.URLField(null=True, blank=True, verbose_name=_('Link to further information')) + group_only = models.BooleanField(default=False, verbose_name=_('Only group adoption')) + photos = models.ManyToManyField(Image, blank=True) + + @property + def animals_list(self): + return self.animals.all() + + class Animal(models.Model): MALE_NEUTERED = "M_N" MALE = "M" @@ -81,6 +100,7 @@ class Animal(models.Model): species = models.ForeignKey(Species, on_delete=models.PROTECT) photos = models.ManyToManyField(Image, blank=True) sex = models.CharField(max_length=20, choices=SEX_CHOICES, ) + adoption_notice = models.ForeignKey(AdoptionNotice, on_delete=models.CASCADE) def __str__(self): return f"{self.name}" @@ -99,26 +119,6 @@ class Animal(models.Model): return reverse('animal-detail', args=[str(self.id)]) -class AdoptionNotice(models.Model): - def __str__(self): - return f"{self.name}" - - created_at = models.DateField(verbose_name=_('Created at')) - searching_since = models.DateField(verbose_name=_('Searching for a home since')) - name = models.CharField(max_length=200) - description = models.TextField(null=True, blank=True, verbose_name=_('Description')) - organization = models.ForeignKey(RescueOrganization, blank=True, null=True, on_delete=models.SET_NULL, - verbose_name=_('Organization')) - further_information = models.URLField(null=True, blank=True, verbose_name=_('Link to further information')) - group_only = models.BooleanField(default=False, verbose_name=_('Only group adoption')) - animals = models.ManyToManyField(Animal) - photos = models.ManyToManyField(Image, blank=True) - - @property - def animals_list(self): - return self.animals.all() - - class MarkdownContent(models.Model): """ Base class to store markdown content diff --git a/src/fellchensammlung/templates/fellchensammlung/add_adoption.html b/src/fellchensammlung/templates/fellchensammlung/add_adoption.html deleted file mode 100644 index f352fb7..0000000 --- a/src/fellchensammlung/templates/fellchensammlung/add_adoption.html +++ /dev/null @@ -1,6 +0,0 @@ -{% extends "fellchensammlung/base_generic.html" %} -{% load i18n %} - -{% block content %} - Work in Progress: Vermitteln -{% endblock %} \ No newline at end of file diff --git a/src/fellchensammlung/templates/fellchensammlung/form_add_adoption.html b/src/fellchensammlung/templates/fellchensammlung/form_add_adoption.html new file mode 100644 index 0000000..0b20276 --- /dev/null +++ b/src/fellchensammlung/templates/fellchensammlung/form_add_adoption.html @@ -0,0 +1,13 @@ +{% extends "fellchensammlung/base_generic.html" %} +{% load i18n %} + +{% block content %} +

Vermitteln

+ Bitte mach dich zunächst mit unseren Regeln vertraut. Dann trage hier die ersten Informationen ein. + Du bekommst in einem weiteren Schritt die Möglichkeit einzelne Tiere zu deiner Vermittlung hinzuzufügen und Fotos hochzuladen. +
+ {% csrf_token %} + {{ form.as_p }} + +
+{% endblock %} \ No newline at end of file diff --git a/src/fellchensammlung/urls.py b/src/fellchensammlung/urls.py index bdf7b43..b1e105f 100644 --- a/src/fellchensammlung/urls.py +++ b/src/fellchensammlung/urls.py @@ -7,11 +7,17 @@ urlpatterns = [ # ex: /animal/5/ path("/", views.animal_detail, name="animal-detail"), # ex: /adoption_notice/7/ - path("/", views.adoption_notice_detail, name="adoption-notice-detail"), + path("vermittlung//", views.adoption_notice_detail, name="adoption-notice-detail"), # ex: /search/ path("suchen/", views.search, name="search"), # ex: /vermitteln/ path("vermitteln/", views.add_adoption, name="add-adoption"), + + # ex: vermitteln-tiere-hinzufügen/5 + path("vermitteln-tiere-hinzufügen/", + views.add_animal_to_adoption, + name="add-animal-to-adoption"), + path("ueber-uns/", views.about, name="about"), ] \ No newline at end of file diff --git a/src/fellchensammlung/views.py b/src/fellchensammlung/views.py index d607209..6b0587c 100644 --- a/src/fellchensammlung/views.py +++ b/src/fellchensammlung/views.py @@ -1,8 +1,10 @@ -from django.shortcuts import render +from django.shortcuts import render, redirect +from django.http import HttpResponse +from django.urls import reverse import markdown -from django.http import HttpResponse from fellchensammlung.models import AdoptionNotice, MarkdownContent, Animal +from .forms import AdoptionNoticeForm, AnimalForm def index(request): @@ -22,12 +24,42 @@ def animal_detail(request, animal_id): context = {"animal": animal} return render(request, 'fellchensammlung/detail_animal.html', context=context) + def search(request): latest_adoption_list = AdoptionNotice.objects.order_by("-created_at")[:5] context = {"adoption_notices": latest_adoption_list} return render(request, 'fellchensammlung/search.html', context=context) + + def add_adoption(request): - return render(request, 'fellchensammlung/add_adoption.html') + if request.method == 'POST': + form = AdoptionNoticeForm(request.POST, request.FILES) + + if form.is_valid(): + instance = form.save() + return redirect(reverse("add-animal-to-adoption", args=[instance.pk])) + else: + form = AdoptionNoticeForm() + return render(request, 'fellchensammlung/form_add_adoption.html', {'form': form}) + + +def add_animal_to_adoption(request, adoption_notice_id): + if request.method == 'POST': + form = AnimalForm(request.POST, request.FILES) + + if form.is_valid(): + form.cleaned_data["adoption_notice_id"] = adoption_notice_id + instance = form.save(commit=False) + instance.adoption_notice_id = adoption_notice_id + instance.save() + if "button_add_another_animal" in request.POST: + return redirect(reverse("add-animal-to-adoption", args=[str(adoption_notice_id)])) + else: + return redirect(reverse("adoption-notice-detail", args=[str(adoption_notice_id)])) + else: + form = AnimalForm() + return render(request, 'fellchensammlung/form_add_animal_to_adoption.html', {'form': form}) + def about(request): md = markdown.Markdown(extensions=["fenced_code"]) @@ -39,4 +71,3 @@ def about(request): "fellchensammlung/about.html", context=context ) - diff --git a/src/notfellchen/settings.py b/src/notfellchen/settings.py index 834d6ab..14b4018 100644 --- a/src/notfellchen/settings.py +++ b/src/notfellchen/settings.py @@ -91,6 +91,9 @@ SEC_POLICY = config.get("security", "Policy", """ LOCATIONS """ STATIC_ROOT = config.get("locations", "static", fallback="/notfellchen/static") +MEDIA_ROOT = config.get("locations", "media", fallback="/notfellchen/static") +MEDIA_URL = '/media/' + # see https://docs.djangoproject.com/en/3.2/ref/settings/#std-setting-ALLOWED_HOSTS ALLOWED_HOSTS = [config.get("notfellchen", "host", fallback='*')] diff --git a/src/notfellchen/urls.py b/src/notfellchen/urls.py index 9679a9e..48d4ed0 100644 --- a/src/notfellchen/urls.py +++ b/src/notfellchen/urls.py @@ -16,8 +16,15 @@ Including another URLconf """ from django.contrib import admin from django.urls import include, path +from django.conf import settings + +from django.conf.urls.static import static urlpatterns = [ path("", include("fellchensammlung.urls")), path('admin/', admin.site.urls), ] + +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, + document_root=settings.MEDIA_ROOT)