How it Works

GenericForeignFileField

Nearly all of the functionality in cropduster comes from its django model field, CropDusterField. A great deal of functionality, in turn, comes from the GenericForeignFileField in the package django-generic-plus. Put in simplest terms, django-generic-plus allows one to create django model fields that are a hybrid of a FileField and a reverse generic foreign key (similar to Django’s GenericRelation, except that the relationship is one-to-one rather than one-to-many). In some respects these fields act the same as a FileField (or, in the case of django-cropduster, an ImageField), and when they are accessed from a model they have the same API as a FieldFile. But, as part of their hybrid status, GenericForeignFileField fields also have functionality that allows relating a file to one or more fields in another model. In the case of django-cropduster, this model is cropduster.models.Image. An example might be edifying. Let’s begin with a simple model:

class Author(models.Model):
    name = models.CharField(max_length=255)
    headshot = CropDusterField(upload_to='img/authors', sizes=[Size("main")])

Assuming that we are dealing with an Author created in the Django admin, one would access the cropduster.Image instance using Author.headshot.related_object:

>>> author = Author.objects.get(pk=1)
>>> author.headshot
<CropDusterImageFieldFile: img/authors/mark-twain/original.jpg>
>>> author.headshot.path
"/www/project/media/img/authors/mark-twain/original.jpg"
>>> author.headshot.related_object
<Image: /media/img/authors/mark-twain/original.jpg>

The accessor at author.headshot.related_object is basically equivalent to running the following python code:

try:
    Image.objects.get(
        content_type=ContentType.objects.get_for_model(author),
        object_id=author.pk,
        field_identifier='')
except Image.DoesNotExist:
    return None

Creating an instance with a cropduster field outside of the Django admin requires the creation of an instance of cropduster.Image and a call to the generate_thumbs method:

from cropduster.models import Image

author = Author.objects.create(
    name="Mark Twain",
    headshot="img/authors/mark-twain/original.jpg")
author.save()

image = Image.objects.create(
    content_object=author,
    field_identifier='',
    image=author.headshot.name)

author.headshot.generate_thumbs()

Note

Cropduster requires that images follow a certain path structure. Let’s continue with the example above. Using the built-in Django ImageField, uploading the file mark-twain.jpg would place it in img/authors/mark-twain.jpg (relative to the MEDIA_ROOT). Because cropduster needs a place to put its thumbnails, it puts all images in a directory and saves the original image to original.%(ext)s in that folder. So the cropduster-compatible path for img/authors/mark-twain.jpg would be img/authors/mark-twain/original.jpg. When a file is uploaded via the Django admin this file structure is created seamlessly, but it must be kept in mind when importing an image into cropduster from outside of the admin.