|
1 | 1 | from datetime import timedelta
|
2 | 2 | from mongoengine.base import BaseField
|
3 | 3 |
|
| 4 | +import os |
| 5 | +import datetime |
| 6 | + |
| 7 | +from mongoengine.python_support import str_types |
| 8 | +from django.db.models.fields.files import FieldFile |
| 9 | +from django.core.files.base import File |
| 10 | +from django.core.files.storage import default_storage |
| 11 | + |
| 12 | +from mongoengine.connection import get_db, DEFAULT_CONNECTION_NAME |
| 13 | +from django.utils.encoding import force_text |
| 14 | + |
| 15 | + |
4 | 16 | class TimedeltaField(BaseField):
|
5 | 17 | """A timedelta field.
|
6 | 18 |
|
@@ -38,3 +50,83 @@ def total_seconds(value):
|
38 | 50 | return (value.days * 24 * 3600) + \
|
39 | 51 | (value.seconds) + \
|
40 | 52 | (value.microseconds / 1000000.0)
|
| 53 | + |
| 54 | + |
| 55 | +class LocalStorageFileField(BaseField): |
| 56 | + |
| 57 | + proxy_class = FieldFile |
| 58 | + |
| 59 | + def __init__(self, |
| 60 | + db_alias=DEFAULT_CONNECTION_NAME, |
| 61 | + name=None, |
| 62 | + upload_to='', |
| 63 | + storage=None, |
| 64 | + **kwargs): |
| 65 | + |
| 66 | + self.db_alias = db_alias |
| 67 | + self.storage = storage or default_storage |
| 68 | + self.upload_to = upload_to |
| 69 | + |
| 70 | + if callable(upload_to): |
| 71 | + self.generate_filename = upload_to |
| 72 | + |
| 73 | + super(DJFileField, self).__init__(**kwargs) |
| 74 | + |
| 75 | + |
| 76 | + def __get__(self, instance, owner): |
| 77 | + # Lots of information on whats going on here can be found |
| 78 | + # on Django's FieldFile implementation, go over to GitHub to |
| 79 | + # read it. |
| 80 | + file = instance._data.get(self.name) |
| 81 | + |
| 82 | + if isinstance(file, str_types) or file is None: |
| 83 | + attr = self.proxy_class(instance, self, file) |
| 84 | + instance._data[self.name] = attr |
| 85 | + |
| 86 | + elif isinstance(file, File) and not isinstance(file, FieldFile): |
| 87 | + file_copy = self.proxy_class(instance, self, file.name) |
| 88 | + file_copy.file = file |
| 89 | + file_copy._committed = False |
| 90 | + instance._data[self.name] = file_copy |
| 91 | + |
| 92 | + elif isinstance(file, FieldFile) and not hasattr(file, 'field'): |
| 93 | + file.instance = instance |
| 94 | + file.field = self |
| 95 | + file.storage = self.storage |
| 96 | + |
| 97 | + return instance._data[self.name] |
| 98 | + |
| 99 | + |
| 100 | + def __set__(self, instance, value): |
| 101 | + instance._data[self.name] = value |
| 102 | + |
| 103 | + |
| 104 | + def get_directory_name(self): |
| 105 | + return os.path.normpath(force_text(datetime.datetime.now().strftime(self.upload_to))) |
| 106 | + |
| 107 | + |
| 108 | + def get_filename(self, filename): |
| 109 | + return os.path.normpath(self.storage.get_valid_name(os.path.basename(filename))) |
| 110 | + |
| 111 | + |
| 112 | + def generate_filename(self, instance, filename): |
| 113 | + return os.path.join(self.get_directory_name(), self.get_filename(filename)) |
| 114 | + |
| 115 | + |
| 116 | + def to_mongo(self, value): |
| 117 | + # Store the path in MongoDB |
| 118 | + # I also used this bit to actually save the file to disk. |
| 119 | + # The value I'm getting here is a FileFiled and it all looks ok. |
| 120 | + |
| 121 | + if not value._committed and value is not None: |
| 122 | + value.save(value.name, value) |
| 123 | + return value.path |
| 124 | + |
| 125 | + return value.name |
| 126 | + |
| 127 | + |
| 128 | + def to_python(self, value): |
| 129 | + eu = self |
| 130 | + return eu.proxy_class(eu.owner_document, eu, value) |
| 131 | + |
| 132 | + |
0 commit comments