2009-12-09 14 views
18

Widzę, że wiele osób z aplikacjami Django, które ładują obrazy, automatycznie zmienia rozmiar obrazów po ich przesłaniu. W niektórych przypadkach jest to dobre i dobre, ale nie chcę tego robić. Zamiast tego po prostu chcę zmusić użytkownika do przesłania pliku, który ma już odpowiedni rozmiar.Sprawdź poprawność rozmiaru obrazu w django admin

Chcę mieć ImageField, w którym zmuszam użytkownika do przesłania obrazu o wymiarach 100x200. Jeśli obraz, który przesyłają, nie ma dokładnie takiego rozmiaru, chcę, aby formularz administracyjny został zwrócony jako nieprawidłowy. Chciałbym również móc zrobić to samo dla proporcji. Chcę zmusić użytkownika do przesłania obrazu w formacie 16: 9 i odrzucić wszelkie przesyłanie, które nie jest zgodne.

Już wiem, jak uzyskać szerokość i wysokość obrazu, ale nie mogę tego zrobić po stronie serwera, dopóki obraz nie jest już przesłany, a formularz został pomyślnie przesłany. Jak mogę to sprawdzić wcześniej, jeśli to możliwe?

Odpowiedz

45

Właściwe miejsce do tego jest podczas sprawdzania formularza.
Szybki przykład (będziemy edytować/zintegrować z więcej informacji później):

from django.core.files.images import get_image_dimensions 
from django.contrib import admin 
from django import forms 

class myForm(forms.ModelForm): 
    class Meta: 
     model = myModel 
    def clean_picture(self): 
     picture = self.cleaned_data.get("picture") 
     if not picture: 
      raise forms.ValidationError("No image!") 
     else: 
      w, h = get_image_dimensions(picture) 
      if w != 100: 
       raise forms.ValidationError("The image is %i pixel wide. It's supposed to be 100px" % w) 
      if h != 200: 
       raise forms.ValidationError("The image is %i pixel high. It's supposed to be 200px" % h) 
     return picture 

class MyAdmin(admin.ModelAdmin): 
    form = myForm 

admin.site.register(Example, MyAdmin) 
+0

byłem zbyt powolny, tutaj jest powiązany link: http://docs.djangoproject.com/en/dev/ref/forms/validation/# clean-a-specific-field-atrybut – monkut

+1

Podczas gdy to rozwiązanie jest fajne dla odniesienia, OP powiedział, że chce sprawdzić wymiary obrazu PRZED przesłaniem formularza. Więc musi to być coś po stronie klienta. Czy też błędnie odczytuję jego ostatni akapit? – cethegeek

+0

Niekoniecznie mam na myśli przed złożeniem formularza, o ile jest on przed zapisaniem modelu. – Apreche

0

Może to być dupe z/bardzo podobna do tej kwestii:

Using jQuery, Restricting File Size Before Uploading

nie sądzę jest sposób, aby zrobić to tak, jak chcesz. Rozwiązanie Agos to sposób na ...

Edytuj: Jedna z odpowiedzi w połączonym pytaniu dotyczącym SO mówi o używaniu lampy błyskowej, aby to zrobić. Chociaż może być to możliwe w przypadku innej technologii, nie sądzę, że można to zrobić za pomocą prostego javascript.

+0

Inną możliwą technologią może być aplet Javy. Widziałem wielu przesyłających, którzy zajmują się tą sprawą w ten sposób. Jest to również przydatne w przypadku, gdy chcesz pozwolić na dużą/dużą liczbę ładowań. – Agos

2

korzystanie z tej funkcji w pliku modelu,

from django.core.exceptions import ValidationError 

    def validate_image(fieldfile_obj): 
      filesize = fieldfile_obj.file.size 
      megabyte_limit = 2.0 
      if filesize > megabyte_limit*1024*1024: 
       raise ValidationError("Max file size is %sMB" % str(megabyte_limit)) 

    class Company(models.Model): 
     logo = models.ImageField("Logo", upload_to=upload_logo_to,validators=[validate_image], blank=True, null=True,help_text='Maximum file size allowed is 2Mb') 
+0

To nie działa. Odwołując się do pliku w ten sposób z walidatora, zanim plik zostanie zapisany, po prostu zwraca '*** FileNotFoundError: [Errno 2] Brak takiego pliku lub katalogu: '/ srv/www/media/80329e39-5c5c-4e79- 8e32-51087ae00f6a''. Być może będzie działać z plikami, których Django nie zapisuje jako obiektów 'InMemoryUploadedFile', gdzie znajdują się w'/tmp' lub gdzieś podobnym do pliku rzeczywistego. Jednak tego nie przetestowałem. – Bryson