Загрузка изображений без ModelForm - PullRequest
0 голосов
/ 05 октября 2019

Я создаю страницу для добавления продуктов в интернет-магазин пользователем, и у меня возникают проблемы с загрузкой изображений.

У меня есть форма с <input type="file">, и после выбора файловФайлы (изображения) должны быть временно загружены на сервер. После завершения загрузки должен отображаться предварительный просмотр изображения. Во время загрузки также должна отображаться загрузка GIF счетчика с индикацией хода выполнения на стороне клиента, а также возможность отмены загрузки. Каждое загруженное изображение должно иметь возможность удаления после загрузки.

Из-за всех этих и других причин я не использую ModelForm, а создаю все вручную.

Итак, мойпланируется подключить прослушиватель onchange к этому входу, и после выбора файлов из JavaScript будет отправляться запрос POST XMLHttpRequest, который будет вызывать представление, сохраняющее изображения в какую-то таблицу для временно загруженных изображений, и идентификаторстрока будет что-то вроде request.session.session_key, но немного по-другому. Моя проблема с этим подходом заключается в создании этого сеансового ключа, который должен быть уникальным и должен длиться до тех пор, пока страница открыта. Таким образом, обновление страницы будет означать создание нового ключа. request.session.session_key не соответствует моим потребностям, так как остается неизменным на протяжении всего сеанса. Когда вся форма будет отправлена, я планирую каким-то образом связать эти временно загруженные изображения с моим основным экземпляром продукта и удалить их из таблицы для временных изображений.

Что вы думаете об этом решении, и если оно жизнеспособнокак сгенерировать ключ?

@ РЕДАКТИРОВАТЬ:

models.py:

class Product(models.Model):

    class Meta:
        abstract = True

    category = models.ForeignKey('Category', on_delete=models.CASCADE, blank=False)
    title = models.CharField(max_length=200)
    price = models.DecimalField(decimal_places=2, max_digits=10)
    free_shipping = models.BooleanField()
    stock = models.PositiveSmallIntegerField()
    image = models.ImageField(upload_to=get_image_path, blank=True, null=True)
    date_added = models.DateTimeField(auto_now=True, null=True)


class Book(Product):
    year = models.PositiveSmallIntegerField()
    publisher = models.CharField(max_length=50)
    author = models.CharField(max_length=50)
    language = models.CharField(max_length=20)
    isbn = models.CharField(max_length=50)


class Shoes(Product):
    size = models.PositiveSmallIntegerField()
    colour = models.CharField(max_length=20)    

1 Ответ

0 голосов
/ 05 октября 2019

У меня что-то похожее сделано с использованием Angular

products.ts

onFileChanged(event) {
    let reader = new FileReader();
    let me = this;
    if (event.target.files.length > 0) {
      const file = event.target.files[0];
      reader.readAsDataURL(file);
      reader.onload = function () {
          me.imagen = reader.result;
      };
      reader.onerror = function (error) {
        console.log('Error: ', error);
      };
    }
}

onSubmit(f){
   // f is my form 
   let postdata=f.value;
   postdata.imagen={'imagen': this.imagen};
   postdata.usuario=+localStorage.getItem("id_usuario");
   postdata.categoria=+postdata.categoria;
   postdata.precio=+postdata.precio;
   postdata.donacion=+postdata.donacion;
   console.log(postdata);
   this.articuloServicio.postNuevoArticulo(postdata)
   .subscribe(res=>{
     this.router.navigateByUrl('/mis_productos')
   },(error=>{
      alert('Error, verifique la informacion ingresada');
   }));
}

models.py

class Image(models.Model):
    image=models.ImageField(upload_to='imagenes/',blank=False, null=False)
    articule=models.ForeignKey(Articule,on_delete=models.CASCADE,
    related_name="images", 
    null=False, blank=False)

Некоторые изображения могут быть для одного и того же продукта

serializers.py

class ArticuloSerializer(serializers.ModelSerializer):

imagen = ImagenCreateSerializer(write_only=True)
class Meta:
    model = Articulo
    fields = ('id', 'categoria','usuario','nombre','precio','donacion','descrip', 'imagen')

def create(self, validated_data):
    imagenes = validated_data.pop('imagen')
    articulo = Articulo(**validated_data)
    articulo.save()
    for imagen in imagenes.values():
        Imagen.objects.create(articulo=articulo, imagen=imagen)
    return articulo

views.py

class ArticulosList(generics.ListCreateAPIView):

queryset = Articulo.objects.all()
serializer_class = ArticuloSerializer
def list(self, request, *args, **kwargs):
    queryset = Articulo.objects.all()
    serializer = ArticuloSerializerDetail(queryset, context={'request': request}, many=True)
    return Response(serializer.data, status=status.HTTP_200_OK)

def create(self, request, *args, **kwargs):
    serializer = ArticuloSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

В products.ts: в onFileChanged, который управляет загрузкой файлов, я использую Filereader, чтобы получить изображение иприсваивается переменной в моем угловом компоненте. В onSubmit я получаю данные из моей формы f и изображения, все данные находятся в объекте, который должен быть отправлен в мой сервис по запросу POST.

В models.py Я делюсь своей моделью изображения,это присоединено к Артикулу, это другая модель в моей схеме. Поле изображения - ImageField от Django.

В serializers.py я делюсь своим ArticuleSerializer, который сериализует данные для моего просмотра Articule и просмотров. Как вы можете видеть, есть функция create, в которой вы можете определить, как обрабатываются данные, когда отправляется запрос.

В views.py я определяю свое представление Articule для get и post, а для post - функция create. Для вызова этого представления в вашем urls.py назначьте его как

path("endpoint/", ArticuleList.as_view({"get": "list", "post": "create"}))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...