Code

Ticket #4165: 5126_file_upload_contrib_app.diff

File 5126_file_upload_contrib_app.diff, 6.0 KB (added by Michael Axiak <axiak@…>, 7 years ago)

Wrote some example MiddleWare and such. Using caching makes a lot of sense for upload progress.

Line 
1Index: django/contrib/uploadprogress/__init__.py
2===================================================================
3Index: django/contrib/uploadprogress/models.py
4===================================================================
5--- django/contrib/uploadprogress/models.py     (revision 0)
6+++ django/contrib/uploadprogress/models.py     (revision 0)
7@@ -0,0 +1,73 @@
8+"""
9+Models file for a simple file upload progress application.
10+This cause the file progress to be stored in the database.
11+To activate:
12+1) Add 'django.contrib.uploadprogress.middleware.FileProgressDB'
13+   to your MIDDLEWARE_CLASSES setting.
14+2) Add 'django.contrib.uploadprogress' to your INSTALLED_APPS.
15+
16+"""
17+
18+from django.db import models
19+import pickle
20+import datetime
21+
22+class FileProgress(models.Model):
23+
24+    remote_addr = models.CharField(maxlength=64)
25+    progress_id = models.CharField(maxlength=32)
26+    progress_text = models.TextField(editable = False)
27+    last_ts     = models.DateTimeField()
28+
29+    class Meta:
30+        verbose_name_plural = 'File Progresses'
31+        unique_together = (('remote_addr',
32+                           'progress_id',
33+                           ),
34+                           )
35+
36+    class Admin:
37+        pass
38+
39+    def __str__(self):
40+        return 'File Progress for "%s" and IP "%s".' % (self.progress_id, self.remote_addr)
41+
42+    def _get_dict(self):
43+        """
44+        Returns a dictionary object.
45+        """
46+        if hasattr(self, '_progress_dict'):
47+            return self._progress_dict
48+       
49+        if not self.progress_text:
50+            self._progress_dict = {}
51+            return {}
52+
53+        try:
54+            self._progress_dict = pickle.loads(self.progress_text)
55+        except:
56+            self._progress_dict = {}
57+
58+        return self._progress_dict
59+
60+    def _set_dict(self, dict):
61+        """
62+        Sets a dictionary object.
63+        """
64+        self._progress_dict = dict
65+
66+    progress = property(_get_dict, _set_dict)
67+
68+    def save(self, *args, **kwargs):
69+        """
70+        Pickles the dictionary representation
71+        of the progress.
72+        """
73+        try:
74+            self.progress_text = pickle.dumps(self.progress)
75+        except:
76+            pass
77+
78+        self.last_ts = datetime.datetime.now()
79+
80+        return super(FileProgress, self).save(*args, **kwargs)
81Index: django/contrib/uploadprogress/middleware/uploadcache.py
82===================================================================
83--- django/contrib/uploadprogress/middleware/uploadcache.py     (revision 0)
84+++ django/contrib/uploadprogress/middleware/uploadcache.py     (revision 0)
85@@ -0,0 +1,53 @@
86+"""
87+Example middleware to process uploads using the cache framework.
88+"""
89+from django.core.cache import cache
90+from django.conf import settings
91+
92+UPLOAD_CACHE_PREFIX = getattr(settings, 'UPLOAD_CACHE_PREFIX', 'UPLOAD_PROGRESS_')
93+
94+class FileProgressStore(object):
95+
96+    def _get_key(self, request):
97+        """
98+        Returns the cache prefix for any cache key.
99+        Uses the IP Address as well as the randomly generated uuid.
100+        """
101+       
102+        if hasattr(self, '_cache_key'):
103+            return self._cache_key
104+       
105+        self._cache_key = '%s__%s__%s' % \
106+                           (UPLOAD_CACHE_PREFIX,
107+                            request.META['REMOTE_ADDR'],
108+                            request.META['UPLOAD_PROGRESS_ID'],)
109+
110+        return self._cache_key
111+
112+    def __init__(self, UploadException):
113+        self.uploadException = UploadException
114+
115+    def __get__(self, request, HttpRequest):
116+        return cache.get(self._get_key(request), {})
117+
118+    def __set__(self, request, new_val):
119+        received_size = total_size = -1
120+        try:
121+            total_size = int(new_val['size'])
122+        except:
123+            pass
124+
125+        try:
126+            received_size = int(new_val['received'])
127+        except:
128+            pass
129+       
130+        cache.set(self._get_key(request), new_val)
131+
132+    def __delete__(self, request):
133+        cache.delete(self._get_key(request))
134+
135+class FileProgressCached(object):
136+
137+    def process_upload(self, UploadException):
138+        return FileProgressStore(UploadException)
139Index: django/contrib/uploadprogress/middleware/uploaddb.py
140===================================================================
141--- django/contrib/uploadprogress/middleware/uploaddb.py        (revision 0)
142+++ django/contrib/uploadprogress/middleware/uploaddb.py        (revision 0)
143@@ -0,0 +1,37 @@
144+"""
145+Example middleware to process uploads using a database model.
146+"""
147+from django.contrib.uploadprogress.models import FileProgress
148+from django.conf import settings
149+import pickle
150+
151+UPLOAD_CACHE_PREFIX = getattr(settings, 'UPLOAD_CACHE_PREFIX', 'UPLOAD_PROGRESS')
152+
153+class FileProgressDBStore(object):
154+
155+    def _get_db_row(self, request):
156+        if not hasattr(self, '_db_row'):
157+            self._db_row, created = FileProgress.objects.get_or_create(
158+                                                 remote_addr = request.META['REMOTE_ADDR'],
159+                                                 progress_id = request.META['UPLOAD_PROGRESS_ID'])
160+
161+        return self._db_row
162+
163+    def __init__(self, UploadException):
164+        self.uploadException = UploadException
165+
166+    def __get__(self, request, HttpRequest):
167+        return self._get_db_row(request).progress
168+
169+    def __set__(self, request, new_val):
170+        row = self._get_db_row(request)
171+        row.progress = new_val
172+        row.save()
173+
174+    def __delete__(self, request):
175+        self._get_db_row(request).delete()
176+
177+class FileProgressDB(object):
178+
179+    def process_upload(self, UploadException):
180+        return FileProgressDBStore(UploadException)
181Index: django/contrib/uploadprogress/middleware/__init__.py
182===================================================================
183--- django/contrib/uploadprogress/middleware/__init__.py        (revision 0)
184+++ django/contrib/uploadprogress/middleware/__init__.py        (revision 0)
185@@ -0,0 +1,3 @@
186+from django.contrib.uploadprogress.middleware.uploaddb import FileProgressDB
187+from django.contrib.uploadprogress.middleware.uploadcache import FileProgressCached
188+