bgneal@695
|
1 """Forms for the user_photos application."""
|
bgneal@700
|
2 import datetime
|
bgneal@700
|
3
|
bgneal@695
|
4 from django import forms
|
bgneal@697
|
5 from django.conf import settings
|
bgneal@695
|
6
|
bgneal@700
|
7 from core.s3 import S3Bucket
|
bgneal@700
|
8 from core.image_uploader import upload
|
bgneal@701
|
9 from core.services import get_redis_connection
|
bgneal@696
|
10 from user_photos.models import Photo
|
bgneal@696
|
11
|
bgneal@695
|
12
|
bgneal@701
|
13 def rate_limit(key, limit, seconds):
|
bgneal@701
|
14 """Use Redis to do a rate limit check. Returns True if the limit is violated
|
bgneal@701
|
15 and False otherwise.
|
bgneal@701
|
16
|
bgneal@701
|
17 key - the key to check in Redis
|
bgneal@701
|
18 limit - the rate limit maximum value
|
bgneal@701
|
19 seconds - the rate limit period in seconds
|
bgneal@701
|
20
|
bgneal@701
|
21 """
|
bgneal@701
|
22 conn = get_redis_connection()
|
bgneal@701
|
23 val = conn.incr(key)
|
bgneal@701
|
24 if val == 1:
|
bgneal@701
|
25 conn.expire(key, seconds)
|
bgneal@701
|
26 return val > limit
|
bgneal@701
|
27
|
bgneal@701
|
28
|
bgneal@695
|
29 class UploadForm(forms.Form):
|
bgneal@695
|
30 image_file = forms.ImageField()
|
bgneal@696
|
31
|
bgneal@696
|
32 def __init__(self, *args, **kwargs):
|
bgneal@696
|
33 self.user = kwargs.pop('user')
|
bgneal@696
|
34 super(UploadForm, self).__init__(*args, **kwargs)
|
bgneal@696
|
35
|
bgneal@701
|
36 def clean(self):
|
bgneal@701
|
37 cleaned_data = super(UploadForm, self).clean()
|
bgneal@701
|
38
|
bgneal@701
|
39 # rate limit uploads
|
bgneal@701
|
40 key = 'user_photos:counts:' + self.user.username
|
bgneal@701
|
41 limit = settings.USER_PHOTOS_RATE_LIMIT
|
bgneal@701
|
42 if rate_limit(key, *limit):
|
bgneal@701
|
43 raise forms.ValidationError("You've exceeded your upload quota. "
|
bgneal@701
|
44 "Please try again later.")
|
bgneal@701
|
45
|
bgneal@701
|
46 return cleaned_data
|
bgneal@701
|
47
|
bgneal@696
|
48 def save(self):
|
bgneal@696
|
49 """Processes the image and creates a new Photo object, which is saved to
|
bgneal@696
|
50 the database. The new Photo instance is returned.
|
bgneal@696
|
51
|
bgneal@696
|
52 This function should only be called if is_valid() returns True.
|
bgneal@696
|
53
|
bgneal@696
|
54 """
|
bgneal@700
|
55 bucket = S3Bucket(access_key=settings.USER_PHOTOS_ACCESS_KEY,
|
bgneal@700
|
56 secret_key=settings.USER_PHOTOS_SECRET_KEY,
|
bgneal@700
|
57 base_url=settings.USER_PHOTOS_BASE_URL,
|
bgneal@700
|
58 bucket_name=settings.USER_PHOTOS_BUCKET)
|
bgneal@700
|
59
|
bgneal@700
|
60 now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
bgneal@700
|
61 metadata = {'user': self.user.username, 'date': now}
|
bgneal@700
|
62
|
bgneal@700
|
63 url, thumb_url = upload(fp=self.cleaned_data['image_file'],
|
bgneal@700
|
64 bucket=bucket,
|
bgneal@700
|
65 metadata=metadata,
|
bgneal@700
|
66 new_size=settings.USER_PHOTOS_MAX_SIZE,
|
bgneal@700
|
67 thumb_size=settings.USER_PHOTOS_THUMB_SIZE)
|
bgneal@700
|
68
|
bgneal@696
|
69 photo = Photo(user=self.user, url=url, thumb_url=thumb_url)
|
bgneal@696
|
70 photo.save()
|
bgneal@696
|
71 return photo
|