Compare commits
63 Commits
27-Favorit
...
feature/33
Author | SHA1 | Date | |
---|---|---|---|
a22c988e94 | |||
7f2283325c | |||
6b7c71ef30 | |||
067bf36118 | |||
9eef044af9 | |||
a4780a22f2 | |||
0d1d829abe | |||
59cfa82ce9 | |||
d47c85795c | |||
8e80614eee | |||
6a1e2d975b | |||
c5f6355f19 | |||
dac63e99ba | |||
9f369456d5 | |||
011a58f6b3 | |||
67ce6cb50b | |||
5df7cc5ec6 | |||
e242dc4add | |||
86cc7f23fe | |||
f73fa616d0 | |||
629a609ff5 | |||
04fe93c7bb | |||
3eaa186b66 | |||
b42be489dc | |||
cc59254ba4 | |||
67a6517716 | |||
0f5474c2d3 | |||
17e71b71d4 | |||
b1aa4473e9 | |||
871acd1dce | |||
14ca45d111 | |||
c71fe4cf2d | |||
7359bf5fab | |||
4f0182fc3e | |||
30f259fb4d | |||
53f89caef5 | |||
3855fb28d7 | |||
3a20a60f05 | |||
648264c9fc | |||
dc79b9d05c | |||
a7c8848fd6 | |||
b845cc054a | |||
07ea2f164c | |||
b0396f5223 | |||
88bffbef8e | |||
2022a924c4 | |||
d5827b2006 | |||
a9013d9673 | |||
0c38ca9a15 | |||
734d09df90 | |||
e601b9bf6b | |||
6f6bd6376d | |||
dc2a703c39 | |||
063777ece4 | |||
4675e5814f | |||
35e0f912fe | |||
07fe1bc3ca | |||
d04e986419 | |||
cbbda88850 | |||
981c440ce3 | |||
c7368f5c44 | |||
20dd880a11 | |||
946c3091c0 |
@@ -6,6 +6,9 @@ The software is currently in early development status, neither scope, datamodel(
|
||||
|
||||
We value privacy as a whole, all resources the frontend requires will be shipped with lostplace's distribution. We also try to minimize the use of JavaScript as far as we can and try to offer JS-less alternatives where we can.
|
||||
|
||||
## Contact
|
||||
If you run into any issues, have any questions or If you are interested in this project in general, feel free to get in touch with us via [reverend@reverend2048.de](mailto:reverend@reverend2048.de), we do speak English and German.
|
||||
|
||||
## Features
|
||||
- Manage lost places with lots of useful information.
|
||||
- OSM-Maps
|
||||
@@ -145,8 +148,4 @@ Before making the django instance public, you should tweak the config `settings.
|
||||
4. Set a new (random) SECRET_KEY in settings.py, e. g.: `base64 /dev/urandom | head -c50`
|
||||
|
||||
|
||||
Run `django_lostplaces/manage.py collectstatic` you should be ready to go.
|
||||
|
||||
|
||||
### Contact
|
||||
If you run into any issues, have any questions or If you are interested in this project in general, feel free to get in touch with us via [reverend@reverend2048.de](mailto:reverend@reverend2048.de), we do speak English and German.
|
||||
Run `django_lostplaces/manage.py collectstatic` you should be ready to go.
|
@@ -9,8 +9,6 @@ from django.contrib.auth.admin import UserAdmin
|
||||
from django.utils import timezone
|
||||
from lostplaces.models import *
|
||||
|
||||
from lostplaces.forms import ExplorerCreationForm, ExplorerChangeForm
|
||||
|
||||
# Register your models here.
|
||||
|
||||
class VoucherAdmin(admin.ModelAdmin):
|
||||
|
@@ -1,3 +1,5 @@
|
||||
from django.shortcuts import redirect
|
||||
|
||||
def get_all_subclasses(cls):
|
||||
'''
|
||||
Gets all subclasses recursively, does not contain
|
||||
@@ -8,4 +10,16 @@ def get_all_subclasses(cls):
|
||||
if not subclass._meta.abstract:
|
||||
subclass_list.append(subclass)
|
||||
subclass_list += get_all_subclasses(subclass)
|
||||
return subclass_list
|
||||
return subclass_list
|
||||
|
||||
def redirect_referer_or(request, url='/'):
|
||||
'''
|
||||
Returns a django redirect to the requests referer,
|
||||
if there is no referer the redirect will poin to the given url
|
||||
Default url is /
|
||||
'''
|
||||
referer = request.META.get('HTTP_REFERER')
|
||||
if referer is not None:
|
||||
return redirect(referer)
|
||||
else:
|
||||
return redirect(url)
|
@@ -8,12 +8,12 @@ from django.db import models
|
||||
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from lostplaces.models import Place, PlaceImage, Voucher
|
||||
from lostplaces.models import Place, PlaceImage, Voucher, Explorer
|
||||
|
||||
class ExplorerCreationForm(UserCreationForm):
|
||||
class SignupVoucherForm(UserCreationForm):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('username', 'email')
|
||||
fields = ('username', 'email', 'first_name', 'last_name')
|
||||
voucher = forms.CharField(
|
||||
max_length=30,
|
||||
help_text=_('The Voucher you got from an administrator')
|
||||
@@ -35,16 +35,47 @@ class ExplorerCreationForm(UserCreationForm):
|
||||
fetched_voucher.delete()
|
||||
return True
|
||||
|
||||
class ExplorerChangeForm(UserChangeForm):
|
||||
class ExplorerUserChangeForm(UserChangeForm):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('username', 'email')
|
||||
fields = [ 'username', 'first_name', 'last_name', 'email' ]
|
||||
''' Hide password hint.'''
|
||||
password = None
|
||||
|
||||
''' Display username, but display it non-editable and not required. '''
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['username'].required = False
|
||||
self.fields['username'].help_text = None
|
||||
self.fields['username'].widget.attrs['disabled'] = 'disabled'
|
||||
|
||||
def clean_username(self):
|
||||
# As shown in the above answer.
|
||||
instance = getattr(self, 'instance', None)
|
||||
if instance:
|
||||
return instance.username
|
||||
else:
|
||||
return self.cleaned_data.get('username', None)
|
||||
|
||||
class ExplorerChangeForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Explorer
|
||||
fields = '__all__'
|
||||
exclude = ['user', 'favorite_places']
|
||||
|
||||
class PlaceForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Place
|
||||
fields = '__all__'
|
||||
exclude = ['submitted_by']
|
||||
exclude = ['submitted_by', 'latitude', 'longitute']
|
||||
|
||||
latitude = forms.IntegerField(
|
||||
widget=forms.NumberInput(attrs={'min':-90,'max': 90,'type': 'number'})
|
||||
)
|
||||
|
||||
longitude = forms.IntegerField(
|
||||
widget=forms.NumberInput(attrs={'min':-180,'max': 180,'type': 'number'})
|
||||
)
|
||||
|
||||
class PlaceImageForm(forms.ModelForm):
|
||||
class Meta:
|
||||
|
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-10-11 21:53+0200\n"
|
||||
"POT-Creation-Date: 2020-12-25 16:04+0100\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"
|
||||
@@ -30,7 +30,7 @@ msgstr "Ungültiger Voucher"
|
||||
msgid "Expired voucher"
|
||||
msgstr "Abgelaufener Voucher"
|
||||
|
||||
#: models/abstract_models.py:29
|
||||
#: models/abstract_models.py:29 templates/explorer/profile.html:31
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
@@ -74,6 +74,22 @@ msgstr "Adresse (URL)"
|
||||
msgid "link text"
|
||||
msgstr "Linktext"
|
||||
|
||||
#: models/models.py:47
|
||||
msgid "Biography"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
#: models/models.py:48
|
||||
msgid "Describe yourself, your preferences, etc. in a few sentences."
|
||||
msgstr "Beschreibe Dich selbst, Deine Vorlieben, usw. in ein paar Sätzen."
|
||||
|
||||
#: models/models.py:56
|
||||
msgid "Profile image"
|
||||
msgstr "Profilbild"
|
||||
|
||||
#: models/models.py:57
|
||||
msgid "Optional profile image for display in Explorer profile"
|
||||
msgstr "Optionales Profilbild zur Anzeige im Explorerprofil"
|
||||
|
||||
#: models/place.py:21
|
||||
msgid "Location"
|
||||
msgstr "Ort"
|
||||
@@ -110,38 +126,92 @@ msgstr "Du wirst in 5 Sekunden weitergeleitet"
|
||||
msgid "Go Back"
|
||||
msgstr "Zurück"
|
||||
|
||||
#: templates/explorer/profile.html:41
|
||||
msgid "E-mail"
|
||||
msgstr "E-Mail"
|
||||
|
||||
#: templates/explorer/profile.html:52
|
||||
msgid "Joined"
|
||||
msgstr "Beigetreten"
|
||||
|
||||
#: templates/explorer/profile.html:60
|
||||
#, fuzzy
|
||||
#| msgid "All Places"
|
||||
msgid "Places"
|
||||
msgstr "Alle Places"
|
||||
|
||||
#: templates/explorer/profile.html:68
|
||||
msgid "Place assets"
|
||||
msgstr ""
|
||||
|
||||
#: templates/explorer/profile.html:76
|
||||
#, fuzzy
|
||||
#| msgid "Edit Explorer profile"
|
||||
msgid "Edit Profile"
|
||||
msgstr "Explorerprofil bearbeiten"
|
||||
|
||||
#: templates/explorer/profile.html:87
|
||||
msgid "Favorite places"
|
||||
msgstr "Favoriten"
|
||||
|
||||
#: templates/explorer/profile.html:103
|
||||
msgid "Places submitted by"
|
||||
msgstr "Places hinzugefügt von"
|
||||
|
||||
#: templates/explorer/profile.html:118
|
||||
msgid "Images submitted by"
|
||||
msgstr "Bilder hinzugefügt von"
|
||||
|
||||
#: templates/explorer/profile.html:140
|
||||
msgid "Photo albums submitted by"
|
||||
msgstr "Fotoalben hinzugefügt von"
|
||||
|
||||
#: templates/explorer/profile_update.html:6
|
||||
#: templates/explorer/profile_update.html:12
|
||||
msgid "Edit Explorer profile"
|
||||
msgstr "Explorerprofil bearbeiten"
|
||||
|
||||
#: templates/explorer/profile_update.html:48
|
||||
#: templates/place/place_update.html:42
|
||||
msgid "Update"
|
||||
msgstr "Aktualisieren"
|
||||
|
||||
#: templates/global.html:32
|
||||
msgid "Logout"
|
||||
msgstr "Ausloggen"
|
||||
|
||||
#: templates/global.html:34
|
||||
#: templates/global.html:33
|
||||
msgid "Profile"
|
||||
msgstr "Profil"
|
||||
|
||||
#: templates/global.html:35
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
|
||||
#: templates/global.html:39 templates/registration/login.html:4
|
||||
#: templates/global.html:40 templates/registration/login.html:4
|
||||
#: templates/registration/login.html:10 templates/registration/login.html:23
|
||||
msgid "Login"
|
||||
msgstr "Anmelden"
|
||||
|
||||
#: templates/global.html:40 templates/registration/login.html:29
|
||||
#: templates/signup.html:6 templates/signup.html:12 templates/signup.html:41
|
||||
#: templates/global.html:41 templates/registration/login.html:29
|
||||
#: templates/signup.html:6 templates/signup.html:12 templates/signup.html:49
|
||||
msgid "Sign up"
|
||||
msgstr "Registrieren"
|
||||
|
||||
#: templates/global.html:50 templates/home.html:10
|
||||
#: templates/global.html:51 templates/home.html:10
|
||||
msgid "Home"
|
||||
msgstr "Startseite"
|
||||
|
||||
#: templates/global.html:51
|
||||
#: templates/global.html:52
|
||||
msgid "UrBex Codex"
|
||||
msgstr "UrBex Codex"
|
||||
|
||||
#: templates/global.html:56 templates/place/place_create.html:5
|
||||
#: templates/global.html:57 templates/place/place_create.html:5
|
||||
#: templates/place/place_create.html:10
|
||||
msgid "Create place"
|
||||
msgstr "Place erstellen"
|
||||
|
||||
#: templates/global.html:57
|
||||
#: templates/global.html:58
|
||||
msgid "All places"
|
||||
msgstr "Alle Places"
|
||||
|
||||
@@ -194,6 +264,14 @@ msgstr "Abschicken"
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: templates/partials/icons/place_favorite.html:6
|
||||
msgid "Remove from favorites"
|
||||
msgstr "Aus den Favoriten entfernen"
|
||||
|
||||
#: templates/partials/icons/place_favorite.html:10
|
||||
msgid "Save as favorite"
|
||||
msgstr "In den Favoriten speichern"
|
||||
|
||||
#: templates/partials/nav/footer.html:64
|
||||
msgid "Made by"
|
||||
msgstr "Erstellt von"
|
||||
@@ -318,10 +396,6 @@ msgstr "Alle Places"
|
||||
msgid "Our lost places"
|
||||
msgstr "Unsere Lost Places"
|
||||
|
||||
#: templates/place/place_update.html:42
|
||||
msgid "Update"
|
||||
msgstr "Aktualisieren"
|
||||
|
||||
#: templates/place_image/place_image_create.html:7
|
||||
msgid "Submit images to a place"
|
||||
msgstr "Bilder zu einem Place hinzufügen"
|
||||
@@ -334,6 +408,16 @@ msgstr "Noch kein Konto?"
|
||||
msgid "Please login to proceed"
|
||||
msgstr "Bitte log Dich ein um fortzufahren"
|
||||
|
||||
#: views/explorer_views.py:78
|
||||
#, fuzzy
|
||||
#| msgid "Successfully updated place"
|
||||
msgid "Successfully updated Explorer profile"
|
||||
msgstr "Place erfolgreich aktualisiert"
|
||||
|
||||
#: views/explorer_views.py:84 views/place_views.py:105
|
||||
msgid "Please fill in all required fields."
|
||||
msgstr "Bitte füll alle benötigten Felder aus."
|
||||
|
||||
#: views/place_image_views.py:26
|
||||
msgid "Image(s) submitted successfully"
|
||||
msgstr "Bild(er) erfolgreich hinzugefügt"
|
||||
@@ -358,10 +442,6 @@ msgstr "Du darfst diesen Place nicht bearbeiten"
|
||||
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"
|
||||
@@ -385,3 +465,8 @@ 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"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Filename(s)"
|
||||
#~ msgid "Filename"
|
||||
#~ msgstr "Dateiname(n)"
|
||||
|
@@ -65,7 +65,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('submitted_when', models.DateTimeField(auto_now_add=True, null=True)),
|
||||
('description', models.TextField(blank=True)),
|
||||
('filename', easy_thumbnails.fields.ThumbnailerImageField(upload_to=lostplaces.models.place.generate_image_upload_path)),
|
||||
('filename', easy_thumbnails.fields.ThumbnailerImageField(upload_to=lostplaces.models.place.generate_place_image_filename)),
|
||||
('place', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='placeimages', to='lostplaces.place')),
|
||||
('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='placeimages', to='lostplaces.explorer')),
|
||||
],
|
||||
|
@@ -1,25 +1,25 @@
|
||||
# Generated by Django 3.1.1 on 2020-10-04 19:52
|
||||
# Generated by Django 3.1.1 on 2020-10-04 19:52
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('lostplaces', '0002_reomve_vouchers'),
|
||||
]
|
||||
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,
|
||||
},
|
||||
),
|
||||
]
|
||||
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,
|
||||
},
|
||||
),
|
||||
]
|
118
django_lostplaces/lostplaces/migrations/0004_gory_fix.py
Normal file
118
django_lostplaces/lostplaces/migrations/0004_gory_fix.py
Normal file
@@ -0,0 +1,118 @@
|
||||
# Generated by Django 3.1.4 on 2020-12-25 16:02
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import easy_thumbnails.fields
|
||||
from lostplaces.models.models import generate_profile_image_filename
|
||||
from lostplaces.models.place import generate_place_image_filename
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('lostplaces', '0003_voucher'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='explorer',
|
||||
name='bio',
|
||||
field=models.TextField(blank=True, help_text='Describe yourself, your preferences, etc. in a few sentences.', null=True, verbose_name='Biography / Description'),
|
||||
),
|
||||
# migrations.AddField(
|
||||
# model_name='explorer',
|
||||
# name='favorite_places',
|
||||
# field=models.ManyToManyField(blank=True, related_name='explorer_favorites', to='lostplaces.Place', verbose_name='Explorers favorite places'),
|
||||
# ),
|
||||
migrations.AddField(
|
||||
model_name='explorer',
|
||||
name='profile_image',
|
||||
field=easy_thumbnails.fields.ThumbnailerImageField(blank=True, help_text='Optional profile image for display in Explorer profile', null=True, upload_to=generate_profile_image_filename, verbose_name='Profile image'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='photoalbum',
|
||||
name='label',
|
||||
field=models.CharField(max_length=100, verbose_name='link text'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='photoalbum',
|
||||
name='submitted_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='photoalbums', to='lostplaces.explorer', verbose_name='Submitter'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='photoalbum',
|
||||
name='submitted_when',
|
||||
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='photoalbum',
|
||||
name='url',
|
||||
field=models.URLField(verbose_name='URL'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='place',
|
||||
name='description',
|
||||
field=models.TextField(help_text="Description of the place: e.g. how to get there, where to be careful, the place's history...", verbose_name='Description'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='place',
|
||||
name='latitude',
|
||||
field=models.FloatField(help_text='Latitude in decimal format: e. g. 41.40338', validators=[django.core.validators.MinValueValidator(-90), django.core.validators.MaxValueValidator(90)], verbose_name='Latitude'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='place',
|
||||
name='location',
|
||||
field=models.CharField(max_length=50, verbose_name='Location'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='place',
|
||||
name='longitude',
|
||||
field=models.FloatField(help_text='Longitude in decimal format: e. g. 2.17403', validators=[django.core.validators.MinValueValidator(-180), django.core.validators.MaxValueValidator(180)], verbose_name='Longitude'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='place',
|
||||
name='name',
|
||||
field=models.CharField(max_length=50, verbose_name='Name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='place',
|
||||
name='submitted_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='places', to='lostplaces.explorer', verbose_name='Submitter'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='place',
|
||||
name='submitted_when',
|
||||
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='placeimage',
|
||||
name='description',
|
||||
field=models.TextField(blank=True, verbose_name='Description'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='placeimage',
|
||||
name='filename',
|
||||
field=easy_thumbnails.fields.ThumbnailerImageField(help_text='Optional: One or more images to upload', upload_to=generate_place_image_filename, verbose_name='Filename(s)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='placeimage',
|
||||
name='submitted_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='placeimages', to='lostplaces.explorer', verbose_name='Submitter'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='placeimage',
|
||||
name='submitted_when',
|
||||
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Submission date'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='voucher',
|
||||
name='created_when',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='Creation date'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='voucher',
|
||||
name='expires_when',
|
||||
field=models.DateTimeField(verbose_name='Expiration date'),
|
||||
),
|
||||
]
|
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.1.4 on 2020-12-25 18:14
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('lostplaces', '0004_auto_20201225_1702'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='explorer',
|
||||
name='visited_places',
|
||||
field=models.ManyToManyField(blank=True, related_name='explorer_visits', to='lostplaces.Place', verbose_name='Explorers visited places'),
|
||||
),
|
||||
]
|
@@ -6,20 +6,34 @@
|
||||
database.
|
||||
'''
|
||||
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models.signals import post_save
|
||||
from django.db.models.signals import post_save, pre_save
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from lostplaces.models.abstract_models import Expireable
|
||||
from lostplaces.models.place import Place
|
||||
|
||||
from easy_thumbnails.fields import ThumbnailerImageField
|
||||
from easy_thumbnails.files import get_thumbnailer
|
||||
|
||||
def generate_profile_image_filename(instance, filename):
|
||||
"""
|
||||
Callback for generating filename for uploaded explorer profile images.
|
||||
Returns filename as: explorer_pk-username.jpg
|
||||
"""
|
||||
|
||||
return 'explorers/' + str(instance.user.pk) + '-' + str(instance.user.username) + '.' + filename.split('.')[-1]
|
||||
|
||||
class Explorer(models.Model):
|
||||
"""
|
||||
Profile that is linked to the a User.
|
||||
Profile that is linked to the Django user.
|
||||
Every user has a profile.
|
||||
Provides additional attributes for user profile.
|
||||
"""
|
||||
|
||||
user = models.OneToOneField(
|
||||
@@ -27,17 +41,37 @@ class Explorer(models.Model):
|
||||
on_delete=models.CASCADE,
|
||||
related_name='explorer'
|
||||
)
|
||||
|
||||
bio = models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('Biography / Description'),
|
||||
help_text=_('Describe yourself, your preferences, etc. in a few sentences.')
|
||||
)
|
||||
profile_image = ThumbnailerImageField(
|
||||
blank=True,
|
||||
null=True,
|
||||
upload_to=generate_profile_image_filename,
|
||||
resize_source=dict(size=(400, 400),
|
||||
sharpen=True),
|
||||
verbose_name=_('Profile image'),
|
||||
help_text=_('Optional profile image for display in Explorer profile')
|
||||
)
|
||||
favorite_places = models.ManyToManyField(
|
||||
Place,
|
||||
related_name='favorite_places',
|
||||
related_name='explorer_favorites',
|
||||
verbose_name='Explorers favorite places',
|
||||
blank=True
|
||||
)
|
||||
visited_places = models.ManyToManyField(
|
||||
Place,
|
||||
related_name='explorer_visits',
|
||||
verbose_name='Explorers visited places',
|
||||
blank=True
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.user.username
|
||||
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def create_user_profile(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
@@ -47,13 +81,34 @@ def create_user_profile(sender, instance, created, **kwargs):
|
||||
def save_user_profile(sender, instance, **kwargs):
|
||||
instance.explorer.save()
|
||||
|
||||
@receiver(pre_save, sender=Explorer)
|
||||
def auto_delete_file_on_change(sender, instance, **kwargs):
|
||||
"""
|
||||
Deletes old file from filesystem
|
||||
when corresponding `Explorer` object is updated
|
||||
with new file.
|
||||
"""
|
||||
if not instance.pk:
|
||||
return False
|
||||
|
||||
try:
|
||||
old_file = Explorer.objects.get(pk=instance.pk).profile_image
|
||||
except Explorer.DoesNotExist:
|
||||
return False
|
||||
print("Deleting:", old_file)
|
||||
new_file = instance.profile_image
|
||||
if not old_file == new_file:
|
||||
old_file.delete(save=False)
|
||||
|
||||
class Voucher(Expireable):
|
||||
"""
|
||||
Vouchers are authorization to created_when = models.DateTimeField(auto_now_add=True)
|
||||
expires_when = models.DateTimeField()kens to allow the registration of new users.
|
||||
Vouchers are authorization tokens to allow the registration of new users.
|
||||
A voucher has a code, a creation and a deletion date, which are all
|
||||
positional. Creation date is being set automatically during voucher
|
||||
creation.
|
||||
|
||||
created_when = models.DateTimeField(auto_now_add=True)
|
||||
expires_when = models.DateTimeField()
|
||||
"""
|
||||
|
||||
code = models.CharField(unique=True, max_length=30)
|
||||
@@ -64,4 +119,3 @@ class Voucher(Expireable):
|
||||
|
||||
def __str__(self):
|
||||
return "Voucher " + str(self.code)
|
||||
|
||||
|
@@ -49,10 +49,10 @@ class Place(Submittable, Taggable, Mapable):
|
||||
return self.name
|
||||
|
||||
|
||||
def generate_image_upload_path(instance, filename):
|
||||
def generate_place_image_filename(instance, filename):
|
||||
"""
|
||||
Callback for generating path for uploaded images.
|
||||
Returns filename as: place_pk-placename{-rnd_string}.jpg
|
||||
Callback for generating filename for uploaded place images.
|
||||
Returns filename as: place_pk-placename{-number}.jpg
|
||||
"""
|
||||
|
||||
return 'places/' + str(instance.place.pk) + '-' + str(instance.place.name) + '.' + filename.split('.')[-1]
|
||||
@@ -72,7 +72,7 @@ class PlaceAsset(Submittable):
|
||||
null=True
|
||||
)
|
||||
|
||||
class PlaceImage (PlaceAsset):
|
||||
class PlaceImage(PlaceAsset):
|
||||
"""
|
||||
PlaceImage defines an image file object that points to a file in uploads/.
|
||||
Intermediate image sizes are generated as defined in THUMBNAIL_ALIASES.
|
||||
@@ -84,7 +84,7 @@ class PlaceImage (PlaceAsset):
|
||||
verbose_name=_('Description'),
|
||||
)
|
||||
filename = ThumbnailerImageField(
|
||||
upload_to=generate_image_upload_path,
|
||||
upload_to=generate_place_image_filename,
|
||||
resize_source=dict(size=(2560, 2560),
|
||||
sharpen=True),
|
||||
verbose_name=_('Filename(s)'),
|
||||
@@ -104,7 +104,6 @@ class PlaceImage (PlaceAsset):
|
||||
|
||||
return 'Image ' + str(self.pk)
|
||||
|
||||
|
||||
# These two auto-delete files from filesystem when they are unneeded:
|
||||
|
||||
@receiver(post_delete, sender=PlaceImage)
|
||||
@@ -118,7 +117,6 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
|
||||
thumbmanager = get_thumbnailer(instance.filename)
|
||||
thumbmanager.delete(save=False)
|
||||
|
||||
|
||||
@receiver(pre_save, sender=PlaceImage)
|
||||
def auto_delete_file_on_change(sender, instance, **kwargs):
|
||||
"""
|
||||
@@ -137,5 +135,4 @@ def auto_delete_file_on_change(sender, instance, **kwargs):
|
||||
# No need to delete thumbnails, as they will be overwritten on regeneration.
|
||||
new_file = instance.filename
|
||||
if not old_file == new_file:
|
||||
if os.path.isfile(old_file.path):
|
||||
os.remove(old_file.path)
|
||||
old_file.delete(save=False)
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -13,7 +13,7 @@
|
||||
viewBox="0 0 512.07 512.07"
|
||||
width="512"
|
||||
version="1.1"
|
||||
sodipodi:docname="favourite_filled.svg"
|
||||
sodipodi:docname="favorite_filled.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata11">
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
50
django_lostplaces/lostplaces/static/icons/pin.svg
Normal file
50
django_lostplaces/lostplaces/static/icons/pin.svg
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 368.16 368.16" style="enable-background:new 0 0 368.16 368.16;" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M184.08,0c-74.992,0-136,61.008-136,136c0,24.688,11.072,51.24,11.536,52.36c3.576,8.488,10.632,21.672,15.72,29.4
|
||||
l93.248,141.288c3.816,5.792,9.464,9.112,15.496,9.112s11.68-3.32,15.496-9.104l93.256-141.296
|
||||
c5.096-7.728,12.144-20.912,15.72-29.4c0.464-1.112,11.528-27.664,11.528-52.36C320.08,61.008,259.072,0,184.08,0z
|
||||
M293.8,182.152c-3.192,7.608-9.76,19.872-14.328,26.8l-93.256,141.296c-1.84,2.792-2.424,2.792-4.264,0L88.696,208.952
|
||||
c-4.568-6.928-11.136-19.2-14.328-26.808C74.232,181.816,64.08,157.376,64.08,136c0-66.168,53.832-120,120-120
|
||||
c66.168,0,120,53.832,120,120C304.08,157.408,293.904,181.912,293.8,182.152z"/>
|
||||
<path d="M184.08,64.008c-39.704,0-72,32.304-72,72c0,39.696,32.296,72,72,72c39.704,0,72-32.304,72-72
|
||||
C256.08,96.312,223.784,64.008,184.08,64.008z M184.08,192.008c-30.872,0-56-25.12-56-56s25.128-56,56-56s56,25.12,56,56
|
||||
S214.952,192.008,184.08,192.008z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
<g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
105
django_lostplaces/lostplaces/static/icons/pin_filled.svg
Normal file
105
django_lostplaces/lostplaces/static/icons/pin_filled.svg
Normal file
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 368.16 368.16"
|
||||
style="enable-background:new 0 0 368.16 368.16;"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="pin_filled.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"><metadata
|
||||
id="metadata47"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs45" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="712"
|
||||
id="namedview43"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.4803346"
|
||||
inkscape:cx="184.08"
|
||||
inkscape:cy="181.37791"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="28"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Capa_1" />
|
||||
<g
|
||||
id="g10">
|
||||
<g
|
||||
id="g8">
|
||||
<g
|
||||
id="g6">
|
||||
<path
|
||||
d="M184.08,0c-74.992,0-136,61.008-136,136c0,24.688,11.072,51.24,11.536,52.36c3.576,8.488,10.632,21.672,15.72,29.4 l93.248,141.288c3.816,5.792,9.464,9.112,15.496,9.112s11.68-3.32,15.496-9.104l93.256-141.296 c5.096-7.728,12.144-20.912,15.72-29.4c0.464-1.112,11.528-27.664,11.528-52.36C320.08,61.008,259.072,0,184.08,0z M293.8,182.152c-3.192,7.608-9.76,19.872-14.328,26.8l-93.256,141.296c-1.84,2.792-2.424,2.792-4.264,0L88.696,208.952 c-4.568-6.928-11.136-19.2-14.328-26.808C74.232,181.816,64.08,157.376,64.08,136c0-66.168,53.832-120,120-120 c66.168,0,120,53.832,120,120C304.08,157.408,293.904,181.912,293.8,182.152z"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M184.08,64.008c-39.704,0-72,32.304-72,72c0,39.696,32.296,72,72,72c39.704,0,72-32.304,72-72 C256.08,96.312,223.784,64.008,184.08,64.008z M184.08,192.008c-30.872,0-56-25.12-56-56s25.128-56,56-56s56,25.12,56,56 S214.952,192.008,184.08,192.008z"
|
||||
id="path4" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g12">
|
||||
</g>
|
||||
<g
|
||||
id="g14">
|
||||
</g>
|
||||
<g
|
||||
id="g16">
|
||||
</g>
|
||||
<g
|
||||
id="g18">
|
||||
</g>
|
||||
<g
|
||||
id="g20">
|
||||
</g>
|
||||
<g
|
||||
id="g22">
|
||||
</g>
|
||||
<g
|
||||
id="g24">
|
||||
</g>
|
||||
<g
|
||||
id="g26">
|
||||
</g>
|
||||
<g
|
||||
id="g28">
|
||||
</g>
|
||||
<g
|
||||
id="g30">
|
||||
</g>
|
||||
<g
|
||||
id="g32">
|
||||
</g>
|
||||
<g
|
||||
id="g34">
|
||||
</g>
|
||||
<g
|
||||
id="g36">
|
||||
</g>
|
||||
<g
|
||||
id="g38">
|
||||
</g>
|
||||
<g
|
||||
id="g40">
|
||||
</g>
|
||||
<path
|
||||
style="fill:#d40000;stroke-width:0.675523"
|
||||
d="M 183.2356,15.407728 C 148.115,15.680007 113.56046,32.165752 91.281357,59.335191 67.968201,87.080284 57.903075,125.97636 67.012946,161.30636 c 5.002813,21.56622 16.217838,40.96402 28.671518,59.02158 29.047926,44.21623 57.936976,88.55418 87.673836,132.30559 2.75528,0.71398 3.44582,-3.87416 5.23173,-5.36255 32.63958,-48.91094 65.16056,-97.91511 96.89098,-147.42174 14.94799,-26.09698 23.38967,-57.3347 16.79888,-87.25041 C 297.41258,88.732147 285.50707,66.159988 267.48079,49.622901 254.86863,36.299556 238.35251,27.47624 221.24564,21.334387 209.00763,17.320382 196.11719,15.285641 183.2356,15.407728 Z m 2.03448,49.555941 c 27.46439,-0.566602 54.10132,17.912787 64.54543,43.490751 4.10895,9.11958 5.7106,19.04018 5.10583,29.01713 0.83931,19.32103 -8.79389,38.15287 -22.74612,51.10133 -14.02478,12.97799 -33.27348,19.77398 -52.19585,18.33769 -29.18994,-0.56334 -56.21632,-22.71956 -64.31454,-50.57715 -3.46488,-10.42859 -2.56691,-21.58508 -1.94784,-32.37905 3.96475,-21.34187 17.606,-41.232363 37.2523,-51.078299 10.71386,-5.480174 22.38724,-8.587404 34.30079,-7.912402 z"
|
||||
id="path91" /></svg>
|
After Width: | Height: | Size: 3.8 KiB |
@@ -923,7 +923,8 @@ body {
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: unset; }
|
||||
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Headline, .LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Paragraph {
|
||||
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Headline,
|
||||
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-Paragraph {
|
||||
font-size: unset; }
|
||||
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Meta .LP-PlaceTeaser__Info .LP-Headline {
|
||||
font-size: 28px; }
|
||||
@@ -941,7 +942,12 @@ body {
|
||||
overflow: hidden;
|
||||
order: unset; }
|
||||
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Description .LP-Paragraph {
|
||||
font-size: unset; }
|
||||
font-size: unset;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; }
|
||||
.LP-PlaceTeaser--extended .LP-PlaceTeaser__Image {
|
||||
height: 165px;
|
||||
width: 280px;
|
||||
@@ -1695,6 +1701,11 @@ body {
|
||||
|
||||
.LP-Map {
|
||||
margin-bottom: 25px; }
|
||||
.LP-Map--wide {
|
||||
height: 300px; }
|
||||
.LP-Map--full {
|
||||
height: 100%;
|
||||
width: 100%; }
|
||||
.LP-Map .ol-attribution {
|
||||
font-family: "Montserrat", Helvetica, sans-serif;
|
||||
color: #565656; }
|
||||
|
@@ -7,13 +7,46 @@
|
||||
{% block maincontent %}
|
||||
|
||||
<div class="LP-UserProfile">
|
||||
<div class="LP-UserProfile__Bio">
|
||||
<h2 class="LP-Headline">Bio</h2>
|
||||
<p class="LP-Paragraph">{{explorer.bio}}</p>
|
||||
</div>
|
||||
<div class="LP-UserProfile__Info">
|
||||
<div class="LP-UserInfo">
|
||||
<div class="LP-UserInfo__UserName">
|
||||
<h1 class="LP-Headline">{{explorer.user.username}}</h1>
|
||||
</div>
|
||||
|
||||
<div class="LP-UserInfo__Meta">
|
||||
<table>
|
||||
<tr>
|
||||
{% if explorer.profile_image %}
|
||||
<figure class="LP-UserInfo__Image">
|
||||
<img src="{{ explorer.profile_image.url }}" class="LP-Image" />
|
||||
</figure>
|
||||
{% endif %}
|
||||
<tr>
|
||||
{% if explorer.user.first_name %}
|
||||
<td class="LP-UserInfo__Key">
|
||||
<span class="LP-Paragraph">{% trans 'Name' %}</span>
|
||||
</td>
|
||||
<td class="LP-UserInfo__Value">
|
||||
<span class="LP-Paragraph">{{explorer.user.first_name}} {{explorer.user.last_name}}</span>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
<tr>
|
||||
{% if explorer.user.email %}
|
||||
<td class="LP-UserInfo__Key">
|
||||
<span class="LP-Paragraph">{% trans 'E-mail' %}</span>
|
||||
</td>
|
||||
<td class="LP-UserInfo__Value">
|
||||
<span class="LP-Paragraph">
|
||||
<a href="{{explorer.user.email}}" class="LP-Link">{{explorer.user.email}}</a>
|
||||
</span>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="LP-UserInfo__Key">
|
||||
<span class="LP-Paragraph">{% trans 'Joined' %}</span>
|
||||
@@ -32,18 +65,51 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="LP-UserInfo__Key">
|
||||
<span class="LP-Paragraph">{% trans 'Place Assets'%}</span>
|
||||
<span class="LP-Paragraph">{% trans 'Place assets'%}</span>
|
||||
</td>
|
||||
<td class="LP-UserInfo__Value">
|
||||
<span class="LP-Paragraph">{{asset_count}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="/explorer/update/"><button class="LP-Button LP-Button">{% trans 'Edit Profile' %}</button></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="LP-Section">
|
||||
<div class="LP-PlaceList">
|
||||
<h1 class="LP-Headline">{% trans 'Favorite places' %}</h1>
|
||||
<ul class="LP-PlaceList__List">
|
||||
{% for place in explorer.favorite_places.all %}
|
||||
<li class="LP-PlaceList__Item">
|
||||
{% include 'partials/place_teaser.html' with place=place extended=True %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% include 'partials/nav/pagination.html' %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="LP-Section">
|
||||
<div class="LP-PlaceList">
|
||||
<h1 class="LP-Headline">{% trans 'Visited places' %}</h1>
|
||||
<ul class="LP-PlaceList__List">
|
||||
{% for place in explorer.visited_places.all %}
|
||||
<li class="LP-PlaceList__Item">
|
||||
{% include 'partials/place_teaser.html' with place=place extended=True %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% include 'partials/nav/pagination.html' %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="LP-Section">
|
||||
<div class="LP-PlaceList">
|
||||
<h1 class="LP-Headline">{% trans 'Places submitted by' %} {{explorer.user.username}}</h1>
|
||||
|
@@ -0,0 +1,55 @@
|
||||
{% extends 'global.html'%}
|
||||
{% load i18n %}
|
||||
{% load thumbnail %}
|
||||
{% load widget_tweaks %}
|
||||
|
||||
# {% block title %}{% trans 'Edit Explorer profile' %}{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
|
||||
<form class="LP-Form" method="POST" enctype="multipart/form-data">
|
||||
<fieldset class="LP-Form__Fieldset">
|
||||
<legend class="LP-Form__Legend">{% trans 'Edit Explorer profile' %}</legend>
|
||||
{% csrf_token %}
|
||||
<div class="LP-Form__Composition LP-Form__Composition--breakable">
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.username %}
|
||||
</div>
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.email %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="LP-Form__Composition LP-Form__Composition--breakable">
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.first_name %}
|
||||
</div>
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=explorer_user_change_form.last_name %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="LP-Form__Composition">
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=explorer_change_form.bio %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="LP-Form__Composition">
|
||||
{% if explorer_image %}
|
||||
<div class="LP-Form__Field">
|
||||
<img src="{% thumbnail explorer_image 200x200 %}"/>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=explorer_change_form.profile_image %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% trans 'Update' as action %}
|
||||
<div class="LP-Form__Composition LP-Form__Composition--buttons">
|
||||
{% include 'partials/form/submit.html' with referrer=request.META.HTTP_REFERER action=action %}
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
{% endblock maincontent %}
|
@@ -30,7 +30,7 @@
|
||||
{% if user.is_authenticated %}
|
||||
Hi {{ user.username }}!
|
||||
<a class="LP-Link" href="{% url 'logout' %}"><span class="LP-Link__Text">{% trans 'Logout' %}</span></a> |
|
||||
<a class="LP-Link" href="{% url 'explorer_profile' explorer_id=user.pk%}"><span class="LP-Link__Text">{% trans 'Profile' %}</span></a>
|
||||
<a class="LP-Link" href="{% url 'explorer_profile' explorer_id=user.pk%}"><span class="LP-Link__Text">{% trans 'Profile' %}</span></a>
|
||||
{% if user.is_superuser %}
|
||||
| <a class="LP-Link" href="{% url 'admin:index' %}" target="_blank"><span class="LP-Link__Text">{% trans 'Admin' %}</span></a>
|
||||
{% endif %}
|
||||
@@ -50,7 +50,7 @@
|
||||
<ul class="LP-Menu__List">
|
||||
<li class="LP-Menu__Item"><a href="{% url 'lostplaces_home' %}" class="LP-Link"><span class="LP-Link__Text">{% trans 'Home' %}</span></a></li>
|
||||
<li class="LP-Menu__Item"><a href="{% url 'flatpage' slug='codex' %}" class="LP-Link"><span class="LP-Link__Text">{% trans 'UrBex Codex' %}</span></a></li>
|
||||
|
||||
<li class="LP-Menu__Item"><a href="{% url 'osm' %}" class="LP-Link"><span class="LP-Link__Text">{% trans 'Map' %}</span></a></li>
|
||||
{% block additional_menu_items %}
|
||||
{% endblock additional_menu_items %}
|
||||
|
||||
|
@@ -15,7 +15,7 @@
|
||||
<article class="LP-TextSection">
|
||||
</article>
|
||||
|
||||
{% include 'partials/osm_map.html' with config=mapping_config %}
|
||||
{% include 'partials/osm_map.html' with config=mapping_config modifier='wide' %}
|
||||
<div class="LP-PlaceGrid">
|
||||
<h1 class="LP-Headline LP-Headline">{% trans 'Explore the latest places' %}</h1>
|
||||
<ul class="LP-PlaceGrid__Grid">
|
||||
|
16
django_lostplaces/lostplaces/templates/osm_map_full.html
Normal file
16
django_lostplaces/lostplaces/templates/osm_map_full.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{% extends 'global.html'%}
|
||||
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% block additional_head %}
|
||||
<link rel="stylesheet" href="{% static 'maps/ol.css' %}" type="text/css">
|
||||
<script src="{% static 'maps/ol.js' %}"></script>
|
||||
{% endblock additional_head %}
|
||||
|
||||
# {% block title %}{% trans 'Map' %}{% endblock %}
|
||||
|
||||
{% block maincontent %}
|
||||
|
||||
{% include 'partials/osm_map.html' with config=mapping_config modifier='full' %}
|
||||
|
||||
{% endblock maincontent %}
|
@@ -4,11 +4,11 @@
|
||||
{% if request.user %}
|
||||
{% if place in request.user.explorer.favorite_places.all %}
|
||||
<a href="{% url 'place_unfavorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Remove from favorites' %}">
|
||||
<img class="LP-Icon" src="{% static '/icons/favourite_filled.svg' %}" />
|
||||
<img class="LP-Icon" src="{% static '/icons/favorite_filled.svg' %}" />
|
||||
</a>
|
||||
{%else%}
|
||||
<a href="{% url 'place_favorite' place_id=place.id %}" class="LP-Link" title="{% trans 'Save as favorite' %}">
|
||||
<img class="LP-Icon" src="{% static '/icons/favourite.svg' %}" />
|
||||
<img class="LP-Icon" src="{% static '/icons/favorite.svg' %}" />
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
@@ -0,0 +1,14 @@
|
||||
{%load static %}
|
||||
{% load i18n %}
|
||||
|
||||
{% if request.user %}
|
||||
{% if place in request.user.explorer.visited_places.all %}
|
||||
<a href="{% url 'place_visit_delete' place_id=place.id %}" class="LP-Link" title="{% trans 'Remove from visits' %}">
|
||||
<img class="LP-Icon" src="{% static '/icons/pin_filled.svg' %}" />
|
||||
</a>
|
||||
{%else%}
|
||||
<a href="{% url 'place_visit_create' place_id=place.id %}" class="LP-Link" title="{% trans 'Save as visited' %}">
|
||||
<img class="LP-Icon" src="{% static '/icons/pin.svg' %}" />
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
@@ -1,5 +1,5 @@
|
||||
{% load static %}
|
||||
<div tabindex="1" id="map" class="LP-Map map" style="height: 300px"></div>
|
||||
<div tabindex="1" id="map" class="LP-Map {% if modifier %}LP-Map--{{modifier}}{% endif %} map"></div>
|
||||
<div id="info" class="map-popup LP-Map__Popup"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@@ -31,7 +31,7 @@
|
||||
<div class="LP-PlaceTeaser__Icons">
|
||||
<ul class="LP-Icon__List">
|
||||
<li class="LP-Icon__Item">{% include 'partials/icons/place_favorite.html' with place=place%}</li>
|
||||
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/location.svg' %}" /></li>
|
||||
<li class="LP-Icon__Item">{% include 'partials/icons/place_visited.html' with place=place%}</li>
|
||||
<li class="LP-Icon__Item"><img class="LP-Icon" src="{% static '/icons/flag.svg' %}" /></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<article class="LP-PlaceDetail">
|
||||
|
||||
<header class="LP-PlaceDetail__Header">
|
||||
<h1 class="LP-Headline">{{ place.name }} {% include 'partials/icons/place_favorite.html' %}</h1>
|
||||
<h1 class="LP-Headline">{{ place.name }} {% include 'partials/icons/place_favorite.html' %} {% include 'partials/icons/place_visited.html' %}</h1>
|
||||
{% if place.placeimages.first.filename.hero.url %}
|
||||
<figure class="LP-PlaceDetail__Image">
|
||||
<img src="{{ place.placeimages.first.filename.hero.url }}" class="LP-Image" />
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
<section class="LP-Section">
|
||||
<h1 class="LP-Headline">{% trans 'Map links' %}</h1>
|
||||
{% include 'partials/osm_map.html' with config=mapping_config%}
|
||||
{% include 'partials/osm_map.html' with config=mapping_config modifier='wide' %}
|
||||
<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|safe}},{{place.longitude|safe}}" class="LP-Link"><span class="LP-Text">Google Maps</span></a></li>
|
||||
|
@@ -11,7 +11,7 @@
|
||||
|
||||
{% block maincontent %}
|
||||
|
||||
{% include 'partials/osm_map.html' with config=mapping_config %}
|
||||
{% include 'partials/osm_map.html' with config=mapping_config modifier='wide' %}
|
||||
<div class="LP-PlaceList">
|
||||
<h1 class="LP-Headline">{% trans 'Our lost places' %}</h1>
|
||||
<ul class="LP-PlaceList__List">
|
||||
|
@@ -19,6 +19,14 @@
|
||||
{% include 'partials/form/inputField.html' with field=form.email %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="LP-Form__Composition LP-Form__Composition--breakable">
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=form.first_name %}
|
||||
</div>
|
||||
<div class="LP-Form__Field">
|
||||
{% include 'partials/form/inputField.html' with field=form.last_name %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="LP-Form__Composition">
|
||||
<div class="LP-Form__Field">
|
||||
|
@@ -4,15 +4,15 @@ from django import forms
|
||||
from django.utils import timezone
|
||||
|
||||
from lostplaces.tests.forms import FormTestCase
|
||||
from lostplaces.forms import ExplorerCreationForm
|
||||
from lostplaces.forms import SignupVoucherForm
|
||||
from lostplaces.models.models import Voucher
|
||||
|
||||
class ExplorerCreationFormTestCase(FormTestCase):
|
||||
class SignupVoucherFormTestCase(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
|
||||
form = SignupVoucherForm
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
@@ -37,7 +37,7 @@ class ExplorerCreationFormTestCase(FormTestCase):
|
||||
)
|
||||
|
||||
def test_validation_valid(self):
|
||||
form = ExplorerCreationForm(self.post_data)
|
||||
form = SignupVoucherForm(self.post_data)
|
||||
self.assertTrue(
|
||||
form.is_valid(),
|
||||
msg='Expecting the %s to validate' % (
|
||||
@@ -49,7 +49,7 @@ class ExplorerCreationFormTestCase(FormTestCase):
|
||||
self.post_data = {
|
||||
'voucher': 'Imanotacode123'
|
||||
}
|
||||
form = ExplorerCreationForm(self.post_data)
|
||||
form = SignupVoucherForm(self.post_data)
|
||||
self.assertFalse(
|
||||
form.is_valid(),
|
||||
msg='Expecting the %s to not validate' % (
|
||||
|
@@ -4,6 +4,8 @@
|
||||
from django.urls import path
|
||||
from lostplaces.views import (
|
||||
HomeView,
|
||||
FlatView,
|
||||
OSMMapView,
|
||||
PlaceDetailView,
|
||||
PlaceListView,
|
||||
PlaceCreateView,
|
||||
@@ -13,35 +15,39 @@ from lostplaces.views import (
|
||||
PlaceTagSubmitView,
|
||||
PlaceFavoriteView,
|
||||
PlaceUnfavoriteView,
|
||||
PhotoAlbumCreateView,
|
||||
PhotoAlbumDeleteView,
|
||||
PlaceVisitCreateView,
|
||||
PlaceVisitDeleteView,
|
||||
PlaceImageCreateView,
|
||||
PlaceImageDeleteView,
|
||||
FlatView,
|
||||
ExplorerProfileView
|
||||
PhotoAlbumCreateView,
|
||||
PhotoAlbumDeleteView,
|
||||
ExplorerProfileView,
|
||||
ExplorerProfileUpdateView
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
path('', HomeView.as_view(), name='lostplaces_home'),
|
||||
path('flat/<slug:slug>/', FlatView, name='flatpage'),
|
||||
path('osm/', OSMMapView.as_view(), name='osm'),
|
||||
|
||||
path('explorer/<int:explorer_id>/', ExplorerProfileView.as_view(), name='explorer_profile'),
|
||||
path('explorer/update/', ExplorerProfileUpdateView.as_view(), name='explorer_profile_update'),
|
||||
|
||||
path('place/', PlaceListView.as_view(), name='place_list'),
|
||||
path('place/<int:pk>/', PlaceDetailView.as_view(), name='place_detail'),
|
||||
path('place/create/', PlaceCreateView.as_view(), name='place_create'),
|
||||
path('photo_album/create/<int:place_id>', PhotoAlbumCreateView.as_view(), name='photo_album_create'),
|
||||
path('photo_album/delete/<int:pk>', PhotoAlbumDeleteView.as_view(), name='photo_album_delete'),
|
||||
path('place/update/<int:pk>/', PlaceUpdateView.as_view(), name='place_edit'),
|
||||
path('place/delete/<int:pk>/', PlaceDeleteView.as_view(), name='place_delete'),
|
||||
path('place/', PlaceListView.as_view(), name='place_list'),
|
||||
path('place_image/create/<int:place_id>', PlaceImageCreateView.as_view(), name='place_image_create'),
|
||||
path('place_image/delete/<int:pk>', PlaceImageDeleteView.as_view(), name='place_image_delete'),
|
||||
path('flat/<slug:slug>/', FlatView, name='flatpage'),
|
||||
path('place/tag/create/<int:tagged_id>/', PlaceTagSubmitView.as_view(), name='place_tag_submit'),
|
||||
path('place/tag/delete/<int:tagged_id>/<int:tag_id>/', PlaceTagDeleteView.as_view(), name='place_tag_delete'),
|
||||
path('place/fav/create/<int:place_id>/', PlaceFavoriteView.as_view(), name='place_favorite'),
|
||||
path('place/fav/delete/<int:place_id>/', PlaceUnfavoriteView.as_view(), name='place_unfavorite'),
|
||||
path('place/visit/create/<int:place_id>/', PlaceVisitCreateView.as_view(), name='place_visit_create'),
|
||||
path('place/visit/delete/<int:place_id>/', PlaceVisitDeleteView.as_view(), name='place_visit_delete'),
|
||||
|
||||
# POST-only URLs for tag submission
|
||||
path('place/tag/<int:tagged_id>', PlaceTagSubmitView.as_view(), name='place_tag_submit'),
|
||||
path('place/tag/delete/<int:tagged_id>/<int:tag_id>', PlaceTagDeleteView.as_view(), name='place_tag_delete'),
|
||||
|
||||
path('explorer/<int:explorer_id>/', ExplorerProfileView.as_view(), name='explorer_profile'),
|
||||
|
||||
path('explorer/favorite/<int:place_id>/', PlaceFavoriteView.as_view(), name='place_favorite'),
|
||||
path('explorer/unfavorite/<int:place_id>/', PlaceUnfavoriteView.as_view(), name='place_unfavorite')
|
||||
|
||||
|
||||
path('place_image/create/<int:place_id>/', PlaceImageCreateView.as_view(), name='place_image_create'),
|
||||
path('place_image/delete/<int:pk>/', PlaceImageDeleteView.as_view(), name='place_image_delete'),
|
||||
|
||||
path('photo_album/create/<int:place_id>/', PhotoAlbumCreateView.as_view(), name='photo_album_create'),
|
||||
path('photo_album/delete/<int:pk>/', PhotoAlbumDeleteView.as_view(), name='photo_album_delete')
|
||||
]
|
||||
|
@@ -10,10 +10,11 @@ from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
|
||||
from django.shortcuts import redirect, get_object_or_404
|
||||
from django.urls import reverse_lazy
|
||||
from django.urls import reverse_lazy, reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from lostplaces.models import Place
|
||||
from lostplaces.common import redirect_referer_or
|
||||
|
||||
class IsAuthenticatedMixin(LoginRequiredMixin, View):
|
||||
'''
|
||||
@@ -108,4 +109,4 @@ class PlaceAssetDeleteView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, SingleOb
|
||||
place_id = self.get_object().place.id
|
||||
self.get_object().delete()
|
||||
messages.success(self.request, self.success_message)
|
||||
return redirect(reverse_lazy('place_detail', kwargs={'pk': place_id}))
|
||||
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place_id}))
|
||||
|
@@ -7,16 +7,18 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.urls import reverse_lazy
|
||||
from django.contrib import messages
|
||||
|
||||
from lostplaces.common import get_all_subclasses
|
||||
from lostplaces.views.base_views import IsAuthenticatedMixin
|
||||
from lostplaces.models.models import Explorer
|
||||
from lostplaces.models.place import Place, PlaceAsset
|
||||
from lostplaces.forms import ExplorerChangeForm, ExplorerUserChangeForm
|
||||
|
||||
class ExplorerProfileView(IsAuthenticatedMixin, View):
|
||||
def get(self, request, explorer_id):
|
||||
explorer = get_object_or_404(Explorer, pk=explorer_id)
|
||||
place_list = Place.objects.filter(submitted_by=explorer)
|
||||
place_list = explorer.places.all()
|
||||
place_count = place_list.count()
|
||||
|
||||
context={
|
||||
@@ -33,13 +35,53 @@ class ExplorerProfileView(IsAuthenticatedMixin, View):
|
||||
asset_count += objects.count()
|
||||
|
||||
context['asset_count'] = asset_count
|
||||
|
||||
print(context['assets'])
|
||||
|
||||
|
||||
return render(
|
||||
request=request,
|
||||
template_name='explorer/profile.html',
|
||||
context=context
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ExplorerProfileUpdateView(IsAuthenticatedMixin, View):
|
||||
success_message = ''
|
||||
permission_denied_message = ''
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
context = {
|
||||
'explorer_user_change_form': ExplorerUserChangeForm(instance=request.user),
|
||||
'explorer_change_form': ExplorerChangeForm(instance=request.user.explorer)
|
||||
}
|
||||
if request.user.explorer.profile_image:
|
||||
context['explorer_image'] = request.user.explorer.profile_image
|
||||
return render(request, 'explorer/profile_update.html', context)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
print(request.POST)
|
||||
explorer_user_change_form = ExplorerUserChangeForm(
|
||||
request.POST,
|
||||
instance=request.user
|
||||
)
|
||||
explorer_change_form = ExplorerChangeForm(
|
||||
request.POST,
|
||||
request.FILES,
|
||||
instance=request.user.explorer
|
||||
)
|
||||
|
||||
if explorer_change_form.is_valid() and explorer_user_change_form.is_valid():
|
||||
explorer_user_change_form.save()
|
||||
explorer_change_form.save()
|
||||
|
||||
print(explorer_change_form.cleaned_data)
|
||||
|
||||
messages.success(
|
||||
self.request,
|
||||
_('Successfully updated Explorer profile')
|
||||
)
|
||||
else:
|
||||
# Usually the browser should have checked the form before sending.
|
||||
messages.error(
|
||||
self.request,
|
||||
_('Please fill in all required fields.')
|
||||
)
|
||||
return redirect(reverse_lazy('explorer_profile_update'))
|
||||
|
@@ -13,12 +13,13 @@ 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
|
||||
from django.urls import reverse_lazy, reverse
|
||||
|
||||
from lostplaces.models import Place, PlaceImage
|
||||
from lostplaces.views.base_views import IsAuthenticatedMixin, IsPlaceSubmitterMixin
|
||||
from lostplaces.views.place_image_views import MultiplePlaceImageUploadMixin
|
||||
from lostplaces.forms import PlaceForm, PlaceImageForm, TagSubmitForm
|
||||
from lostplaces.common import redirect_referer_or
|
||||
|
||||
from taggit.models import Tag
|
||||
|
||||
@@ -104,7 +105,14 @@ class PlaceCreateView(MultiplePlaceImageUploadMixin, IsAuthenticatedMixin, View)
|
||||
self.request,
|
||||
_('Please fill in all required fields.')
|
||||
)
|
||||
return render(request, 'place/place_create.html', context={'form': place_form})
|
||||
return render(
|
||||
request=request,
|
||||
template_name='place/place_create.html',
|
||||
context={
|
||||
'place_form': place_form,
|
||||
'place_image_form': PlaceImageForm()
|
||||
}
|
||||
)
|
||||
|
||||
class PlaceDeleteView(IsAuthenticatedMixin, IsPlaceSubmitterMixin, DeleteView):
|
||||
template_name = 'place/place_delete.html'
|
||||
@@ -127,14 +135,8 @@ class PlaceFavoriteView(IsAuthenticatedMixin, View):
|
||||
if request.user is not None:
|
||||
request.user.explorer.favorite_places.add(place)
|
||||
request.user.explorer.save()
|
||||
|
||||
referer = request.META.get('HTTP_REFERER')
|
||||
if referer is not None:
|
||||
return redirect(referer)
|
||||
else:
|
||||
return redirect(
|
||||
reverse_lazy('place_detail', kwargs={'pk': place.pk})
|
||||
)
|
||||
|
||||
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))
|
||||
|
||||
class PlaceUnfavoriteView(IsAuthenticatedMixin, View):
|
||||
|
||||
@@ -143,11 +145,25 @@ class PlaceUnfavoriteView(IsAuthenticatedMixin, View):
|
||||
if request.user is not None:
|
||||
request.user.explorer.favorite_places.remove(place)
|
||||
request.user.explorer.save()
|
||||
|
||||
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))
|
||||
|
||||
class PlaceVisitCreateView(IsAuthenticatedMixin, View):
|
||||
|
||||
def get(self, request, place_id):
|
||||
place = get_object_or_404(Place, id=place_id)
|
||||
if request.user is not None:
|
||||
request.user.explorer.visited_places.add(place)
|
||||
request.user.explorer.save()
|
||||
|
||||
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))
|
||||
|
||||
referer = request.META.get('HTTP_REFERER')
|
||||
if referer is not None:
|
||||
return redirect(referer)
|
||||
else:
|
||||
return redirect(
|
||||
reverse_lazy('place_detail', kwargs={'pk': place.pk})
|
||||
)
|
||||
class PlaceVisitDeleteView(IsAuthenticatedMixin, View):
|
||||
|
||||
def get(self, request, place_id):
|
||||
place = get_object_or_404(Place, id=place_id)
|
||||
if request.user is not None:
|
||||
request.user.explorer.visited_places.remove(place)
|
||||
request.user.explorer.save()
|
||||
|
||||
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': place.pk}))
|
||||
|
@@ -6,14 +6,15 @@ from django.views.generic.edit import CreateView
|
||||
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.contrib import messages
|
||||
from django.urls import reverse_lazy
|
||||
from django.urls import reverse_lazy, reverse
|
||||
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.forms import SignupVoucherForm, TagSubmitForm
|
||||
from lostplaces.models import Place, PhotoAlbum
|
||||
from lostplaces.views.base_views import IsAuthenticatedMixin
|
||||
from lostplaces.common import redirect_referer_or
|
||||
|
||||
from lostplaces.views.base_views import (
|
||||
PlaceAssetCreateView,
|
||||
@@ -23,7 +24,7 @@ from lostplaces.views.base_views import (
|
||||
from taggit.models import Tag
|
||||
|
||||
class SignUpView(SuccessMessageMixin, CreateView):
|
||||
form_class = ExplorerCreationForm
|
||||
form_class = SignupVoucherForm
|
||||
success_url = reverse_lazy('login')
|
||||
template_name = 'signup.html'
|
||||
success_message = _('User created')
|
||||
@@ -79,10 +80,22 @@ class PlaceTagDeleteView(IsAuthenticatedMixin, View):
|
||||
place = get_object_or_404(Place, pk=tagged_id)
|
||||
tag = get_object_or_404(Tag, pk=tag_id)
|
||||
place.tags.remove(tag)
|
||||
return redirect(reverse_lazy('place_detail', kwargs={'pk': tagged_id}))
|
||||
|
||||
|
||||
return redirect_referer_or(request, reverse('place_detail', kwargs={'pk': tagged_id}))
|
||||
|
||||
def FlatView(request, slug):
|
||||
if request.LANGUAGE_CODE == 'de':
|
||||
return render(request, 'flat/' + slug + '-de' + '.html')
|
||||
else:
|
||||
return render(request, 'flat/' + slug + '.html')
|
||||
|
||||
class OSMMapView(IsAuthenticatedMixin, View):
|
||||
def get(self, request):
|
||||
place_list = Place.objects.all()
|
||||
context = {
|
||||
'mapping_config': {
|
||||
'all_points': place_list,
|
||||
'map_center': Place.average_latlon(place_list)
|
||||
}
|
||||
}
|
||||
return render(request, 'osm_map_full.html', context)
|
||||
|
Reference in New Issue
Block a user