#!/usr/bin/env python # -*- coding: utf-8 -*- ''' (Data)models which describe the structure of data to be saved into database. ''' import os import uuid from django.db import models from django.dispatch import receiver from django.contrib.auth.models import AbstractUser from easy_thumbnails.fields import ThumbnailerImageField # Create your models here. class Explorer(AbstractUser): """ Custom user model Addtional fields wbd """ def __str__(self): return self.username class Voucher(models.Model): """ 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. """ code = models.CharField(unique=True, max_length=10) created = models.DateTimeField(auto_now_add=True) expires = models.DateField() def __str__(self): return "Voucher " + str(self.pk) class Place (models.Model): """ Place defines a lost place (location, name, description etc.). """ name = models.CharField(max_length=50) submitted_when = models.DateTimeField(auto_now_add=True, null=True) submitted_by = models.ForeignKey( Explorer, on_delete=models.SET_NULL, null=True, blank=True, related_name='places' ) location = models.CharField(max_length=50) latitude = models.FloatField() longitude = models.FloatField() description = models.TextField() def __str__(self): return self.name def generate_image_upload_path(instance, filename): """ Callback for generating path for uploaded images. """ 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( Place, on_delete=models.CASCADE, related_name='images' ) submitted_by = models.ForeignKey( Explorer, on_delete=models.SET_NULL, null=True, blank=True, related_name='images' ) def __str__(self): """ Returning the name of the corresponding place + id of this image as textual represntation of this instance """ 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): """ Deletes file from filesystem when corresponding `PlaceImage` object is deleted. """ if instance.filename: 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): """ Deletes old file from filesystem when corresponding `PlaceImage` object is updated with new file. """ if not instance.pk: return False try: old_file = PlaceImage.objects.get(pk=instance.pk).filename except PlaceImage.DoesNotExist: return False new_file = instance.filename if not old_file == new_file: if os.path.isfile(old_file.path): os.remove(old_file.path)