2016-12-29 57 views
0

我有這個模型複製構造器basemodel:使用Image.copy遞歸deepcopy的

class BaseModel(models.Model): 
    def __init__(self, *args, **kwargs): 
     super().__init__(*args, **kwargs) 
     self.original = copy.deepcopy(self 

我的問題是,一些車型有ImageField的,當我嘗試複製,我得到AttributeError的。我發現這個錯誤的解決方案here,說「使用image.copy(),而不是copy.deepcopy()。

我可以實現image.copy()在遞歸deepcopy當字段是圖像?

非常感謝

編輯:這是跟蹤:

Traceback: 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/PIL/ImageFile.py" in load 

139. read = self.load_read 

During handling of the above exception ('JpegImageFile' object has no attribute 'load_read'), another exception occurred: 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner 

39. response = get_response(request) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response 

187. response = self.process_exception_by_middleware(e, request) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response 

185. response = wrapped_callback(request, *callback_args, **callback_kwargs) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/django/views/decorators/csrf.py" in wrapped_view 

58. return view_func(*args, **kwargs) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/django/views/generic/base.py" in view 

68. return self.dispatch(request, *args, **kwargs) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/rest_framework/views.py" in dispatch 

477. response = self.handle_exception(exc) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/rest_framework/views.py" in handle_exception 

437. self.raise_uncaught_exception(exc) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/rest_framework/views.py" in dispatch 

474. response = handler(request, *args, **kwargs) 

File "/home/imontilla/PycharmProjects/api/apps/chats/api.py" in put 

107. return self.response_or_errors(serializer, respond_with=serializers.ChatMessageOutputSerializer) 

File "/home/imontilla/PycharmProjects/api/apps/core/generics.py" in response_or_errors 

31. instance = serializer.save(**kwargs) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/rest_framework/serializers.py" in save 

214. self.instance = self.create(validated_data) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/rest_framework/serializers.py" in create 

902. instance = ModelClass.objects.create(**validated_data) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/django/db/models/manager.py" in manager_method 

85. return getattr(self.get_queryset(), name)(*args, **kwargs) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/django/db/models/query.py" in create 

397. obj = self.model(**kwargs) 

File "/home/imontilla/PycharmProjects/api/apps/core/models.py" in __init__ 

22. self.original_instance = copy.deepcopy(self) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/copy.py" in deepcopy 

182. y = _reconstruct(x, rv, 1, memo) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/copy.py" in _reconstruct 

297. state = deepcopy(state, memo) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/copy.py" in deepcopy 

155. y = copier(x, memo) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/copy.py" in _deepcopy_dict 

243. y[deepcopy(key, memo)] = deepcopy(value, memo) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/copy.py" in deepcopy 

182. y = _reconstruct(x, rv, 1, memo) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/copy.py" in _reconstruct 

297. state = deepcopy(state, memo) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/copy.py" in deepcopy 

155. y = copier(x, memo) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/copy.py" in _deepcopy_dict 

243. y[deepcopy(key, memo)] = deepcopy(value, memo) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/copy.py" in deepcopy 

174. rv = reductor(4) 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/PIL/Image.py" in __getstate__ 

639. self.getpalette(), 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/PIL/Image.py" in getpalette 

1196. self.load() 

File "/home/imontilla/.virtualenvs/petycash-django/lib/python3.5/site-packages/PIL/ImageFile.py" in load 

143. read = self.fp.read 

Exception Type: AttributeError at /chats/6fbd9f3e87f945b99969b2c53e35eb66/messages/image/ 

Exception Value: 'NoneType' object has no attribute 'read' 
+0

你似乎混淆PIL圖像對象和Django'ImageField' –

+0

的錯誤是一樣的,其他的問題,我得到它在PIL/ImageFile.py:143閱讀= read.fp.read 。我不知道它是如何工作在內部Django的圖像領域,但propably它有作爲ImageFile實例的價值(ö也許我有其他模型ImageFile,我不知道我的項目中的所有模型)。 –

回答

0

我認爲最好的方法是一種方法copy添加到您的類中的這個方法,你可以控制的方式複製具有不同類型的對象。

class BaseModel(models.Model): 
    def __init__(self, *args, **kwargs): 
     super().__init__(*args, **kwargs) 
     self.original = self.copy() 

    def copy(self): 
     clone = copy.copy(self) # to copy __dict__ only 
     for key, value in clone.__dict__.items(): 
      if isinstance(value, BaseModel): 
       clone.__dict__[key] = value.copy() # recoursively 
      elif isinstance(value, Image): 
       clone.__dict__[key] = value.copy() 
      else: 
       clone.__dict__[key] = copy.deepcopy(value) 
     return clone 
+0

我需要複製值(不是引用)。我害怕使用copy.copy而不是copy.deepcopy。你確定這個解決方案複製了這些值嗎? –

+0

@IvanMontilla是的,我確定。在我的解決方案中,首先我只複製'__dict__',它由'copy.copy'完成。但之後,在for循環中,我根據其類型對每個值進行深度複製。 – Fomalhaut

+0

不工作,我認爲__dict__只能訪問實例的屬性,而不能訪問屬性的屬性。我解決了將ImageFileField更改爲FileField的問題,在這種情況下,FileField可以提供相同的操作。謝謝。 –