lostplaces-backend/lostplaces/lostplaces_app/models.py

182 lines
5.0 KiB
Python

#!/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 django.core.validators import MaxValueValidator, MinValueValidator
from easy_thumbnails.fields import ThumbnailerImageField
from taggit.managers import TaggableManager
# 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=30)
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(
validators=[
MinValueValidator(-90),
MaxValueValidator(90)
]
)
longitude = models.FloatField(
validators=[
MinValueValidator(-180),
MaxValueValidator(180)
]
)
description = models.TextField()
tags = TaggableManager(blank=True)
# Get center position of LP-geocoordinates.
def average_latlon(place_list):
amount = len(place_list)
# Init fill values to prevent None
longitude = 0
latitude = 0
if amount > 0:
for place in place_list:
longitude += place.longitude
latitude += place.latitude
return (latitude / amount, longitude / amount)
return (latitude, longitude)
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_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='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)
class ExternalLink(models.Model):
url = models.URLField(max_length=200)
label = models.CharField(max_length=100)
submitted_by = models.ForeignKey(
Explorer,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='external_links'
)
submitted_when = models.DateTimeField(auto_now_add=True, null=True)
class PhotoAlbum(ExternalLink):
place = models.ForeignKey(
Place,
on_delete=models.CASCADE,
related_name='photo_albums',
null=True
)