24 Commits

Author SHA1 Message Date
01f7dad37c Translated Model fields - primarily for backend. 2020-10-11 21:56:14 +02:00
2bfdf5c172 Translated place deletion question with blrocktrans in a more natural way. 2020-10-11 21:55:38 +02:00
15f6a30cd6 Streamlined translations ... again :P 2020-10-11 21:27:27 +02:00
812c921a42 Merge commit 'dafe7eee3489e3a7c17b6560fc2aa09648773ecd' into feature/localization 2020-10-11 17:20:53 +02:00
dafe7eee34 Deleted mishap. 2020-10-11 09:47:34 +02:00
7943537276 Translated an additional bunch of messages. 2020-10-11 07:50:15 +02:00
62c1c84bb2 Minor code styling issue. 2020-10-11 07:49:50 +02:00
df36fd8ed0 Fixed the fixes' translation ;-) 2020-10-11 07:15:33 +02:00
8713ed587d Small indentation fix. 2020-10-11 07:13:16 +02:00
7271ea2cd9 Merge branch 'feature/localization' into develop 2020-10-11 07:09:59 +02:00
dff2e67991 Ops. Forgot one file. 2020-10-11 07:05:17 +02:00
65880d1472 Renamed migration file with typo. 2020-10-11 07:04:32 +02:00
326e34a4b8 Fixed i18n to invalidate decimal geocoords. 2020-10-11 06:55:12 +02:00
3a213c87b5 Added a German Urbex codec. 2020-10-11 06:44:06 +02:00
1b197b2e12 Added query for German language to FlatView. 2020-10-11 06:15:40 +02:00
092378b24a Rename localized flat pages to include langcode. 2020-10-11 06:14:55 +02:00
561c70668d Merge remote-tracking branch 'origin/develop' into develop 2020-10-11 02:46:16 +02:00
86fbee4116 Merge from master 2020-10-04 22:12:53 +02:00
ab3ecae54b Voucher is_valid property 2020-10-04 22:12:44 +02:00
ae915681ac Testing is_expired 2020-10-04 22:12:24 +02:00
cfbe54a4e5 Making expireable a abstract model 2020-10-04 22:11:37 +02:00
76b514e1e6 #40 Hotfix Error when signing up 2020-10-04 15:42:06 +02:00
e32b3f6595 Merge branch 'develop' of mowoe.com:reverend/lostplaces-backend into develop 2020-09-29 21:28:53 +02:00
12f60bcfdf Added can_modify_place_asset template tag. 2020-09-29 20:40:46 +02:00
28 changed files with 434 additions and 80 deletions

View File

@@ -17,7 +17,7 @@ class ExplorerCreationForm(UserCreationForm):
voucher = forms.CharField(
max_length=30,
help_text=_('The Voucher you got from an administrator')
)
)
def is_valid(self):
super().is_valid()
@@ -28,7 +28,7 @@ class ExplorerCreationForm(UserCreationForm):
self.add_error('voucher', _('Invalid voucher'))
return False
if not submitted_voucher.valid:
if not fetched_voucher.valid:
self.add_error('voucher', _('Expired voucher'))
return False

View File

@@ -8,11 +8,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-11 02:14+0200\n"
"POT-Creation-Date: 2020-10-11 21:53+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Commander1024 <commander@commander1024.de>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: de.DE\n"
"Language: de-DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -30,26 +30,42 @@ msgstr "Ungültiger Voucher"
msgid "Expired voucher"
msgstr "Abgelaufener Voucher"
#: models/abstract_models.py:28
#: models/abstract_models.py:29
msgid "Name"
msgstr "Name"
#: models/abstract_models.py:35
#: models/abstract_models.py:36
msgid "Latitude"
msgstr "Breitengrad"
#: models/abstract_models.py:36
#: models/abstract_models.py:37
msgid "Latitude in decimal format: e. g. 41.40338"
msgstr "Breitengrad in dezimaler Form: z. B. 51.95021"
#: models/abstract_models.py:43
#: models/abstract_models.py:44
msgid "Longitude"
msgstr "Längengrad"
#: models/abstract_models.py:44
#: models/abstract_models.py:45
msgid "Longitude in decimal format: e. g. 2.17403"
msgstr "Breitengrad in dezimaler Form: z. B. 7.4840155"
#: models/abstract_models.py:59
msgid "Submission date"
msgstr "Einreichungsdatum"
#: models/abstract_models.py:67
msgid "Submitter"
msgstr "Einreicher"
#: models/abstract_models.py:79
msgid "Creation date"
msgstr "Erstellungsdatum"
#: models/abstract_models.py:82
msgid "Expiration date"
msgstr "Ablaufdatum"
#: models/external_links.py:13
msgid "URL"
msgstr "Adresse (URL)"
@@ -96,7 +112,7 @@ msgstr "Zurück"
#: templates/global.html:32
msgid "Logout"
msgstr "Abmelden"
msgstr "Ausloggen"
#: templates/global.html:34
msgid "Admin"
@@ -108,8 +124,8 @@ msgid "Login"
msgstr "Anmelden"
#: templates/global.html:40 templates/registration/login.html:29
#: templates/signup.html:12 templates/signup.html:41
msgid "Sign Up"
#: templates/signup.html:6 templates/signup.html:12 templates/signup.html:41
msgid "Sign up"
msgstr "Registrieren"
#: templates/global.html:50 templates/home.html:10
@@ -122,11 +138,11 @@ msgstr "UrBex Codex"
#: templates/global.html:56 templates/place/place_create.html:5
#: templates/place/place_create.html:10
msgid "Create Place"
msgid "Create place"
msgstr "Place erstellen"
#: templates/global.html:57
msgid "All Places"
msgid "All places"
msgstr "Alle Places"
#: templates/home.html:20 templates/home_unauth.html:20
@@ -247,7 +263,8 @@ msgid "Submit a photo album"
msgstr "Fotoalbum hinzufügen"
#: templates/photo_album/photo_album_create.html:8
#: templates/place/place_detail.html:18
#: templates/place/place_detail.html:18 templates/place/place_update.html:5
#: templates/place/place_update.html:10
msgid "Edit place"
msgstr "Place bearbeiten"
@@ -265,12 +282,13 @@ msgid "Create"
msgstr "Erstellen"
#: templates/place/place_delete.html:5
msgid "Lost Place Deletion"
msgid "Delete lost place"
msgstr "Lost Place löschen"
#: templates/place/place_delete.html:15
msgid "Are you sure you want to delete"
msgstr "Willst Du den Ort wirklich löschen: "
#, python-format
msgid "Are you sure you want to delete %(place_name)s?"
msgstr "Bist Du sicher, dass Du %(place_name)s löschen möchtest?"
#: templates/place/place_delete.html:19
msgid "Delete"
@@ -293,17 +311,13 @@ msgid "Images"
msgstr "Bilder"
#: templates/place/place_list.html:10
msgid "Lost Places"
msgid "All Places"
msgstr "Alle Places"
#: templates/place/place_list.html:16
msgid "Listing our places"
msgid "Our lost places"
msgstr "Unsere Lost Places"
#: templates/place/place_update.html:5 templates/place/place_update.html:10
msgid "Update place"
msgstr "Place bearbeiten"
#: templates/place/place_update.html:42
msgid "Update"
msgstr "Aktualisieren"
@@ -313,13 +327,61 @@ msgid "Submit images to a place"
msgstr "Bilder zu einem Place hinzufügen"
#: templates/registration/login.html:29
msgid "Have No Account Yet?"
msgid "No account, yet?"
msgstr "Noch kein Konto?"
#: templates/signup.html:6
msgid "Sign up"
msgstr "Registrieren"
#: views/base_views.py:25
msgid "Please login to proceed"
msgstr "Bitte log Dich ein um fortzufahren."
msgstr "Bitte log Dich ein um fortzufahren"
#: views/place_image_views.py:26
msgid "Image(s) submitted successfully"
msgstr "Bild(er) erfolgreich hinzugefügt"
#: views/place_image_views.py:41
msgid "Image deleted successfully"
msgstr "Bild erfolgreich gelöscht"
#: views/place_image_views.py:42
msgid "You are not allowed to delete this image"
msgstr "Du darfst dieses Bild nicht löschen"
#: views/place_views.py:62
msgid "Successfully updated place"
msgstr "Place erfolgreich aktualisiert"
#: views/place_views.py:63
msgid "You are not allowed to edit this place"
msgstr "Du darfst diesen Place nicht bearbeiten"
#: views/place_views.py:97
msgid "Successfully created place"
msgstr "Place erfolgreich erstellt"
#: views/place_views.py:105
msgid "Please fill in all required fields."
msgstr "Bitte füll alle benötigten Felder aus."
#: views/place_views.py:112
msgid "Successfully deleted place"
msgstr "Place erfolgreich gelöscht"
#: views/place_views.py:114
msgid "You are not allowed to delete this place"
msgstr "Du darfst diesen Place nicht löschen"
#: views/views.py:29
msgid "User created"
msgstr "Benutzer erstellt"
#: views/views.py:54
msgid "Photo album link submitted"
msgstr "Fotoalbum-Link hinzugefügt"
#: views/views.py:59
msgid "Photo album link deleted"
msgstr "Fotoalbum-Link gelöscht"
#: views/views.py:60
msgid "You are not allowed to edit this photo album link"
msgstr "Du darfst diesen Fotoalbum-Link nicht bearbeiten"

View File

@@ -0,0 +1,22 @@
# Generated by Django 3.1.1 on 2020-10-04 19:37
# Edited by reverend
import datetime
from django.db import migrations, models
import django.utils.timezone
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('lostplaces', '0001_initial'),
]
operations = [
migrations.DeleteModel(
name='Voucher'
),
migrations.DeleteModel(
name='Expireable'
)
]

View File

@@ -0,0 +1,25 @@
# Generated by Django 3.1.1 on 2020-10-04 19:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lostplaces', '0002_remove_vouchers'),
]
operations = [
migrations.CreateModel(
name='Voucher',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_when', models.DateTimeField(auto_now_add=True)),
('expires_when', models.DateTimeField()),
('code', models.CharField(max_length=30, unique=True)),
],
options={
'abstract': False,
},
),
]

View File

@@ -1,4 +1,5 @@
from django.utils import timezone
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.validators import MaxValueValidator, MinValueValidator
@@ -52,18 +53,35 @@ class Submittable(models.Model):
class Meta:
abstract = True
submitted_when = models.DateTimeField(auto_now_add=True, null=True)
submitted_when = models.DateTimeField(
auto_now_add=True,
null=True,
verbose_name=_('Submission date')
)
submitted_by = models.ForeignKey(
'Explorer',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='%(class)ss'
related_name='%(class)ss',
verbose_name=_('Submitter')
)
class Expireable(models.Model):
"""
Base class for things that can expire, i.e. VouchersAv
Base class for things that can expire, i.e. Vouchers
"""
created_when = models.DateTimeField(auto_now_add=True)
expires_when = models.DateTimeField()
class Meta:
abstract = True
created_when = models.DateTimeField(
auto_now_add=True,
verbose_name=_('Creation date')
)
expires_when = models.DateTimeField(
verbose_name=_('Expiration date')
)
@property
def is_expired(self):
return timezone.now() > self.expires_when

View File

@@ -49,6 +49,10 @@ class Voucher(Expireable):
"""
code = models.CharField(unique=True, max_length=30)
@property
def valid(self):
return not self.is_expired
def __str__(self):
return "Voucher " + str(self.code)

View File

@@ -138,4 +138,4 @@ def auto_delete_file_on_change(sender, instance, **kwargs):
new_file = instance.filename
if not old_file == new_file:
if os.path.isfile(old_file.path):
os.remove(old_file.path)
os.remove(old_file.path)

View File

@@ -0,0 +1,52 @@
{% extends 'global.html'%}
# {% block title %}UrBex Codex{% endblock %}
{% block maincontent %}
<header class="LP-TextSection__Headline">
<h1 class="LP-Headline">Nimm nichts mit - außer Deinen Bildern. Laß nichts da - außer Deinen Fußspuren!</h1>
</header>
<article class="LP-TextSection LP-TextSection__Text">
<p>Das sollte doch eigentlich eindeutig sein, oder? Aber wie wir alle wissen, hat jedes Schild eine Geschichte. Wir haben zu viel sinnlose Zerstörung gesehen, sodass wir uns dazu entschieden haben, einen grundlegenden Urban Exploration Codex niederzuschreiben.</p>
<ul class="LP-UnorderedList">
<li>
<b>Wir respektieren fremdes Eigentum</b>, so wie wir das von anderen auch verlangen. Deswegen öffnen wir keinen Zugang gewaltsam, oder beschädigen eine Verschlusseinrichtung. Wir betreten ein Grundstück oder ein Gebäude / eine Anlage / eine Ruine nur dann, wenn wir davon ausgehen können, nicht gegen den Willen des Eigentümers dort zu sein. Eine gut erhaltene Umzäunung, oder ein ständiger Wachschutz sprechen dafür, dass der Eigentümer sich noch mit seiner Anlage befasst. Längst umgesunkene Zäune, Ruinen im letzten Stadium eines Verfalls sprecher dafür, dass dem Eigentümer das eher Wurst ist.
</li>
<li>
<b>Wir nehmen von einer Location nichts mit</b>, auch keine "kleinen Andenken", und lassen nichts da - auch keine Kippen, keine Verpackungen - nichts.
<b>Wir verändern am Ort nichts, nehmen nichts weg und fügen nichts hinzu.</b>
</li>
<li>
<b>Wir rauchen möglichst nicht.</b> Nicht nur, weil es stinkt und Müll verursacht. Es gibt immer die Chance, irgendwas durch Funkenflug anzuzünden. Lass es trockene Blätter an einem heißen Sommertag oder (potentielle) entflammbare Materialien in Industrieanlagen sein.
</li>
<li>
<b>Sprayen ist ein absolutes "no-go"!</b>
</li>
<li>
<b>In einer Location verhalten wir uns vorsichtig.</b> Wir werfen nichts in Löcher oder aus Fenstern und berühren auch keine elektrischen Anlagen. Nicht immer ist der Strom wirklich abgeschaltet. Deswegen öffnen wor auch keine Flaschen und andere Behälter. Wir gehen niemals ohne Licht in einen dunklen Raum, und nehmen immer eine Reservelampe mit.
</li>
<li>
<b>Wir sagen vor einer Tour mindestens einer Person unseres Vertrauens, wo wir sind</b> (Koordinaten!), wie lange wir uns dort aufhalten werden und was wir dort tun. Wir verabreden, daß wir uns bei einem längeren Aufenthalt dort regelmäßig melden, oder aber ein "okay" geben, wenn wir die Location wieder verlassen haben. Wenn wir uns verspäten, dann denken wir daran, eine entsprechende Nachricht abzusetzen. Unsere Kontaktperson soll nach einer gewissen Zeit, wenn sie nichts von mir hört, für Hilfe sorgen.
</li>
<li>
<b>Wir bereiten unsere Tour sorgfältig vor.</b> Es ist ärgerlich, wenn die Kamera-Akkus nicht geladen sind - aber gefährlich ist es keineswegs. Es ist aber lebensgefährlich, wenn ein verschmutzter Nagel durch eine Sohle getreten wird. Sicherheitsschuhe zu tragen ist eine gute Idee. Wenn wir unter Tage gehen, nehmen wir angemessenes Equipment mit um uns zu schützen — z. B. einen Gaswarner oder vllt. sogar einen Geigerzähler.
</li>
<li>
<b>Wir parken nicht so, daß Dritte auf unser Vorhaben aufmerksam werden.</b> Unser Hobby braucht keine öffentliche Aufmerksamkeit, die sich auf illegales Betreten von Grundstücken richtet (und illegal dürfte das Betreten ja meist sein ...).
</li>
<li>
<b>Wir verraten unsere Locations nicht</b> und veröffentlichen ausschließlich Fotos, bei denen Geodaten aus den Dateien (EXIF) entfernt worden sind. Deswegen posten wir unterwegs nur dann vom Smartphone, wenn wir absolut sicher sind, dass keine Koordinaten im Bild enthalten sind.
</li>
<li>
<b>Vor allem halten wir die Klappe</b> und geben nicht mit einer tollen, noch unberührt aussehenden Location an. Deine "Freunde" in Facebook kennst Du oft nicht mal persönlich, schon gar nicht in einer Gruppe. Nichts verbreitet sich schneller als ein "Geheimnis", das unter dem Siegel des Vertrauens weitergegeben wurde. Willst Du daran schuld sein, daß hirnbefreite Sprayer auch diesen Ort demolieren?
</li>
<li>
<b>Wir sorgen durch Argumente und Überzeugung dafür, daß unsere Begleiter sich ebenso verhalten!</b> In erster Linie versuchen wir durch unser eigenes Verhalten zu überzeugen.
</li>
</ul>
</article>
{% endblock maincontent %}

View File

@@ -37,7 +37,7 @@
{% else %}
You are not logged in.
<a class="LP-Link" href="{% url 'login' %}"><span class="LP-Link__Text">{% trans 'Login' %}</span></a> |
<a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">{% trans 'Sign Up' %}</span></a>
<a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">{% trans 'Sign up' %}</span></a>
{% endif %}
</span>
</div>
@@ -53,8 +53,8 @@
{% block additional_menu_items %}
{% endblock additional_menu_items %}
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_create'%}" class="LP-Link"><span class="LP-Link__Text">{% trans 'Create Place' %}</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_list'%}" class="LP-Link"><span class="LP-Link__Text">{% trans 'All Places' %}</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_create'%}" class="LP-Link"><span class="LP-Link__Text">{% trans 'Create place' %}</span></a></li>
<li class="LP-Menu__Item LP-Menu__Item--additional"><a href="{% url 'place_list'%}" class="LP-Link"><span class="LP-Link__Text">{% trans 'All places' %}</span></a></li>
</ul>
</nav>
</aside>

View File

@@ -11,7 +11,7 @@
}),
],
view: new ol.View({
center: ol.proj.fromLonLat([{{config.map_center.longitude}}, {{config.map_center.latitude}}]),
center: ol.proj.fromLonLat([{{config.map_center.longitude|safe}}, {{config.map_center.latitude|safe}}]),
zoom: 9
})
});
@@ -21,7 +21,7 @@
{% for point in config.all_points %}
new ol.Feature({
geometry: new ol.geom.Point(
ol.proj.fromLonLat([{{point.longitude}},{{point.latitude}}])
ol.proj.fromLonLat([{{point.longitude|safe}},{{point.latitude|safe}}])
),
url: '{{point.get_absolute_url}}',
name: ' {{point.name}}'

View File

@@ -2,12 +2,12 @@
{% load static %}
{% load i18n %}
# {% block title %}{% trans 'Create Place' %}{% endblock %}
# {% block title %}{% trans 'Create place' %}{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST" enctype="multipart/form-data">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">{% trans 'Create Place' %}</legend>
<legend class="LP-Form__Legend">{% trans 'Create place' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">

View File

@@ -2,7 +2,7 @@
{% load static %}
{% load i18n %}
{% block title %}{% trans 'Lost Place Deletion' %}{% endblock %}
{% block title %}{% trans 'Delete lost place' %}{% endblock %}
{% block maincontent %}
@@ -12,7 +12,7 @@
{% csrf_token %}
<div class="LP-Form__Composition">
<div class="LP-Form__Field LP-Form__InfoText">
<p class="LP-Paragraph">{% trans 'Are you sure you want to delete' %} "{{place.name}}"?</p>
<p class="LP-Paragraph">{% blocktrans with place_name=place.name%}Are you sure you want to delete {{place_name}}?{% endblocktrans %}</p>
</div>
</div>

View File

@@ -47,9 +47,9 @@
{% include 'partials/osm_map.html' with config=mapping_config%}
<div class="LP-LinkList">
<ul class="LP-LinkList__Container">
<li class="LP-LinkList__Item"><a target="_blank" href="https://www.google.com/maps?q={{place.latitude}},{{place.longitude}}" class="LP-Link"><span class="LP-Text">Google Maps</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="https://www.tim-online.nrw.de/tim-online2/?center={{place.latitude}},{{place.longitude}}&icon=true&bg=dop" class="LP-Link"><span class="LP-Text">TIM Online</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="http://www.openstreetmap.org/?mlat={{place.latitude}}&mlon={{place.longitude}}&zoom=16" class="LP-Link"><span class="LP-Text">OSM</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="https://www.google.com/maps?q={{place.latitude|safe}},{{place.longitude|safe}}" class="LP-Link"><span class="LP-Text">Google Maps</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="https://www.tim-online.nrw.de/tim-online2/?center={{place.latitude|safe}},{{place.longitude|safe}}&icon=true&bg=dop" class="LP-Link"><span class="LP-Text">TIM Online</span></a></li>
<li class="LP-LinkList__Item"><a target="_blank" href="http://www.openstreetmap.org/?mlat={{place.latitude|safe}}&mlon={{place.longitude|safe}}&zoom=16" class="LP-Link"><span class="LP-Text">OSM</span></a></li>
</ul>
</div>
</section>
@@ -63,7 +63,7 @@
<a target="_blank" href="{{photo_album.url}}" class="LP-Link">
<span class="LP-Text">{{photo_album.label}}</span>
</a>
{% if user.explorer == photo_album.submitted_by or user.explorer == place.submitted_by %}
{% if user.explorer == photo_album.submitted_by or user.explorer == place.submitted_by %}
<a href="{% url 'photo_album_delete' pk=photo_album.pk%}" class="LP-Link LP-LinkList__ItemHover" title="Delete Photo Album">
<div class="RV-Iconized__Container RV-Iconized__Container--small">
{% icon 'trash' className="RV-Iconized__Icon" %}

View File

@@ -7,13 +7,13 @@
<script src="{% static 'maps/ol.js' %}"></script>
{% endblock additional_head %}
{% block title %}{% trans 'Lost Places' %}{% endblock %}
{% block title %}{% trans 'All Places' %}{% endblock %}
{% block maincontent %}
{% include 'partials/osm_map.html' with config=mapping_config %}
<div class="LP-PlaceList">
<h1 class="LP-Headline">{% trans 'Listing our places' %}</h1>
<h1 class="LP-Headline">{% trans 'Our lost places' %}</h1>
<ul class="LP-PlaceList__List">
{% for place in place_list %}
<li class="LP-PlaceList__Item">

View File

@@ -2,12 +2,12 @@
{% load static %}
{% load i18n %}
# {% block title %}{% trans 'Update place' %}{% endblock %}
# {% block title %}{% trans 'Edit place' %}{% endblock %}
{% block maincontent %}
<form class="LP-Form" method="POST" enctype="multipart/form-data">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">{% trans 'Update place' %}</legend>
<legend class="LP-Form__Legend">{% trans 'Edit place' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">

View File

@@ -26,6 +26,6 @@
</fieldset>
</form>
<p class="LP-Headline">{% trans 'Have No Account Yet?' %} <a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">{% trans 'Sign Up' %}</span></a></p>
<p class="LP-Headline">{% trans 'No account, yet?' %} <a class="LP-Link" href="{% url 'signup' %}"><span class="LP-Link__Text">{% trans 'Sign up' %}</span></a></p>
{% endblock maincontent %}

View File

@@ -9,7 +9,7 @@
<form class="LP-Form" method="POST">
<fieldset class="LP-Form__Fieldset">
<legend class="LP-Form__Legend">{% trans 'Sign Up' %}</legend>
<legend class="LP-Form__Legend">{% trans 'Sign up' %}</legend>
{% csrf_token %}
<div class="LP-Form__Composition LP-Form__Composition--breakable">
<div class="LP-Form__Field">
@@ -38,7 +38,7 @@
<div class="LP-Form__Composition LP-Form__Composition--buttons">
<div class="LP-Form__Field LP-Form__Button LP-Input">
<button class="LP-Button">{% trans 'Sign Up' %}</button>
<button class="LP-Button">{% trans 'Sign up' %}</button>
</div>
</div>
</fieldset>

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
from django import template
from django.http import request
register = template.Library()
@@ -22,4 +23,4 @@ def proper_paginate(paginator, current_page, neighbors=2):
end_index = paginator.num_pages
page_list = [f for f in range(start_index, end_index+1)]
return page_list[:(2*neighbors + 1)]
return paginator.page_range
return paginator.page_range

View File

@@ -0,0 +1,76 @@
from django.test import TestCase
from django.core.exceptions import FieldDoesNotExist
class FormTestCase(TestCase):
'''
Base class for FormTests.
Parameters:
- form : Form to test
'''
form = None
def assertField(self, field_name, field_class, must_have={}, must_not_have={}):
'''
Tests if a field exists under the given name and
if the field is of the right type.
Also checks if the field has the given must_have attributes
and does not have any of the must_not_have attributes. If you
dont care about the value of the attribute you can just set it to
something that fullfills value == False (i.e. '' or 0)
'''
try:
field = self.form.base_fields[field_name]
except FieldDoesNotExist:
self.fail(
'Expecting %s to have a field named \'%s\'' % (
self.form.__name__,
field_name
)
)
self.assertEqual(
type(field), field_class,
msg='Expecting type of %s to be %s' % (
str(field),
field_class.__name__
)
)
for key, value in must_have.items():
if value:
self.assertEqual(
getattr(field, key), value,
msg='Expeting the value of %s %s to be \'%s\'' % (
str(field),
key,
value
)
)
else:
self.assertTrue(
hasattr(field, key),
msg='Expeting %s to have \'%s\'' % (
str(field),
key
)
)
for key, value in must_not_have.items():
if value:
self.assertTrue(
getattr(field, key) != value,
msg='Expeting the value of %s %s to not be \'%s\'' % (
str(field),
key,
value
)
)
else:
self.assertFalse(
hasattr(field, value),
msg='Expeting %s to not have \'%s\'' % (
str(field),
key
)
)
return field

View File

@@ -0,0 +1,59 @@
import datetime
from django import forms
from django.utils import timezone
from lostplaces.tests.forms import FormTestCase
from lostplaces.forms import ExplorerCreationForm
from lostplaces.models.models import Voucher
class ExplorerCreationFormTestCase(FormTestCase):
"""
This test case only tests for the voucher since all other aspects don't realy matter
to this project and are already tested by django
"""
form = ExplorerCreationForm
@classmethod
def setUpTestData(cls):
Voucher.objects.create(
code='Imacode123',
expires_when=timezone.now() + datetime.timedelta(minutes=1)
)
def setUp(self):
self.post_data = {
'voucher': 'Imacode123',
'username': 'testpeter',
'email': 'testpeter@example.org',
'password1': 'Develop123',
'password2': 'Develop123'
}
def test_voucher_field(self):
self.assertField(
field_name='voucher',
field_class=forms.CharField
)
def test_validation_valid(self):
form = ExplorerCreationForm(self.post_data)
self.assertTrue(
form.is_valid(),
msg='Expecting the %s to validate' % (
self.form.__name__
)
)
def test_validation_invalid(self):
self.post_data = {
'voucher': 'Imanotacode123'
}
form = ExplorerCreationForm(self.post_data)
self.assertFalse(
form.is_valid(),
msg='Expecting the %s to not validate' % (
self.form.__name__
)
)

View File

@@ -2,11 +2,9 @@
# -*- coding: utf-8 -*-
from django.db import models
from django.contrib.auth.models import User
from django.core.exceptions import FieldDoesNotExist
from django.test import TestCase
# Creating a test user
class ModelTestCase(TestCase):
'''

View File

@@ -1,6 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
from django.utils import timezone
from django.test import TestCase
from django.db import models
from django.contrib.auth.models import User
@@ -10,7 +13,8 @@ from lostplaces.models import (
Mapable,
Submittable,
PlaceAsset,
Expireable
Expireable,
Voucher
)
from lostplaces.tests.models import ModelTestCase
@@ -112,4 +116,34 @@ class PlaceAssetTestCase(ModelTestCase):
)
class ExpireableTestCase(ModelTestCase):
model = Expireable
model = Expireable
def test_fields(self):
self.assertField(
field_name='created_when',
field_class=models.DateTimeField,
must_have={'auto_now_add': True}
)
self.assertField(
field_name='expires_when',
field_class=models.DateTimeField
)
def test_is_expired(self):
valid_voucher = Voucher.objects.create(
code='Test123',
expires_when=timezone.now() + datetime.timedelta(minutes=2)
)
self.assertFalse(
valid_voucher.is_expired,
msg='Expecing the expirable object to not be expired'
)
invalid_voucher = Voucher.objects.create(
code='Test1234',
expires_when=timezone.now() - datetime.timedelta(minutes=2)
)
self.assertTrue(
invalid_voucher.is_expired,
msg='Expecing the expirable object to be expired'
)

View File

@@ -1,5 +1,6 @@
from django.views import View
from django.shortcuts import get_object_or_404, redirect
from django.utils.translation import ugettext_lazy as _
from lostplaces.views.base_views import PlaceAssetCreateView, PlaceAssetDeleteView
from lostplaces.models import PlaceImage, Place
@@ -22,7 +23,7 @@ class PlaceImageCreateView(MultiplePlaceImageUploadMixin, PlaceAssetCreateView):
model = PlaceImage
form_class = PlaceImageForm
template_name = 'place_image/place_image_create.html'
success_message = 'Place Images submitted'
success_message = _('Image(s) submitted successfully')
commit = False
def post(self, request, place_id, *args, **kwargs):
@@ -37,7 +38,5 @@ class PlaceImageCreateView(MultiplePlaceImageUploadMixin, PlaceAssetCreateView):
class PlaceImageDeleteView(PlaceAssetDeleteView):
model = PlaceImage
success_message = 'Images deleted successfully'
permission_denied_message = 'You\'r not allowed to delete this image'
success_message = _('Image deleted successfully')
permission_denied_message = _('You are not allowed to delete this image')

View File

@@ -10,6 +10,7 @@ from django.views.generic import ListView
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
@@ -58,8 +59,8 @@ class PlaceUpdateView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, SuccessMessag
template_name = 'place/place_update.html'
model = Place
form_class = PlaceForm
success_message = 'Successfully updated place.'
place_submitter_error_message = 'You do no have permissions to alter this place'
success_message = _('Successfully updated place')
place_submitter_error_message = _('You are not allowed to edit this place')
def get_success_url(self):
return reverse_lazy('place_detail', kwargs={'pk':self.get_object().pk})
@@ -93,7 +94,7 @@ class PlaceCreateView(MultiplePlaceImageUploadMixin, IsAuthenticatedMixin, View)
messages.success(
self.request,
'Successfully created place.'
_('Successfully created place')
)
return redirect(reverse_lazy('place_detail', kwargs={'pk': place.pk}))
@@ -101,21 +102,20 @@ class PlaceCreateView(MultiplePlaceImageUploadMixin, IsAuthenticatedMixin, View)
# Usually the browser should have checked the form before sending.
messages.error(
self.request,
'Please fill in all required fields.'
_('Please fill in all required fields.')
)
return render(request, 'place/place_create.html', context={'form': place_form})
class PlaceDeleteView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, DeleteView):
template_name = 'place/place_delete.html'
model = Place
success_message = 'Successfully deleted place.'
success_message = _('Successfully deleted place')
success_url = reverse_lazy('place_list')
success_message = 'Place deleted'
place_submitter_error_message = 'You do no have permission to delete this place'
place_submitter_error_message = _('You are not allowed to delete this place')
def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs)
def get_place(self):
return self.get_object()
return self.get_object()

View File

@@ -9,6 +9,7 @@ from django.contrib import messages
from django.urls import reverse_lazy
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponseForbidden
from django.utils.translation import ugettext_lazy as _
from lostplaces.forms import ExplorerCreationForm, TagSubmitForm
from lostplaces.models import Place, PhotoAlbum
@@ -25,7 +26,7 @@ class SignUpView(SuccessMessageMixin, CreateView):
form_class = ExplorerCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
success_message = 'User created.'
success_message = _('User created')
class HomeView(IsAuthenticatedMixin, View):
def get(self, request, *args, **kwargs):
@@ -50,13 +51,13 @@ class PhotoAlbumCreateView(PlaceAssetCreateView):
model = PhotoAlbum
fields = ['url', 'label']
template_name = 'photo_album/photo_album_create.html'
success_message = 'Photo Album submitted'
success_message = _('Photo album link submitted')
class PhotoAlbumDeleteView(PlaceAssetDeleteView):
model = PhotoAlbum
pk_url_kwarg = 'pk'
success_message = 'Photo Album deleted'
permission_denied_messsage = 'You do not have permissions to alter this photo album'
success_message = _('Photo album link deleted')
permission_denied_messsage = _('You are not allowed to edit this photo album link')
class PlaceTagSubmitView(IsAuthenticatedMixin, View):
def post(self, request, tagged_id, *args, **kwargs):
@@ -81,4 +82,7 @@ class PlaceTagDeleteView(IsAuthenticatedMixin, View):
return redirect(reverse_lazy('place_detail', kwargs={'pk': tagged_id}))
def FlatView(request, slug):
return render(request, 'flat/' + slug + '.html')
if request.LANGUAGE_CODE == 'de':
return render(request, 'flat/' + slug + '-de' + '.html')
else:
return render(request, 'flat/' + slug + '.html')

View File

@@ -8,7 +8,7 @@ with open('Readme.md') as f:
setup(
name='django-lostplaces',
version='0.1.a5',
version='0.1.2 HotFix',
description='A django app to manage lost places',
author='Reverend',
author_email='reverend@reverend2048.de',