diff --git a/lostplaces/lostplaces/settings.py b/lostplaces/lostplaces/settings.py index f69bacb..23940fb 100644 --- a/lostplaces/lostplaces/settings.py +++ b/lostplaces/lostplaces/settings.py @@ -131,9 +131,6 @@ STATIC_ROOT = os.path.join(BASE_DIR, 'static_files') MEDIA_URL = '/uploads/' MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads') -# Use custom user model -AUTH_USER_MODEL = 'lostplaces_app.Explorer' - # Templates to use for authentication LOGIN_URL = reverse_lazy('login') LOGIN_REDIRECT_URL = reverse_lazy('lostplaces_home') diff --git a/lostplaces/lostplaces_app/admin.py b/lostplaces/lostplaces_app/admin.py index 11e082a..5d53ab7 100644 --- a/lostplaces/lostplaces_app/admin.py +++ b/lostplaces/lostplaces_app/admin.py @@ -12,17 +12,11 @@ from .forms import ExplorerCreationForm, ExplorerChangeForm # Register your models here. -class ExplorerAdmin(UserAdmin): - add_form = ExplorerCreationForm - form = ExplorerChangeForm - model = Explorer - list_display = ['email', 'username',] - class VoucherAdmin(admin.ModelAdmin): fields = ['code', 'expires', 'created'] readonly_fields = ['created'] -admin.site.register(Explorer, ExplorerAdmin) +admin.site.register(Explorer) admin.site.register(Voucher, VoucherAdmin) admin.site.register(Place) admin.site.register(PlaceImage) diff --git a/lostplaces/lostplaces_app/forms.py b/lostplaces/lostplaces_app/forms.py index 8d78269..2b3f178 100644 --- a/lostplaces/lostplaces_app/forms.py +++ b/lostplaces/lostplaces_app/forms.py @@ -5,11 +5,12 @@ from django import forms from django.contrib.auth.forms import UserCreationForm, UserChangeForm -from .models import Explorer, Place, PlaceImage, Voucher +from django.contrib.auth.models import User +from lostplaces_app.models import Place, PlaceImage, Voucher class ExplorerCreationForm(UserCreationForm): class Meta: - model = Explorer + model = User fields = ('username', 'email') voucher = forms.CharField( max_length=30, @@ -30,7 +31,7 @@ class ExplorerCreationForm(UserCreationForm): class ExplorerChangeForm(UserChangeForm): class Meta: - model = Explorer + model = User fields = ('username', 'email') class PlaceForm(forms.ModelForm): diff --git a/lostplaces/lostplaces_app/models.py b/lostplaces/lostplaces_app/models.py index 47133e0..8e1885a 100644 --- a/lostplaces/lostplaces_app/models.py +++ b/lostplaces/lostplaces_app/models.py @@ -10,22 +10,40 @@ 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.dispatch import receiver -from django.contrib.auth.models import AbstractUser from django.core.validators import MaxValueValidator, MinValueValidator from easy_thumbnails.fields import ThumbnailerImageField from taggit.managers import TaggableManager # Create your models here. -class Explorer(AbstractUser): + +class Explorer(models.Model): """ - Custom user model - Addtional fields wbd + Profile that is linked to the a User. + Every user has a profile. """ + + user = models.OneToOneField( + User, + on_delete=models.CASCADE, + related_name='explorer' + ) def __str__(self): - return self.username + return self.user.name + +@receiver(post_save, sender=User) +def create_user_profile(sender, instance, created, **kwargs): + if created: + Explorer.objects.create(user=instance) + +@receiver(post_save, sender=User) +def save_user_profile(sender, instance, **kwargs): + instance.explorer.save() + class Voucher(models.Model): """ @@ -42,6 +60,7 @@ class Voucher(models.Model): def __str__(self): return "Voucher " + str(self.pk) + class Place (models.Model): """ Place defines a lost place (location, name, description etc.). @@ -53,7 +72,7 @@ class Place (models.Model): Explorer, on_delete=models.SET_NULL, null=True, - blank=True, + blank=True, related_name='places' ) location = models.CharField(max_length=50) @@ -79,7 +98,7 @@ class Place (models.Model): # Init fill values to prevent None longitude = 0 latitude = 0 - + if amount > 0: for place in place_list: longitude += place.longitude @@ -91,6 +110,7 @@ class Place (models.Model): def __str__(self): return self.name + def generate_image_upload_path(instance, filename): """ Callback for generating path for uploaded images. @@ -98,13 +118,14 @@ def generate_image_upload_path(instance, filename): return 'places/' + str(uuid.uuid4())+'.'+filename.split('.')[-1] + class PlaceImage (models.Model): """ PlaceImage defines an image file object that points to a file in uploads/. Intermediate image sizes are generated as defined in SIZES. PlaceImage references a Place to which it belongs. """ - + description = models.TextField(blank=True) filename = ThumbnailerImageField(upload_to=generate_image_upload_path) place = models.ForeignKey( @@ -117,7 +138,7 @@ class PlaceImage (models.Model): Explorer, on_delete=models.SET_NULL, null=True, - blank=True, + blank=True, related_name='images' ) @@ -130,6 +151,8 @@ class PlaceImage (models.Model): return ' '.join([self.place.name, str(self.pk)]) # These two auto-delete files from filesystem when they are unneeded: + + @receiver(models.signals.post_delete, sender=PlaceImage) def auto_delete_file_on_delete(sender, instance, **kwargs): """ @@ -140,6 +163,7 @@ def auto_delete_file_on_delete(sender, instance, **kwargs): if os.path.isfile(instance.filename.path): os.remove(instance.filename.path) + @receiver(models.signals.pre_save, sender=PlaceImage) def auto_delete_file_on_change(sender, instance, **kwargs): """ @@ -160,6 +184,7 @@ def auto_delete_file_on_change(sender, instance, **kwargs): if os.path.isfile(old_file.path): os.remove(old_file.path) + class ExternalLink(models.Model): url = models.URLField(max_length=200) label = models.CharField(max_length=100) @@ -167,11 +192,12 @@ class ExternalLink(models.Model): Explorer, on_delete=models.SET_NULL, null=True, - blank=True, + blank=True, related_name='external_links' ) submitted_when = models.DateTimeField(auto_now_add=True, null=True) + class PhotoAlbum(ExternalLink): place = models.ForeignKey( Place, diff --git a/lostplaces/lostplaces_app/templates/partials/tagging.html b/lostplaces/lostplaces_app/templates/partials/tagging.html index 581055b..471f880 100644 --- a/lostplaces/lostplaces_app/templates/partials/tagging.html +++ b/lostplaces/lostplaces_app/templates/partials/tagging.html @@ -6,7 +6,7 @@ {{tag}} - {% if request.user and request.user == config.tagged_item.submitted_by %} + {% if request.user and request.user.explorer == config.tagged_item.submitted_by %} @@ -28,7 +28,7 @@ Tags hinzufügen {% csrf_token %}
-
+
@@ -46,11 +46,15 @@ submit_form.onsubmit = () => false const tagify = new Tagify(input, { - 'whitelist': [ - {% for tag in all_tags %} - '{{tag}}', - {% endfor %} - ] + 'whitelist': [{ + % + for tag in all_tags % + } + '{{tag}}', + { + % endfor % + } + ] }) const on_form_submit = function() { diff --git a/lostplaces/lostplaces_app/templates/place/place_detail.html b/lostplaces/lostplaces_app/templates/place/place_detail.html index b7ecfe8..23eece1 100644 --- a/lostplaces/lostplaces_app/templates/place/place_detail.html +++ b/lostplaces/lostplaces_app/templates/place/place_detail.html @@ -62,7 +62,7 @@ {{photo_album.label}} - {% if user == photo_album.submitted_by or user == place.submitted_by %} + {% if user.explorer == photo_album.submitted_by or user.explorer == place.submitted_by %}
{% icon 'trash' className="RV-Iconized__Icon" %} diff --git a/lostplaces/lostplaces_app/tests/__init__.py b/lostplaces/lostplaces_app/tests/__init__.py index d23299f..7eae89c 100644 --- a/lostplaces/lostplaces_app/tests/__init__.py +++ b/lostplaces/lostplaces_app/tests/__init__.py @@ -1,11 +1,11 @@ from django.db import models as django_models -from lostplaces_app.models import Explorer +from django.contrib.auth.models import User def mock_user(): - explorer_list = Explorer.objects.all() + explorer_list = User.objects.all() if len(explorer_list) <= 0: - return Explorer.objects.create_user( + return User.objects.create_user( username='testpeter', password='Develop123' ) diff --git a/lostplaces/lostplaces_app/tests/models/test_place_image_model.py b/lostplaces/lostplaces_app/tests/models/test_place_image_model.py index bd1bf41..ef5526b 100644 --- a/lostplaces/lostplaces_app/tests/models/test_place_image_model.py +++ b/lostplaces/lostplaces_app/tests/models/test_place_image_model.py @@ -19,7 +19,7 @@ def mock_place_image(): filename=mock.MagicMock(spec=File, name='FileMock'), place=mock_place(), submitted_when=datetime.datetime.now(), - submitted_by=mock_user() + submitted_by=mock_user().explorer ) class TestPlaceImage(TestSubmittable, TestCase): diff --git a/lostplaces/lostplaces_app/tests/models/test_place_model.py b/lostplaces/lostplaces_app/tests/models/test_place_model.py index 7213266..3996bd6 100644 --- a/lostplaces/lostplaces_app/tests/models/test_place_model.py +++ b/lostplaces/lostplaces_app/tests/models/test_place_model.py @@ -14,7 +14,7 @@ def mock_place(): place = Place.objects.create( name='Im a place', submitted_when=datetime.datetime.now(), - submitted_by=mock_user(), + submitted_by=mock_user().explorer, location='Testtown', latitude=50.5, longitude=7.0, diff --git a/lostplaces/lostplaces_app/tests/views/test_base_views.py b/lostplaces/lostplaces_app/tests/views/test_base_views.py index 6525595..60a03d4 100644 --- a/lostplaces/lostplaces_app/tests/views/test_base_views.py +++ b/lostplaces/lostplaces_app/tests/views/test_base_views.py @@ -3,7 +3,7 @@ from django.urls import reverse_lazy from lostplaces_app.models import Place -from lostplaces_app.models import Explorer +from django.contrib.auth.models import User from lostplaces_app.tests.models.test_place_model import mock_place from lostplaces_app.tests import mock_user @@ -23,7 +23,7 @@ class TestIsAuthenticated(TestCase): response = self.client.get(url, follow=True) self.assertRedirects( response=response, - expected_url='?'.join([str(reverse_lazy('login')), 'redirect_to=/place/1/']), + expected_url='?'.join([str(reverse_lazy('login')), 'next=/place/1/']), status_code=302, target_status_code=200, msg_prefix='''Accesing an IsAuthenticated view while not logged should @@ -47,7 +47,7 @@ class TestIsPlaceSubmitter(TestCase): self.assertEqual(response.status_code, 200) def test_is_no_submitter(self): - Explorer.objects.create_user( + User.objects.create_user( username='manfred', password='Develop123' ) diff --git a/lostplaces/lostplaces_app/tests/views/test_place_views.py b/lostplaces/lostplaces_app/tests/views/test_place_views.py index ff4b46f..ae9c671 100644 --- a/lostplaces/lostplaces_app/tests/views/test_place_views.py +++ b/lostplaces/lostplaces_app/tests/views/test_place_views.py @@ -23,7 +23,7 @@ class TestPlaceCreateView(TestCase): response = self.client.get(url) self.assertRedirects( response=response, - expected_url='?'.join([str(reverse_lazy('login')), 'redirect_to=/place/1/']), + expected_url='?'.join([str(reverse_lazy('login')), 'next=/place/1/']), status_code=302, target_status_code=200, msg_prefix='''Accesing PlaceDetailView while not logged should diff --git a/lostplaces/lostplaces_app/views/base_views.py b/lostplaces/lostplaces_app/views/base_views.py index 8012f6f..1eedc6f 100644 --- a/lostplaces/lostplaces_app/views/base_views.py +++ b/lostplaces/lostplaces_app/views/base_views.py @@ -48,7 +48,7 @@ class IsPlaceSubmitter(UserPassesTestMixin, View): # Check if currently logged in user was the submitter place_obj = self.get_place() - if place_obj and hasattr(place_obj, 'submitted_by') and self.request.user == place_obj.submitted_by: + if place_obj and hasattr(place_obj, 'submitted_by') and self.request.user.explorer == place_obj.submitted_by: return True if self.place_submitter_error_message: @@ -69,7 +69,7 @@ class PlaceAssetCreateView(IsAuthenticated, SuccessMessageMixin, CreateView): self.place = Place.objects.get(pk=place_id) response = super().post(request, *args, **kwargs) self.object.place = self.place - self.object.submitted_by = request.user + self.object.submitted_by = request.user.explorer self.object.save() return response @@ -95,7 +95,7 @@ class PlaceAssetDeleteView(IsAuthenticated, IsPlaceSubmitter, SingleObjectMixin, if can_edit_place: return True - if self.get_object().submitted_by == self.request.user: + if self.get_object().submitted_by == self.request.user.explorer: return True messages.error(self.request, self.permission_denied_message) diff --git a/lostplaces/lostplaces_app/views/place_views.py b/lostplaces/lostplaces_app/views/place_views.py index f538187..4855b20 100644 --- a/lostplaces/lostplaces_app/views/place_views.py +++ b/lostplaces/lostplaces_app/views/place_views.py @@ -72,7 +72,7 @@ class PlaceCreateView(IsAuthenticated, View): place_form = PlaceForm(request.POST) if place_form.is_valid(): - submitter = request.user + submitter = request.user.explorer place = place_form.save(commit=False) # Save logged in user as "submitted_by" place.submitted_by = submitter