This repository has been archived on 2025-05-04. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
s2forums/djangobb_forum/fields.py

123 lines
4.2 KiB
Python
Raw Permalink Normal View History

2009-01-05 14:30:08 +02:00
"""
Details about AutoOneToOneField:
http://softwaremaniacs.org/blog/2007/03/07/auto-one-to-one-field/
"""
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
import random
from hashlib import sha1
2009-01-05 14:30:08 +02:00
from django.db.models import OneToOneField
from django.db.models.fields.related import SingleRelatedObjectDescriptor
from django.db import models, IntegrityError
2009-01-05 14:30:08 +02:00
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.serializers.json import DjangoJSONEncoder
from django.utils import simplejson as json
from django.conf import settings
2009-01-05 14:30:08 +02:00
import logging
logger = logging.getLogger(__name__)
2009-01-05 14:30:08 +02:00
class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
def __get__(self, instance, instance_type=None):
try:
return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
except self.related.model.DoesNotExist:
obj = self.related.model(**{self.related.field.name: instance})
try:
obj.save()
except IntegrityError:
# Sometimes this happens, try again
try:
return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
except self.related.model.DoesNotExist:
# Doesn't exist but already exists, what the heck.
2014-12-01 15:05:29 -05:00
# logger.warn("Integrity error encountered after DoesNotExist?", extra={'stack': True})
pass
2009-01-05 14:30:08 +02:00
return obj
class AutoOneToOneField(OneToOneField):
"""
OneToOneField creates dependent object on first request from parent object
if dependent oject has not created yet.
"""
def contribute_to_related_class(self, cls, related):
setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))
#if not cls._meta.one_to_one_field:
# cls._meta.one_to_one_field = self
class ExtendedImageField(models.ImageField):
"""
Extended ImageField that can resize image before saving it.
"""
def __init__(self, *args, **kwargs):
self.width = kwargs.pop('width', None)
self.height = kwargs.pop('height', None)
super(ExtendedImageField, self).__init__(*args, **kwargs)
def save_form_data(self, instance, data):
if data and self.width and self.height:
content = self.resize_image(data.read(), width=self.width, height=self.height)
salt = sha1(str(random.random())).hexdigest()[:5]
fname = sha1(salt + settings.SECRET_KEY).hexdigest() + '.png'
data = SimpleUploadedFile(fname, content, content_type='image/png')
2009-01-05 14:30:08 +02:00
super(ExtendedImageField, self).save_form_data(instance, data)
def resize_image(self, rawdata, width, height):
"""
Resize image to fit it into (width, height) box.
"""
try:
import Image
except ImportError:
from PIL import Image
image = Image.open(StringIO(rawdata))
oldw, oldh = image.size
if oldw >= oldh:
x = int(round((oldw - oldh) / 2.0))
image = image.crop((x, 0, (x + oldh) - 1, oldh - 1))
else:
y = int(round((oldh - oldw) / 2.0))
image = image.crop((0, y, oldw - 1, (y + oldw) - 1))
image = image.resize((width, height), resample=Image.ANTIALIAS)
2009-01-05 14:30:08 +02:00
string = StringIO()
image.save(string, format='PNG')
return string.getvalue()
class JSONField(models.TextField):
"""
JSONField is a generic textfield that neatly serializes/unserializes
JSON objects seamlessly.
Django snippet #1478
"""
__metaclass__ = models.SubfieldBase
def to_python(self, value):
if value == "":
return None
try:
if isinstance(value, basestring):
return json.loads(value)
except ValueError:
pass
return value
def get_prep_value(self, value):
if value == "":
return None
if isinstance(value, dict):
value = json.dumps(value, cls=DjangoJSONEncoder)
return super(JSONField, self).get_prep_value(value)