mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #31701 -- Made FileDescriptor subclass DeferredAttribute.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							dd5aa8cb5f
						
					
				
				
					commit
					a93425a37f
				
			| @@ -8,6 +8,7 @@ from django.core.files.images import ImageFile | ||||
| from django.core.files.storage import Storage, default_storage | ||||
| from django.db.models import signals | ||||
| from django.db.models.fields import Field | ||||
| from django.db.models.query_utils import DeferredAttribute | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
|  | ||||
|  | ||||
| @@ -140,7 +141,7 @@ class FieldFile(File): | ||||
|         self.storage = self.field.storage | ||||
|  | ||||
|  | ||||
| class FileDescriptor: | ||||
| class FileDescriptor(DeferredAttribute): | ||||
|     """ | ||||
|     The descriptor for the file attribute on the model instance. Return a | ||||
|     FieldFile when accessed so you can write code like:: | ||||
| @@ -154,9 +155,6 @@ class FileDescriptor: | ||||
|         >>> with open('/path/to/hello.world') as f: | ||||
|         ...     instance.file = File(f) | ||||
|     """ | ||||
|     def __init__(self, field): | ||||
|         self.field = field | ||||
|  | ||||
|     def __get__(self, instance, cls=None): | ||||
|         if instance is None: | ||||
|             return self | ||||
| @@ -173,9 +171,7 @@ class FileDescriptor: | ||||
|  | ||||
|         # The instance dict contains whatever was originally assigned | ||||
|         # in __set__. | ||||
|         if self.field.name not in instance.__dict__: | ||||
|             instance.refresh_from_db(fields=[self.field.name]) | ||||
|         file = instance.__dict__[self.field.name] | ||||
|         file = super().__get__(instance, cls) | ||||
|  | ||||
|         # If this value is a string (instance.file = "path/to/file") or None | ||||
|         # then we simply wrap it with the appropriate attribute class according | ||||
| @@ -186,7 +182,7 @@ class FileDescriptor: | ||||
|         # handle None. | ||||
|         if isinstance(file, str) or file is None: | ||||
|             attr = self.field.attr_class(instance, self.field, file) | ||||
|             instance.__dict__[self.field.name] = attr | ||||
|             instance.__dict__[self.field.attname] = attr | ||||
|  | ||||
|         # Other types of files may be assigned as well, but they need to have | ||||
|         # the FieldFile interface added to them. Thus, we wrap any other type of | ||||
| @@ -196,7 +192,7 @@ class FileDescriptor: | ||||
|             file_copy = self.field.attr_class(instance, self.field, file.name) | ||||
|             file_copy.file = file | ||||
|             file_copy._committed = False | ||||
|             instance.__dict__[self.field.name] = file_copy | ||||
|             instance.__dict__[self.field.attname] = file_copy | ||||
|  | ||||
|         # Finally, because of the (some would say boneheaded) way pickle works, | ||||
|         # the underlying FieldFile might not actually itself have an associated | ||||
| @@ -211,10 +207,10 @@ class FileDescriptor: | ||||
|             file.instance = instance | ||||
|  | ||||
|         # That was fun, wasn't it? | ||||
|         return instance.__dict__[self.field.name] | ||||
|         return instance.__dict__[self.field.attname] | ||||
|  | ||||
|     def __set__(self, instance, value): | ||||
|         instance.__dict__[self.field.name] = value | ||||
|         instance.__dict__[self.field.attname] = value | ||||
|  | ||||
|  | ||||
| class FileField(Field): | ||||
| @@ -303,10 +299,6 @@ class FileField(Field): | ||||
|             file.save(file.name, file.file, save=False) | ||||
|         return file | ||||
|  | ||||
|     def contribute_to_class(self, cls, name, **kwargs): | ||||
|         super().contribute_to_class(cls, name, **kwargs) | ||||
|         setattr(cls, self.name, self.descriptor_class(self)) | ||||
|  | ||||
|     def generate_filename(self, instance, filename): | ||||
|         """ | ||||
|         Apply (if callable) or prepend (if a string) upload_to to the filename, | ||||
| @@ -345,7 +337,7 @@ class ImageFileDescriptor(FileDescriptor): | ||||
|     assigning the width/height to the width_field/height_field, if appropriate. | ||||
|     """ | ||||
|     def __set__(self, instance, value): | ||||
|         previous_file = instance.__dict__.get(self.field.name) | ||||
|         previous_file = instance.__dict__.get(self.field.attname) | ||||
|         super().__set__(instance, value) | ||||
|  | ||||
|         # To prevent recalculating image dimensions when we are instantiating | ||||
|   | ||||
		Reference in New Issue
	
	Block a user