Compare commits

...

17 Commits

Author SHA1 Message Date
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
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
16 changed files with 312 additions and 33 deletions

View File

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

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-11 02:14+0200\n" "POT-Creation-Date: 2020-10-11 07:48+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Commander1024 <commander@commander1024.de>\n" "Last-Translator: Commander1024 <commander@commander1024.de>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -30,23 +30,23 @@ msgstr "Ungültiger Voucher"
msgid "Expired voucher" msgid "Expired voucher"
msgstr "Abgelaufener Voucher" msgstr "Abgelaufener Voucher"
#: models/abstract_models.py:28 #: models/abstract_models.py:29
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
#: models/abstract_models.py:35 #: models/abstract_models.py:36
msgid "Latitude" msgid "Latitude"
msgstr "Breitengrad" msgstr "Breitengrad"
#: models/abstract_models.py:36 #: models/abstract_models.py:37
msgid "Latitude in decimal format: e. g. 41.40338" msgid "Latitude in decimal format: e. g. 41.40338"
msgstr "Breitengrad in dezimaler Form: z. B. 51.95021" msgstr "Breitengrad in dezimaler Form: z. B. 51.95021"
#: models/abstract_models.py:43 #: models/abstract_models.py:44
msgid "Longitude" msgid "Longitude"
msgstr "Längengrad" msgstr "Längengrad"
#: models/abstract_models.py:44 #: models/abstract_models.py:45
msgid "Longitude in decimal format: e. g. 2.17403" msgid "Longitude in decimal format: e. g. 2.17403"
msgstr "Breitengrad in dezimaler Form: z. B. 7.4840155" msgstr "Breitengrad in dezimaler Form: z. B. 7.4840155"
@ -322,4 +322,56 @@ msgstr "Registrieren"
#: views/base_views.py:25 #: views/base_views.py:25
msgid "Please login to proceed" 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(s) deleted successfully"
msgstr "Bild(er) 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
#, fuzzy
#| msgid "Successfully deleted place"
msgid "Successfully updated place"
msgstr "Place erfolgreich gelöscht"
#: views/place_views.py:63
msgid "You do no have permissions to alter this place"
msgstr "Du hast nicht die Berechtigung, diesen Place zu bearbeiten"
#: views/place_views.py:97
#, fuzzy
#| msgid "Successfully deleted place"
msgid "Successfully created place"
msgstr "Place erfolgreich gelöscht"
#: views/place_views.py:112
msgid "Successfully deleted place"
msgstr "Place erfolgreich gelöscht"
#: views/place_views.py:114
msgid "You do no have permission to delete this place"
msgstr "Du hast nicht die Berechtigung, diesen Place zu löschen"
#: views/views.py:29
msgid "User created"
msgstr "User erstellt"
#: views/views.py:54
msgid "Photo Album submitted"
msgstr "Fotoalbum hinzugefügt"
#: views/views.py:59
msgid "Photo Album deleted"
msgstr "Fotoalbum gelöscht"
#: views/views.py:60
msgid "You do not have permissions to alter this photo album"
msgstr "Du hast nicht die Berechtigung, diesen Place zu 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.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
@ -63,7 +64,14 @@ class Submittable(models.Model):
class Expireable(models.Model): class Expireable(models.Model):
""" """
Base class for things that can expire, i.e. VouchersAv Base class for things that can expire, i.e. Vouchers
""" """
class Meta:
abstract = True
created_when = models.DateTimeField(auto_now_add=True) created_when = models.DateTimeField(auto_now_add=True)
expires_when = models.DateTimeField() expires_when = models.DateTimeField()
@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) code = models.CharField(unique=True, max_length=30)
@property
def valid(self):
return not self.is_expired
def __str__(self): def __str__(self):
return "Voucher " + str(self.code) return "Voucher " + str(self.code)

View File

@ -63,7 +63,7 @@
<a target="_blank" href="{{photo_album.url}}" class="LP-Link"> <a target="_blank" href="{{photo_album.url}}" class="LP-Link">
<span class="LP-Text">{{photo_album.label}}</span> <span class="LP-Text">{{photo_album.label}}</span>
</a> </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"> <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"> <div class="RV-Iconized__Container RV-Iconized__Container--small">
{% icon 'trash' className="RV-Iconized__Icon" %} {% icon 'trash' className="RV-Iconized__Icon" %}

View File

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django import template from django import template
from django.http import request
register = template.Library() register = template.Library()
@ -22,4 +23,4 @@ def proper_paginate(paginator, current_page, neighbors=2):
end_index = paginator.num_pages end_index = paginator.num_pages
page_list = [f for f in range(start_index, end_index+1)] page_list = [f for f in range(start_index, end_index+1)]
return page_list[:(2*neighbors + 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 -*- # -*- coding: utf-8 -*-
from django.db import models from django.db import models
from django.contrib.auth.models import User
from django.core.exceptions import FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist
from django.test import TestCase from django.test import TestCase
# Creating a test user
class ModelTestCase(TestCase): class ModelTestCase(TestCase):
''' '''

View File

@ -1,6 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime
from django.utils import timezone
from django.test import TestCase from django.test import TestCase
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
@ -10,7 +13,8 @@ from lostplaces.models import (
Mapable, Mapable,
Submittable, Submittable,
PlaceAsset, PlaceAsset,
Expireable Expireable,
Voucher
) )
from lostplaces.tests.models import ModelTestCase from lostplaces.tests.models import ModelTestCase
@ -112,4 +116,34 @@ class PlaceAssetTestCase(ModelTestCase):
) )
class ExpireableTestCase(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.views import View
from django.shortcuts import get_object_or_404, redirect 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.views.base_views import PlaceAssetCreateView, PlaceAssetDeleteView
from lostplaces.models import PlaceImage, Place from lostplaces.models import PlaceImage, Place
@ -22,7 +23,7 @@ class PlaceImageCreateView(MultiplePlaceImageUploadMixin, PlaceAssetCreateView):
model = PlaceImage model = PlaceImage
form_class = PlaceImageForm form_class = PlaceImageForm
template_name = 'place_image/place_image_create.html' template_name = 'place_image/place_image_create.html'
success_message = 'Place Images submitted' success_message = _('Image(s) submitted successfully')
commit = False commit = False
def post(self, request, place_id, *args, **kwargs): def post(self, request, place_id, *args, **kwargs):
@ -37,7 +38,5 @@ class PlaceImageCreateView(MultiplePlaceImageUploadMixin, PlaceAssetCreateView):
class PlaceImageDeleteView(PlaceAssetDeleteView): class PlaceImageDeleteView(PlaceAssetDeleteView):
model = PlaceImage model = PlaceImage
success_message = 'Images deleted successfully' success_message = _('Image(s) deleted successfully')
permission_denied_message = 'You\'r not allowed to delete this image' 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 import messages
from django.contrib.messages.views import SuccessMessageMixin 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.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy from django.urls import reverse_lazy
@ -58,8 +59,8 @@ class PlaceUpdateView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, SuccessMessag
template_name = 'place/place_update.html' template_name = 'place/place_update.html'
model = Place model = Place
form_class = PlaceForm form_class = PlaceForm
success_message = 'Successfully updated place.' success_message = _('Successfully updated place')
place_submitter_error_message = 'You do no have permissions to alter this place' place_submitter_error_message = _('You do no have permissions to alter this place')
def get_success_url(self): def get_success_url(self):
return reverse_lazy('place_detail', kwargs={'pk':self.get_object().pk}) return reverse_lazy('place_detail', kwargs={'pk':self.get_object().pk})
@ -93,7 +94,7 @@ class PlaceCreateView(MultiplePlaceImageUploadMixin, IsAuthenticatedMixin, View)
messages.success( messages.success(
self.request, self.request,
'Successfully created place.' _('Successfully created place')
) )
return redirect(reverse_lazy('place_detail', kwargs={'pk': place.pk})) return redirect(reverse_lazy('place_detail', kwargs={'pk': place.pk}))
@ -108,14 +109,13 @@ class PlaceCreateView(MultiplePlaceImageUploadMixin, IsAuthenticatedMixin, View)
class PlaceDeleteView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, DeleteView): class PlaceDeleteView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, DeleteView):
template_name = 'place/place_delete.html' template_name = 'place/place_delete.html'
model = Place model = Place
success_message = 'Successfully deleted place.' success_message = _('Successfully deleted place')
success_url = reverse_lazy('place_list') 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 do no have permission to delete this place'
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message) messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs) return super().delete(request, *args, **kwargs)
def get_place(self): 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.urls import reverse_lazy
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponseForbidden from django.http import HttpResponseForbidden
from django.utils.translation import ugettext_lazy as _
from lostplaces.forms import ExplorerCreationForm, TagSubmitForm from lostplaces.forms import ExplorerCreationForm, TagSubmitForm
from lostplaces.models import Place, PhotoAlbum from lostplaces.models import Place, PhotoAlbum
@ -25,7 +26,7 @@ class SignUpView(SuccessMessageMixin, CreateView):
form_class = ExplorerCreationForm form_class = ExplorerCreationForm
success_url = reverse_lazy('login') success_url = reverse_lazy('login')
template_name = 'signup.html' template_name = 'signup.html'
success_message = 'User created.' success_message = _('User created')
class HomeView(IsAuthenticatedMixin, View): class HomeView(IsAuthenticatedMixin, View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
@ -50,13 +51,13 @@ class PhotoAlbumCreateView(PlaceAssetCreateView):
model = PhotoAlbum model = PhotoAlbum
fields = ['url', 'label'] fields = ['url', 'label']
template_name = 'photo_album/photo_album_create.html' template_name = 'photo_album/photo_album_create.html'
success_message = 'Photo Album submitted' success_message = _('Photo Album submitted')
class PhotoAlbumDeleteView(PlaceAssetDeleteView): class PhotoAlbumDeleteView(PlaceAssetDeleteView):
model = PhotoAlbum model = PhotoAlbum
pk_url_kwarg = 'pk' pk_url_kwarg = 'pk'
success_message = 'Photo Album deleted' success_message = _('Photo Album deleted')
permission_denied_messsage = 'You do not have permissions to alter this photo album' permission_denied_messsage = _('You do not have permissions to alter this photo album')
class PlaceTagSubmitView(IsAuthenticatedMixin, View): class PlaceTagSubmitView(IsAuthenticatedMixin, View):
def post(self, request, tagged_id, *args, **kwargs): def post(self, request, tagged_id, *args, **kwargs):

View File

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