Flow improvements

Dynamic displaying of received offers
This commit is contained in:
Kumi 2021-04-20 08:36:59 +02:00
parent f51350f28f
commit 81f7d6eb66
20 changed files with 256 additions and 45 deletions

View file

@ -1,3 +1,6 @@
from django.contrib import admin
from urlaubsauktion.admin import joker_admin as admin
# Register your models here.
from .models import Inquiry, Offer
admin.register(Inquiry)
admin.register(Offer)

View file

@ -1,8 +1,11 @@
from django.contrib.gis.db import models
from django.utils import timezone
from django.conf import settings
from clients.models import ClientProfile
from partners.models import Establishment
from partners.models import Establishment, RoomCategory
from dateutil.relativedelta import relativedelta
import uuid
@ -37,10 +40,19 @@ class Inquiry(models.Model):
self.activated = timezone.now()
self.save()
@property
def expiry(self):
if self.activated:
return self.activated + relativedelta(days=settings.INQUIRY_RUNTIME)
@property
def expired(self):
return self.expiry and (self.expiry < timezone.now())
@property
def active(self):
try:
return bool(self.activated)
return bool(self.activated) and not self.expired
except:
return False
@ -52,9 +64,18 @@ class Inquiry(models.Model):
return qset[0]
class Offer(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, unique=True)
inquiry = models.ForeignKey(Inquiry, models.PROTECT)
establishment = models.ForeignKey(Establishment, models.PROTECT)
nights = models.IntegerField()
roomcategory = models.ForeignKey(RoomCategory, models.PROTECT)
departure = models.DateField()
comment = models.TextField(null=True, blank=True)
accepted = models.BooleanField(default=False)
hidden = models.BooleanField(default=False)
@property
def establishment(self):
return self.roomcategory.establishment
@property
def nights(self):
return (self.departure - self.inquiry.arrival).days

View file

@ -1,7 +1,7 @@
from django.views.generic import CreateView, UpdateView, View, ListView, DetailView
from django.shortcuts import redirect, get_object_or_404
from django.contrib import messages
from django.urls import reverse
from django.urls import reverse, reverse_lazy
from django.contrib.gis.geos import Point
from django.contrib.gis.db.models.functions import Distance
from django.conf import settings
@ -110,14 +110,16 @@ class OfferSelectionTableView(InConstructionMixin, ListView):
def get_queryset(self):
inquiry = get_object_or_404(Inquiry, uuid=self.kwargs["uuid"])
return inquiry.offer_set.all()
class OfferCreationView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView):
model = Offer
template_name = "auction/offer_create.html"
fields = []
fields = ["roomcategory", "departure", "comment"]
def dispatch(self, request, *args, **kwargs):
self.establishment = self.get_establishment()
self.inquiry = self.get_inquiry()
if not self.establishment:
messages.warning(request, "Um bieten zu können, muss zuerst eine Unterkunft im System hinterlegt werden!")
@ -135,12 +137,23 @@ class OfferCreationView(InConstructionMixin, PartnerProfileRequiredMixin, Create
else:
return Establishment.objects.filter(**kwargs).first()
def get_inquiry(self):
return get_object_or_404(Inquiry, uuid=self.kwargs.get("inquiry"))
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["establishment"] = self.establishment
context["inquiry"] = get_object_or_404(Inquiry, uuid=self.kwargs.get("inquiry"))
context["inquiry"] = self.inquiry
return context
def form_valid(self, form):
form.instance.inquiry = self.inquiry
return super().form_valid(form)
def get_success_url(self):
messages.success(self.request, "Angebot erfolgreich erstellt! Viel Erfolg!")
return reverse_lazy("auction:bidding", args=[self.establishment.id])
class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView):
model = Inquiry
template_name = "auction/bidding_list.html"
@ -166,7 +179,8 @@ class BiddingListView(InConstructionMixin, PartnerProfileRequiredMixin, ListView
def get_queryset(self):
establishment = self.get_establishment()
return Inquiry.objects.annotate(distance=Distance("destination_coords", establishment.coords)).exclude(activated__isnull=True)
excluded = [offer.inquiry.id for offer in establishment.offer_set.all()]
return Inquiry.objects.annotate(distance=Distance("destination_coords", establishment.coords)).exclude(activated__isnull=True).exclude(id__in=excluded)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)

View file

@ -35,3 +35,7 @@ JOKER_COUNTRIES = ["AT"]
CURRENCY_SYMBOL = ""
CURRENCY_CODE = "EUR"
CURRENCY_NAME = "Euro"
# Run time of inquiries in days
INQUIRY_RUNTIME = 7

View file

@ -1,3 +1,7 @@
from django.contrib import admin
from urlaubsauktion.admin import joker_admin as admin
# Register your models here.
from .models import PartnerProfile, Establishment, RoomCategory
admin.register(PartnerProfile)
admin.register(Establishment)
admin.register(RoomCategory)

View file

@ -18,7 +18,7 @@ class Establishment(LocationMixin, ImageMixin, PhoneMixin):
superior = models.BooleanField("Superior", default=False)
verified = models.BooleanField(default=False)
active = models.BooleanField(default=True)
featureset = models.OneToOneField(FeatureSet, models.PROTECT, null=True)
featureset = models.OneToOneField(FeatureSet, models.PROTECT, null=True, blank=True)
@property
def user(self):
@ -32,7 +32,16 @@ class Establishment(LocationMixin, ImageMixin, PhoneMixin):
def booking_set(self):
return self.offer_set.filter(accepted=True)
@property
def offer_set(self):
querysets = []
for roomcategory in self.roomcategory_set.all():
querysets.append(roomcategory.offer_set.all())
return querysets[0].union(*querysets[1:])
class RoomCategory(ImageMixin):
establishment = models.ForeignKey(Establishment, models.CASCADE)
name = models.CharField(max_length=64)
average_price = models.DecimalField(max_digits=10, decimal_places=2)
name = models.CharField("Name", max_length=64)
average_price = models.DecimalField("Durchschnittspreis / Nacht", max_digits=10, decimal_places=2)
active = models.BooleanField(default=True)

View file

@ -5,8 +5,8 @@ register = template.Library()
@register.simple_tag
def stars(number, superior=False, color=""):
number = int(number)
if not 1 <= number <= 5:
raise ValueError("Number of stars must be between 1 and 5.")
if not 0 <= number <= 5:
raise ValueError("Number of stars must be between 0 and 5.")
output = ""
@ -22,7 +22,7 @@ def stars(number, superior=False, color=""):
def hearts(number, color=""):
number = int(number)
if not 1 <= number <= 5:
raise ValueError("Number of hearts must be between 1 and 5.")
raise ValueError("Number of hearts must be between 0 and 5.")
output = ""

View file

@ -1,7 +1,7 @@
from django.urls import path, reverse_lazy
from django.views.generic import RedirectView
from .views import PartnerRegistrationView, PartnerProfileView, OffersListView, EstablishmentsListView, EstablishmentRequestView, PartnerDashboardView, EstablishmentVerificationView
from .views import PartnerRegistrationView, PartnerProfileView, OffersListView, EstablishmentsListView, EstablishmentRequestView, PartnerDashboardView, EstablishmentVerificationView, RoomCategoryListView
app_name = "partners"
@ -9,6 +9,7 @@ urlpatterns = [
path('register/', PartnerRegistrationView.as_view(), name="register"),
path('profile/', PartnerProfileView.as_view(), name="profile"),
path('establishments/', EstablishmentsListView.as_view(), name="establishments"),
path('establishments/<int:id>/', RoomCategoryListView.as_view(), name="roomcategories"),
path('establishments/validate/', EstablishmentVerificationView.as_view(), name="establishment_verify"),
path('establishments/register/', EstablishmentRequestView.as_view(), name="establishment_register"),
path('offers/', OffersListView.as_view(), name="offers"),

View file

@ -4,7 +4,7 @@ from django.http import HttpResponseRedirect
from django.shortcuts import get_list_or_404, redirect, get_object_or_404
from django.contrib import messages
from .models import PartnerProfile, Establishment
from .models import PartnerProfile, Establishment, RoomCategory
from .mixins import PartnerProfileRequiredMixin
from .forms import VerificationForm
@ -82,6 +82,46 @@ class EstablishmentsListView(InConstructionMixin, PartnerProfileRequiredMixin, L
def get_queryset(self):
return self.request.user.partnerprofile.establishment_set.all()
class RoomCategoryListView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView, ListView):
model = RoomCategory
template_name = "partners/roomcategory_list.html"
fields = ["name", "average_price"]
def dispatch(self, request, *args, **kwargs):
self.establishment = self.get_establishment()
if not self.establishment:
messages.warning(request, "Um bieten zu können, muss zuerst eine Unterkunft im System hinterlegt werden!")
return redirect("partners:establishment_register")
return super().dispatch(request, *args, **kwargs)
def get_establishment(self):
establishment = self.kwargs.get("id", None)
kwargs = {"owner": self.request.user.partnerprofile}
if establishment:
kwargs["id"] = establishment
return get_object_or_404(Establishment, **kwargs)
else:
return Establishment.objects.filter(**kwargs).first()
def get_queryset(self):
establishment = self.establishment
return RoomCategory.objects.filter(establishment=establishment)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["establishment"] = self.establishment
return context
def form_valid(self, form):
form.instance.establishment = self.establishment
return super().form_valid(form)
def get_success_url(self):
return reverse_lazy("partners:roomcategories", args=[self.establishment.id])
class EstablishmentRequestView(InConstructionMixin, PartnerProfileRequiredMixin, CreateView):
model = Establishment
template_name = "partners/establishment_register.html"
@ -112,4 +152,4 @@ class EstablishmentVerificationView(SuperUserRequiredMixin, FormView):
messages.success(self.request, "Unterkunft %s bestätigt!" % eobj[0].name)
return HttpResponseRedirect(resolve_url("partners:establishment_verify"))
return HttpResponseRedirect(reverse_lazy("partners:establishment_verify"))

View file

@ -16,4 +16,5 @@ phonenumbers
googlemaps
Babel
staticmap
django-mathfilters
git+https://kumig.it/kumisystems/PyInvoice

View file

@ -15,7 +15,11 @@
<div class="row d-flex justify-content-center">
<div class="col-md-12 col-lg-12 col-lg-offset-2">
<h2>{% trans "Verfügbare Anfragen" %}</h2>
<div>für {{ establishment.name }}</div>
<div>für <select id="id_establishment" name="establishment" class="">
{% for e in request.user.partnerprofile.establishment_set.all %}
<option value="{{ e.id }}" {% if e == establishment %}selected{% endif %}>{{ e.name }}</option>
{% endfor %}
</select> </div>
<table id="biddingtable">
<thead>
<td>ID</td>

View file

@ -3,6 +3,7 @@
{% load static %}
{% load mapimage %}
{% load dbsetting %}
{% load mathfilters %}
{% block "content" %}
<!--================== PAGE-COVER ================-->
<section class="page-cover" id="cover-hotel-booking">
@ -51,6 +52,10 @@
<td>{% trans "Anreisedatum" %}</td>
<td>{{ inquiry.arrival|date:"SHORT_DATE_FORMAT" }}</td>
</tr>
<tr>
<td>{% trans "Aufenthaltsdauer" %}</td>
<td>{% if inquiry.min_nights == 0 %}Egal!{% elif inquiry.min_nights == 1 %}Kurztrip (2 3 Nächte){% else %}min. 3 Nächte{% endif %}</td>
</tr>
<tr>
<td>{% trans "Erwachsene" %}</td>
<td>{{ inquiry.adults }}</td>
@ -112,7 +117,9 @@
<div class="form-group">
<label>{% trans "Zimmerkategorie" %}</label>
<select class="form-control" id="id_roomcategory" name="roomcategory">
<option value="0">Standardzimmer</option>
{% for roomcategory in establishment.roomcategory_set.all %}
<option value="{{ roomcategory.id }}">{{ roomcategory.name }} (€ {{ roomcategory.average_price }}/Nacht {{ inquiry.budget|intdiv:roomcategory.average_price }} Nächte)</option>
{% endfor %}
</select>
</div>
</div><!-- end columns -->
@ -145,10 +152,10 @@
</div><!-- end row -->
<div class="checkbox">
<label><input type="checkbox" {% if request.user.is_authenticated %}required{% else %}disabled{% endif %} id="id_terms" name="terms"> {% trans "Ich erkläre mich einverstanden mit den" %} <a href="#">{% trans "Allgemeinen Geschäftsbedingungen" %}</a> {% trans "und der" %} <a href="#">{% trans "Datenschutzerklärung" %}</a>. Ich verstehe insbesondere, dass ich an dieses Angebot gebunden bin und dieses nach Annahme durch die anfragende Person nicht mehr zurückziehen kann.</label>
<label><input type="checkbox" required id="id_terms" name="terms"> {% trans "Ich erkläre mich einverstanden mit den" %} <a href="#">{% trans "Allgemeinen Geschäftsbedingungen" %}</a> {% trans "und der" %} <a href="#">{% trans "Datenschutzerklärung" %}</a>. Ich verstehe insbesondere, dass ich an dieses Angebot gebunden bin und dieses nach Annahme durch die anfragende Person nicht mehr zurückziehen kann.</label>
</div><!-- end checkbox -->
<div class="col-md-12 text-center" id="result_msg"></div>
<button type="submit" onclick="setPaymentMethod(); return true;" class="btn btn-orange" name="submit" id="submit">{% trans "Zahlung durchführen" %}</button>
<button type="submit" class="btn btn-orange" name="submit" id="submit">{% trans "Angebot erstellen" %}</button>
</form>
</div><!-- end columns -->

View file

@ -14,7 +14,13 @@
<div class="col-md-12 col-lg-8 col-lg-offset-2">
<div class="payment-success-text">
<h1>Angebote vergleichen</h1>
{% if object.offer_set.all %}
<div id="offers" style="text-align: center;"></div>
{% else %}
<div class="alert alert-warning alert-dismissible text-center" role="alert">
Leider sind zu deiner Anfrage bislang noch keine Angebote eingegangen. Komm doch einfach später nochmal vorbei!
</div>
{% endif %}
</div>
</div><!-- end columns -->
</div><!-- end row -->

View file

@ -6,30 +6,40 @@
{
from: "",
tableHeader: [
['Habbo Hotel<br/>{% autoescape off %}{% stars 3 1 orange %}{% endautoescape %}<br/><img style="max-height:100px;max-width:100%;" src="https://logoeps.com/wp-content/uploads/2012/12/habbo-logo-vector.png"></img>'],
['Kumi Systems<br/>{% autoescape off %}{% stars 1 0 orange %}{% endautoescape %}<br/><img style="max-height:100px;max-width:100%;" src="https://kumi.systems/wp-content/uploads/2020/12/schrift_logo.png"></img>'],
{% for offer in object_list %}['{{ offer.roomcategory.establishment.name }}<br/>{% autoescape off %}{% stars offer.roomcategory.establishment.stars offer.roomcategory.establishment.superior orange %}{% endautoescape %}{% if offer.roomcategory.establishment.image %}<br/><img style="max-height:100px;max-width:100%;" src="{{ offer.roomcategory.establishment.image.url }}"></img>{% endif %}'],{% endfor %}
],
rows : [
{
rowVal: [["1. Mai 2021", "1. Mai 2021"],["3. Mai 2021", "10. Mai 2021"],["2 Nächte", "9 Nächte"]],
rowVal: [
[{% for offer in object_list %}'{{ offer.inquiry.arrival }}',{% endfor %}],
[{% for offer in object_list %}'{{ offer.departure }}',{% endfor %}],
[{% for offer in object_list %}'{{ offer.nights }} Nächte',{% endfor %}]
],
rowDesc: ["Anreise", "Abreise", "Dauer"]
},
{
rowVal: [[{% autoescape off %}'{% hearts 3 red %} (304)', '{% hearts 5 red %} (1)'{% endautoescape %}]],
rowVal: [
[{% for offer in object_list %}{% autoescape off %}'{% hearts 3 red %} (304)'{% endautoescape %},{% endfor %}]
],
rowDesc: ["Bewertungen"]
},
{
rowVal: [['Doppelzimmer Luxus', 'Wohnzimmer'], ["1 King-Size Bett", "1 Couch"]],
rowVal: [
[{% for offer in object_list %}'{{ offer.roomcategory.name }}',{% endfor %}],
[{% for offer in object_list %}'&nbsp;',{% endfor %}]
],
rowDesc: ["Zimmerart", "Betten"]
},
{
rowVal: [['Romantikpaket inkl. Frühstück am Bett, 2x 60 Minuten Hot-Stone-Massage, 0,75l Prosecco, Obstschale, Zugang zum Spa', 'Gratis Arbeitsgelegenheit inklusive!']],
rowVal: [
[{% for offer in object_list %}'{{ offer.comment }}',{% endfor %}]
],
rowDesc: ["Zusätzliche Angaben"]
},
{
rowVal: [
[200, 200],
['<button class="btn btn-orange btn-block">Zahlungspflichtig buchen!</button>', '<button class="btn btn-orange btn-block">Zahlungspflichtig buchen!</button>']
[{% for offer in object_list %}'€ {{ offer.inquiry.budget }}',{% endfor %}],
[{% for offer in object_list %}'<a href="#{{ offer.uuid }}" class="btn btn-orange btn-block">Zahlungspflichtig buchen!</button>',{% endfor %}]
],
rowDesc: ["Fixpreis", ""]
}

View file

@ -55,6 +55,10 @@
<td>{% trans "Anreisedatum" %}</td>
<td>{{ object.arrival|date:"SHORT_DATE_FORMAT" }}</td>
</tr>
<tr>
<td>{% trans "Aufenthaltsdauer" %}</td>
<td>{% if object.min_nights == 0 %}Egal!{% elif object.min_nights == 1 %}Kurztrip (2 3 Nächte){% else %}min. 3 Nächte{% endif %}</td>
</tr>
<tr>
<td>{% trans "Erwachsene" %}</td>
<td>{{ object.adults }}</td>
@ -254,7 +258,7 @@
<img src="{% static "frontend/images/paypal.png" %}" class="img-fluid" alt="stripe" />
<div class="paypal-text">
<p>{% trans "Die Zahlung per Kreditkarte wird durch unseren Zahlungsdienstleister Stripe abgewickelt." %}</p>
<p>{% trans "Der gebotene Betrag wird autorisiert und erst bei verbindlicher Buchung einer Reise tatsächlich von Ihrer Kreditkarte abgebucht." %}</p>
<p>{% trans "Der gebotene Betrag wird autorisiert und erst bei verbindlicher Buchung einer Reise tatsächlich von Ihrer Kreditkarte abgebucht. Bei Auslaufen oder Stornierung Ihres Angebots wird der Betrag ohne Abzug wieder freigegeben." %}</p>
</div><!-- end paypal-text -->
<div class="clearfix"></div>

View file

@ -28,19 +28,29 @@
<div class="table-responsive">
<table class="table table-hover">
<tbody>
{% for inquiry in object_list %}
<tr>
<td class="dash-list-icon booking-list-date"><div class="b-date"><h3>12</h3><p>April 2021</p></div></td>
<td class="dash-list-icon booking-list-date"><div class="b-date"><h3>{{ inquiry.arrival.day }}</h3><p>{{ inquiry.arrival|date:"E Y" }}</p></div></td>
<td class="dash-list-text booking-list-detail">
<h3>Habbo Hotel</h3>
<h3>{% if inquiry.accepted %}{{ inquiry.accepted.name }} ({{ inquiry.destination_name }}){% else %}{{ inquiry.destination_name }}{% endif %}</h3>
<ul class="list-unstyled booking-info">
<li><span>Ankunft:</span> 12. April 2021</li>
<li><span>Abreise:</span> 19. April 2021</li>
<li><span>Preis:</span> € 500,00</li>
<li><span>Ankunft:</span> {{ inquiry.arrival }}</li>
<li><span>{% if inquiry.accepted %}Abreise{% else %}Dauer{% endif %}:</span> {% if inquiry.accepted %}{{ inquiry.accepted.departure }}{% elif inquiry.min_nights == 0 %}Egal!{% elif inquiry.min_nights == 1 %}Kurztrip (2 3 Nächte){% elif inquiry.min_nights == 2 %}min. 3 Nächte{% endif %}</li>
<li><span>Preis:</span> € {{ inquiry.budget }}</li>
<li><span>Status:</span> {% if inquiry.accepted %}Fixiert{% elif inquiry.active %}In Gebotsphase ({{ inquiry.offer_set.all|length }} Gebote){% else %}Inaktiv{% endif %}</li>
</ul>
<button class="btn btn-orange">Details</button>
{% if inquiry.accepted %}
<button class="btn btn-orange">Buchungsdetails</button>
{% elif inquiry.active %}
<a href="{% url "auction:offer_selection" inquiry.uuid %}" class="btn btn-orange">Gebote ansehen</a>
{% elif inquiry.expired %}
{% else %}
<a href="{% url "auction:process_inquiry" inquiry.uuid %}" class="btn btn-orange">Zahlung abschließen</a>
{% endif %}
</td>
<td class="dash-list-btn"><button class="btn btn-orange">Stornieren</button><button class="btn">PDF-Bestätigung</button></td>
</tr>
{% endfor %}
</tbody>
</table>
</div><!-- end table-responsive -->

View file

@ -35,9 +35,9 @@
<li><span>Buchungen:</span> {{ establishment.bookings | length }}</li>
<li><span>Status:</span> {% if establishment.is_active %}aktiv{% else %}inaktiv{% endif %}</li>
</ul>
<button class="btn btn-orange">Details</button>
<a href="{% url "partners:roomcategories" establishment.id %}" class="btn btn-orange">Zimmer und Ausstattung bearbeiten</button>
</td>
<td class="dash-list-btn"><a href="{% url "partners:bidding" 1 %}" class="btn btn-orange">Bieten</a><button class="btn">Deaktivieren</button></td>
<td class="dash-list-btn"><a href="{% url "auction:bidding" establishment.id %}" class="btn btn-orange">Bieten</a><button class="btn">Deaktivieren</button></td>
</tr>
{% endfor %}
</tbody>

View file

@ -1,4 +1,4 @@
{% extends "clients/base.html" %}
{% extends "partners/base.html" %}
{% load i18n %}
{% load bootstrap4 %}
{% block "dashboardcontent" %}

View file

@ -0,0 +1,71 @@
{% extends "partners/base.html" %}
{% load i18n %}
{% load bootstrap4 %}
{% block "dashboardcontent" %}
<div class="col-12 col-md-10 col-lg-10 dashboard-content booking-trips">
<h2 class="dash-content-title">Deine Zimmerkategorien</h2>
<div class="dash-content-title"><small>für {{ establishment.name }}</small></div>
<div class="dash-content-title"><button class="btn" data-toggle="modal" data-target="#create-category">Kategorie hinzufügen</button></div>
<div class="dashboard-listing booking-listing">
<div class="dash-listing-heading">
<div class="custom-radio">
<input type="radio" id="radio01" name="radio" checked/>
<label for="radio01"><span></span>Alle Kategorien</label>
</div><!-- end custom-radio -->
<div class="custom-radio">
<input type="radio" id="radio02" name="radio" />
<label for="radio02"><span></span>Aktiv</label>
</div><!-- end custom-radio -->
<div class="custom-radio">
<input type="radio" id="radio03" name="radio" />
<label for="radio03"><span></span>Inaktiv</label>
</div><!-- end custom-radio -->
</div>
<div class="table-responsive">
<table class="table table-hover">
<tbody>
{% for roomcategory in object_list %}
<tr>
<td class="dash-list-text booking-list-detail">
<h3>{{ roomcategory.name }}</h3>
<ul class="list-unstyled booking-info">
<li><span>Durchschnittspreis:</span> {{ roomcategory.average_price }}</li>
<li><span>Buchungen:</span> {{ roomcategory.bookings | length }}</li>
<li><span>Status:</span> {% if roomcategory.active %}aktiv{% else %}inaktiv{% endif %}</li>
</ul>
<a href="{% url "partners:roomcategories" establishment.id %}" class="btn btn-orange">Zimmer und Ausstattung bearbeiten</button>
</td>
<td class="dash-list-btn"><a href="{% url "auction:bidding" establishment.id %}" class="btn btn-orange">Bieten</a><button class="btn">Deaktivieren</button></td>
</tr>
{% endfor %}
</tbody>
</table>
</div><!-- end table-responsive -->
</div><!-- end booking-listings -->
</div><!-- end columns -->
{% endblock %}
{% block "modal" %}
<div id="create-category" class="modal custom-modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">Profildaten</h3>
<button type="button" class="close" data-dismiss="modal">&times;</button>
</div><!-- end modal-header -->
<div class="modal-body">
<form method="POST">
{% csrf_token %}
{% bootstrap_form form %}
<button class="btn btn-orange btn-block">Anwenden</button>
</form>
</div><!-- end modal-bpdy -->
</div><!-- end modal-content -->
</div><!-- end modal-dialog -->
</div><!-- end edit-profile -->
{% endblock %}

View file

@ -14,6 +14,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.gis',
'phonenumber_field',
'localauth',
'public',
@ -24,6 +25,7 @@ INSTALLED_APPS = [
'auction',
'bootstrap4',
'django_countries',
'mathfilters',
]
MIDDLEWARE = [