admin.py: class ImageGalleryAdminForm(forms.ModelForm): archive = forms.FileField(label="ZIP archive", required=False) class Meta: model = get_model('uploads', 'ImageGallery') models.py: class Image(BaseFileModel): file = models.ImageField(upload_to=get_image_path) gallery = models.ForeignKey(ImageGallery, default=get_default_gallery)How would you write test cases to verify that you could actually upload a ZIP archive? Well, here's how the Django documentation describes things:
http://docs.djangoproject.com/en/dev/topics/testing/ Submitting files is a special case. To POST a file, you need only provide the file field name as a key, and a file handle to the file you wish to upload as a value. For example: >>> c = Client() >>> f = open('wishlist.doc') >>> c.post('/customers/wishes/', {'name': 'fred', 'attachment': f}) >>> f.close() (The name attachment here is not relevant; use whatever name your file-processing code expects.)
Why can you pass a file handler inside a dictionary? You have to dig into the Django django.test.client code to understand why it's even possible.
django.test.client: def post(self, path, data={}, content_type=MULTIPART_CONTENT, follow=False, **extra): """ Requests a response from the server using POST. """ if content_type is MULTIPART_CONTENT: post_data = encode_multipart(BOUNDARY, data)Notice that content_type is by default set to MULTIPART_CONTENT. It invokes the function encode_multipart(), which has these particular important lines:
def encode_multipart(boundary, data): """ Encodes multipart POST data from a dictionary of form values. The key will be used as the form data name; the value will be transmitted as content. If the value is a file, the contents of the file will be sent as an application/octet-stream; otherwise, str(value) will be sent. """ . . . # Not by any means perfect, but good enough for our purposes. is_file = lambda thing: hasattr(thing, "read") and callable(thing.read) for (key, value) in data.items(): if is_file(value): lines.extend(encode_file(boundary, key, value))Django creates a lambda function that determines if the file handler you pass-in has a read() function. If it does, it will consider the dictionary value as a file. It will then invoke encode_file() and create a MIME-encoded submission.
Try it out for yourself at the Python interpreter:
python manage.py shell
>>> from django.test.client import BOUNDARY >>> f = open("/tmp/dragon.zip") >>> django.test.client.encode_multipart(BOUNDARY, {'d' : f}) You should start to see something like the following: '--BoUnDaRyStRiNg\r\nContent-Disposition: form-data; name="d"; filename="dragon.zip"\r\nContent-Type: application/octet-stream\r\n\r\nPK\x03\x04\x14\x00\x00\x00\x08\x00\'G\xbc<\xcb\x99\x05\xbb:\xaa\x00\x00\xb8\xaa\x00\x00\n\x00\x00\x00dragon.jpg\
No comments:
Post a Comment