#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2014 dhilipsiva <dhilipsiva@gmail.com>
#
# Distributed under terms of the MIT license.

"""
I do media file upload to S3 very often in various projects.
So I thought I ll have a script always ready.
"""

# Settings


AWS_SECRET_KEY = 'secret_key'
AWS_ACCESS_KEY = 'access_key'
AWS_BUCKET = 'bucket'
AWS_BASE_URL = 'https://*.cloudfront.net'
AWS_EXPIRY_TIME = 60 * 30  # Half an hour
AWS_FORCE_HTTP = True
UPLOAD_TO_S3 = False
MEDIA_URL = ""

"""
A Wrapper around boto to upload to s3
"""
import os
from boto.s3.connection import S3Connection
from boto.s3.key import Key

from django.conf import settings

if settings.UPLOAD_TO_S3:
    conn = S3Connection(settings.AWS_ACCESS_KEY, settings.AWS_SECRET_KEY)
    bucket = conn.get_bucket(settings.AWS_BUCKET)


def key_for_file(file):
    """
    `key_for_file` generates an s3 key for the given file.
    """
    return '/files/' + file._file.path.split('media/')[1]


def upload(file):
    """
    This guy uploads the file from the given directory
    """
    k = Key(bucket)
    k.key = key_for_file(file)
    k.set_contents_from_filename(file._file.path)


def temp_url(file):
    """
    Function to generate a temproary AWS URL for fiven file object
    """
    k = Key(bucket)
    k.key = key_for_file(file)
    return k.generate_url(
        expires_in=settings.AWS_EXPIRY_TIME,
        force_http=settings.AWS_FORCE_HTTP)


def process_file(file):
    """
    Upload the file to s3
    """
    if not settings.UPLOAD_TO_S3:
        return file
    try:
        if not file.uploaded:
            upload(file)
            os.remove(file._file.path)
            file.uploaded = True
            file.save()
    except Exception:
        print "unable to upload file to s3"
    finally:
        return file

"""
Model configuration
"""
from django.db import models

AWS_PREFIX = AWS_BASE_URL + MEDIA_URL


class Model:

    uploaded = models.BooleanField(default=False)

    def get_url(self, size=""):
        if self.uploaded:
            filename, extension = self._file.name.rsplit('.', 1)
            path = AWS_PREFIX + filename
        else:
            filename, extension = self._file.url.rsplit('.', 1)
            path = filename
        if size:
            path += "-" + size
        path += "." + extension
        return path

    @property
    def url(self):
        if self.uploaded:
            return temp_url(self)
        return self._file.url


"""
Management command to process existing files.
"""
from django.core.management.base import BaseCommand
from files.models import File

files = File.objects.filter(uploaded=False)


class Command(BaseCommand):
    help = 'Re-process all the files from s3'

    def handle(self, *args, **options):
        for file in files:
            file = process_file(file)

@@ -478,16 +478,172 @@
  = True%0A
+%22%22%22%0A%60UPLOAD_TO_S3%60 flag to tell if the files are needed to be uploaded to S3.%0ADuring development, set this to %60False%60. And set to %60True%60 in production.%0A%22%22%22%0A
 UPLOAD_T
@@ -1993,16 +1993,43 @@
 le%0A%0A%22%22%22%0A
+File: myapp/models.py%0AFile 
 Model co
@@ -2131,418 +2131,464 @@
 el:%0A
-%0A    uploaded = models.BooleanField(default=False)%0A%0A    def get_url(self, size=%22%22):%0A        if self.uploaded:%0A            filename, extension = self._file.name.rsplit('.', 1)%0A            path = AWS_PREFIX + filename%0A        else:%0A            filename, extension = self._file.url.rsplit('.', 1)%0A            path = filename%0A        if size:%0A            path += %22-%22 + size%0A        path += %22.%22 + extension%0A
+    %22%22%22%0A    This is the djngo model that you have file associated with.%0A    Here I am assuming that %60_file%60 is your FileField%0A    %22%22%22%0A%0A    %22%22%22%0A    Add a %60uploaded%60 BooleanField to mark files if they%0A    are uploaded to S3 or not%0A    %22%22%22%0A    uploaded = models.BooleanField(default=False)%0A%0A    @property%0A    def get_url(self):%0A        if self.uploaded:%0A            %22%22%22%0A            If the file is uploaded, return the temproary URL.%0A            %22%22%22%0A  
         
 retu
@@ -2587,43 +2587,22 @@
     
+  
 return 
-path%0A%0A    @property%0A    def 
+temp_
 url(
@@ -2598,33 +2598,32 @@
 n temp_url(self)
-:
 %0A        if self
@@ -2619,59 +2619,80 @@
     
-if self.uploaded:%0A            return temp_url(self)
+%22%22%22%0A        Else the file URL or anything that is equivalent%0A        %22%22%22
 %0A   

Update on the script #4