You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
xmrauctions/items/models.py

107 lines
4.1 KiB
Python

from os import path as os_path
from secrets import token_urlsafe
from django_prometheus.models import ExportModelOperationsMixin
from django.db import models
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.contrib.auth.models import User
from monero.address import address
from PIL import Image, ExifTags
from io import BytesIO
from core.monero import AuctionDaemon
from core.validators import address_is_valid_monero
ItemSaleTypes = (
('SHIPPING', 'Ship the item to a provided address.'),
('MEETING', 'Deliver the item to an agreed upon public location.')
)
class Item(ExportModelOperationsMixin('item'), models.Model):
owner = models.ForeignKey(User, related_name='owner', on_delete=models.CASCADE)
name = models.CharField(max_length=100)
list_date = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
description = models.TextField(max_length=500)
ask_price_xmr = models.FloatField()
available = models.BooleanField(default=True)
payout_address = models.CharField(max_length=100, validators=[address_is_valid_monero])
whereabouts = models.CharField(max_length=100)
sale_type = models.CharField(max_length=20, choices=ItemSaleTypes, default='SHIPPING')
def __str__(self):
return f"{self.id} - {self.owner} - {self.name}"
class ItemImage(ExportModelOperationsMixin('item_image'), models.Model):
item = models.ForeignKey(Item, related_name='images', on_delete=models.CASCADE)
image = models.ImageField(upload_to='%Y/%m/%d')
thumbnail = models.ImageField(upload_to='%Y/%m/%d')
def save(self, *args, **kwargs):
self.correct_image()
super(ItemImage, self).save(*args, **kwargs)
def correct_image(self):
try:
# Open image and set some variables
img = Image.open(self.image)
img_format = img.format
max_size = (800, 800)
thumb_size = (150, 150)
file_ext = os_path.splitext(self.image.name)[1]
random_str = token_urlsafe(12)
img_name = f'{self.item.id}-{random_str}.%s{file_ext}'
img_bytes = BytesIO()
thumb_bytes = BytesIO()
# If image contains exif check for orientation and rotate
for orientation in ExifTags.TAGS.keys():
if ExifTags.TAGS[orientation] == 'Orientation':
img_exif = img._getexif()
if img_exif:
if orientation in img_exif:
image_orientation = img_exif[orientation]
if image_orientation == 3:
img = img.rotate(180, expand=True)
if image_orientation == 6:
img = img.rotate(-90, expand=True)
if image_orientation == 8:
img = img.rotate(90, expand=True)
# Store a copy of the image for thumbnail
thumb = img.copy()
# TODO - task this and just present page without until it's done
# Correct the image size to safe maximums
img.thumbnail(max_size, Image.ANTIALIAS)
img.save(img_bytes, format=img_format, quality=80)
self.image = InMemoryUploadedFile(
img_bytes,
'ImageField',
img_name % 'full',
self.image.file.content_type,
img.size,
self.image.file.charset
)
# Create thumbnail from image
thumb.thumbnail(thumb_size, Image.ANTIALIAS)
thumb.save(thumb_bytes, format=img_format, quality=80)
self.thumbnail = InMemoryUploadedFile(
thumb_bytes,
'ImageField',
img_name % 'thumbnail',
self.image.file.content_type,
img.size,
self.image.file.charset
)
thumb.close()
img.close()
except:
raise Exception('Unable to correct image size')
def __str__(self):
return f'{self.id} - {self.item.name} - {self.id}'