2013-04-07 21 views
6

Mongoengine przechowuje pliki FileField i ImageField na GridFS. Jakie jest najprostsze podejście do replikowania funkcjonalności oryginalnego pola pliku/obrazu?Mongoengine FileField zapisywanie na dysku?

EDIT:

Więc to jest klasa mam na miejscu w tej chwili. Jestem w stanie załadować pliki i zapisać je na dysku, Mongo przechowuje ścieżkę do pliku w bazie danych.

Upadam na "to_python", ponieważ uważam, że musi on utworzyć obiekt klasy proxy_, ale nie widzę, jak, jeśli wszystko, co dostaję, jest ścieżką do pliku (jak przekazywana jest wartość w).

import os 
import datetime 

from mongoengine.python_support import str_types 
from django.db.models.fields.files import FieldFile 
from django.core.files.base import File 
from django.core.files.storage import default_storage 
from mongoengine.base import BaseField 
from mongoengine.connection import get_db, DEFAULT_CONNECTION_NAME 
from django.utils.encoding import force_text 
#from django.utils.encoding import force_str 


class DJFileField(BaseField): 

    proxy_class = FieldFile 

    def __init__(self, 
       db_alias=DEFAULT_CONNECTION_NAME, 
       name=None, 
       upload_to='', 
       storage=None, 
       **kwargs): 

     self.db_alias = db_alias 
     self.storage = storage or default_storage 
     self.upload_to = upload_to 

     if callable(upload_to): 
      self.generate_filename = upload_to 

     super(DJFileField, self).__init__(**kwargs) 


    def __get__(self, instance, owner): 
     # Lots of information on whats going on here can be found 
     # on Django's FieldFile implementation, go over to GitHub to 
     # read it. 
     file = instance._data.get(self.name) 

     if isinstance(file, str_types) or file is None: 
      attr = self.proxy_class(instance, self, file) 
      instance._data[self.name] = attr 

     elif isinstance(file, File) and not isinstance(file, FieldFile): 
      file_copy = self.proxy_class(instance, self, file.name) 
      file_copy.file = file 
      file_copy._committed = False 
      instance._data[self.name] = file_copy 

     elif isinstance(file, FieldFile) and not hasattr(file, 'field'): 
      file.instance = instance 
      file.field = self 
      file.storage = self.storage 

     # That was fun, wasn't it? 
     return instance._data[self.name] 


    def __set__(self, instance, value): 
     instance._data[self.name] = value 

    # The 3 methods below get used by the FieldFile proxy_object 
    def get_directory_name(self): 
     return os.path.normpath(force_text(datetime.datetime.now().strftime(self.upload_to))) 

    def get_filename(self, filename): 
     return os.path.normpath(self.storage.get_valid_name(os.path.basename(filename))) 

    def generate_filename(self, instance, filename): 
     return os.path.join(self.get_directory_name(), self.get_filename(filename)) 


    def to_mongo(self, value): 
    # Store the path in MongoDB 
    # I also used this bit to actually save the file to disk. 
    # The value I'm getting here is a FileFiled and it all looks 
    # pretty good at this stage even though I'm not 100% sure 
    # of what's going on. 

     import ipdb; ipdb.set_trace() 

     if not value._committed and value is not None: 
      value.save(value.name, value) 
      return value.path 

     return value.path  


    def to_python(self, value): 
     # Now this is the real problem, value is the path that got saved 
     # in mongo. No idea how to return a FileField obj from here. 
     # self.instance and instance throw errors. 
+0

Czy to jest prawdziwe pytanie? Czy możesz rozwinąć to, co chcesz zrobić w terenie? – Ross

+0

Ross def prawdziwe pytanie. Chodzi mi o to, co byś mi poradził, gdybym chciał mieć nowe Pole, które zasadniczo działało w ten sam sposób, co oryginalny FileField w Django. Używanie obiektu pamięci masowej i mongo tylko do informacji o ścieżce itp. – holografix

Odpowiedz

2

myślę, że byłoby to dobry dodatek - może być nazywany LocalFileField aby uczynić go bardziej ram agnostykiem, a jeśli pod warunkiem, testy i dokumenty miałoby to wspaniały dodatek do https://github.com/MongoEngine/extras-mongoengine

Jedynym powodem jestem nie jest sprzedawany z rdzeniem - jeśli uruchamiasz replikę, plik będzie przechowywany tylko w jednym węźle.

+1

Dzięki za odpowiedź Ross. Jakiego rodzaju testy poleciłabym? Czy możesz podać mi jakieś przykłady? Z całym szacunkiem nie zgadzam się, myślę, że powinien on być częścią rdzenia, ponieważ nie widzę łatwego sposobu przesyłania obrazów powiązanych z dokumentem, które można następnie wykorzystać w szablonie i wyobrażam sobie, że wielu twórców chciałoby to zrobić. Czy też brakuje mi czegoś oczywistego, tj .: jak korzystać z obecnego MongoEngine.ImageField na szablonie. Dokumenty mogą sugerować, że zamiast używać lokalnego systemu plików, używasz czegoś takiego jak S3. – holografix

Powiązane problemy