CCCPaste

Uploading of many file in Django

Качване на множество файлове във формата независимо дали са снимки или видео?
Чрез единични полета във вече съществуващия модел не работи, понеже по този начин се качват по една снимка и по едно видео.
Решението е да се направи допълнителен модел .....Media, който се свързва с първия модел. В него се добавя поле file = models.FileField и се оказва, къде ще се качват файловете.

Пример:
Първи модел

django.contrib.auth import get_user_model
from django.db import models
from django.utils import timezone

UserModel = get_user_model()


class Publication(models.Model):
    location = models.CharField(
        max_length=200,
        null=True,
        blank=True,
    )

    description = models.TextField(
        null=False,
        blank=False,
    )


    weight_kg = models.FloatField(
        null=True,
        blank=True,
    )

    created_at = models.DateTimeField(
        default=timezone.now,
    )

    user = models.ForeignKey(UserModel, on_delete=models.CASCADE)


Втори модел

class PublicationMedia(models.Model):
    MEDIA_TYPE_CHOICES = (
        ('image', 'Image'),
        ('video', 'Video'),
    )
    publication = models.ForeignKey(Publication, on_delete=models.CASCADE)
    file = models.FileField(upload_to='files/')
    media_type = models.CharField(max_length=5, choices=MEDIA_TYPE_CHOICES)


Формата не се променя и не й се добавя допълнителни полета. С добавено допълнително поле не работи, понеже това поле идва от другия модел. Остава си така:

class PublicationBaseForm(forms.ModelForm):
    class Meta:
        model = Publication
        fields = ["location", "description", "weight_kg"]
        widgets = {
            'location': forms.TextInput(attrs={'placeholder': 'Enter your fishing location'}),
            'description': forms.Textarea(attrs={'placeholder': 'Enter a description of your fishing experience'}),
            'weight_kg': forms.NumberInput(attrs={'placeholder': 'Enter weight of the fish'}),
        }


След което ръчно се добавя полето за качване на файловете в html-a по този начин:





Във view-то в променливата media_files става списък с качените файлове обекти.
Итерира се през всички файлове с for цикъл и се записва всеки един файл в базата свързан с публикацията.

@method_decorator(login_required, name='dispatch')
class PublicationCreateView(views.CreateView):
    form_class = PublicationCreateForm
    model = Publication
    template_name = "publications/publication_create.html"
    success_url = reverse_lazy("feed")

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.user = self.request.user
        self.object.save()

        media_files = self.request.FILES.getlist('media_files') --> списък от фаловете
        for file in media_files: --> итерира се
            content_type = file.content_type
            media_type = 'video' if content_type.startswith('video') else 'image' --> взима се типа на файла
            PublicationMedia.objects.create(
                publication=self.object,
                file=file,
                media_type=media_type
            ) --> създава се обект

        return super().form_valid(form)