2013-04-07 17 views
6

Mongoengine lưu trữ FileField và ImageField sang GridFS. Cách tiếp cận dễ nhất để nhân rộng chức năng của Trường Tệp/Hình ảnh gốc là gì?Mongoengine FileField được lưu vào đĩa?

EDIT:

Vì vậy, đây là lớp tôi có tại thời điểm này. Tôi có thể tải các tập tin và lưu chúng vào đĩa, Mongo giữ đường dẫn đến tập tin trong cơ sở dữ liệu.

Tôi rơi xuống trên "to_python" vì tôi tin rằng nó cần phải tạo một đối tượng của proxy_class nhưng tôi không thể thấy làm thế nào, nếu tất cả tôi nhận được là một đường dẫn đến tập tin (như giá trị được thông qua trong).

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

Đây có phải là câu hỏi thực sự không? Bạn có thể mở rộng trên những gì bạn muốn lĩnh vực để làm gì? – Ross

+0

Ross xóa một câu hỏi thực sự. Những gì tôi có nghĩa là: những gì bạn sẽ khuyên tôi đã làm, nếu tôi muốn có một lĩnh vực mới, mà về cơ bản hành động theo cùng một cách như FileField gốc ở Django. Sử dụng một đối tượng lưu trữ và mongo chỉ cho thông tin đường dẫn, vv – holografix

Trả lời

2

Tôi nghĩ rằng nó sẽ là một bổ sung tuyệt vời - có thể gọi là LocalFileField để làm cho nó khuôn khổ hơn bất khả tri và nếu bạn cung cấp kiểm tra và tài liệu nó sẽ làm cho một bổ sung tuyệt vời để https://github.com/MongoEngine/extras-mongoengine

Lý do duy nhất tôi không được bán khi có nó trong lõi - là nếu bạn đang chạy bản sao tệp sẽ vẫn chỉ được lưu trữ trên một nút.

+1

Cảm ơn bạn đã phản hồi Ross. Bạn sẽ giới thiệu loại bài kiểm tra nào? Bạn có thể cho tôi một số ví dụ? Tôi thực sự không đồng ý, tôi nghĩ rằng nó phải là một phần cốt lõi vì tôi không thể thấy một cách dễ dàng để tải lên hình ảnh liên kết với một Tài liệu mà sau đó có thể được sử dụng trên một mẫu và tôi tưởng tượng rất nhiều nhà phát triển muốn làm điều đó. Hoặc tôi thiếu một cái gì đó rõ ràng, tức là: làm thế nào để sử dụng MongoEngine.ImageField hiện tại trên một mẫu. Các tài liệu có thể gợi ý rằng thay vì sử dụng một hệ thống tập tin cục bộ, bạn sử dụng một cái gì đó giống như S3. – holografix