pep-un/Oxomium

Add attachement to control point

Closed this issue · 1 comments

pep-un commented

The controler must be in capacity to prove the control and add an attachement.

Voici un guide détaillé, étape par étape, pour créer une classe Attachment qui peut être utilisée dans plusieurs autres classes, avec des mises en œuvre évolutives afin d'ajouter des améliorations front-end, telles que Dropzone.js, ultérieurement. Ce guide couvrira les impacts sur les vues basées sur les classes, les formulaires, et les améliorations potentielles futures.


Étape 1 : Création de la classe Attachment

Objectif

Nous allons d'abord créer une classe Attachment qui pourra être liée à plusieurs modèles via une relation ManyToManyField. Cela permet de lier plusieurs fichiers à plusieurs objets de modèles différents, ce qui offre une grande flexibilité.

Implémentation

  1. Modèle Attachment : Ce modèle gérera les fichiers eux-mêmes, et pourra être lié à plusieurs autres modèles.
from django.db import models

class Attachment(models.Model):
    file = models.FileField(upload_to='attachments/')
    name = models.CharField(max_length=255, blank=True)

    def __str__(self):
        return self.name if self.name else self.file.name

Explications :

  • file : Le fichier uploadé.
  • name : Un nom optionnel pour chaque fichier, au cas où tu souhaites afficher un nom plus convivial que le nom du fichier.

Étape 2 : Lier Attachment aux autres modèles

Objectif

Nous allons lier le modèle Attachment à d'autres classes via une relation ManyToManyField. Cela permet à un modèle (par exemple, Project, Task, etc.) d'avoir plusieurs fichiers joints, et ces fichiers peuvent également être associés à d'autres objets.

Implémentation

Supposons que tu souhaites ajouter des pièces jointes à un modèle Project et un modèle Task. Tu vas simplement ajouter un champ ManyToManyField à chaque modèle.

class Project(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField()
    attachments = models.ManyToManyField('Attachment', blank=True, related_name='projects')

    def __str__(self):
        return self.name


class Task(models.Model):
    title = models.CharField(max_length=255)
    description = models.TextField()
    attachments = models.ManyToManyField('Attachment', blank=True, related_name='tasks')

    def __str__(self):
        return self.title

Explications :

  • attachments : Le champ ManyToManyField qui relie plusieurs fichiers à un objet.
  • related_name : Cela te permet de récupérer les projets ou tâches associés à un fichier donné. Par exemple, attachment.projects.all() retourne tous les projets liés à une pièce jointe.

Étape 3 : Création des formulaires

Objectif

Nous allons maintenant créer les formulaires pour permettre aux utilisateurs de télécharger des fichiers et de les associer à des objets, tels que des projets ou des tâches.

Implémentation

  1. Formulaire pour Project :
from django import forms
from .models import Project

class ProjectForm(forms.ModelForm):
    attachments = forms.FileField(required=False, widget=forms.ClearableFileInput(attrs={'multiple': True}))

    class Meta:
        model = Project
        fields = ['name', 'description']
  1. Formulaire pour Task :
from django import forms
from .models import Task

class TaskForm(forms.ModelForm):
    attachments = forms.FileField(required=False, widget=forms.ClearableFileInput(attrs={'multiple': True}))

    class Meta:
        model = Task
        fields = ['title', 'description']

Explications :

  • attachments : Le champ FileField est ajouté manuellement au formulaire pour gérer les fichiers multiples via l'attribut multiple=True. Cela permet d’uploader plusieurs fichiers simultanément.
  • forms.ClearableFileInput : Ce widget permet d'afficher une interface d'upload de fichiers avec la possibilité de supprimer les fichiers sélectionnés avant l'envoi.

Étape 4 : Création des vues basées sur des classes

Objectif

Nous allons maintenant configurer les vues basées sur des classes pour gérer la création et la mise à jour de projets et de tâches, tout en prenant en compte les fichiers joints.

Implémentation

  1. Vue ProjectCreateView pour créer un projet :
from django.views.generic import CreateView
from .models import Project, Attachment
from .forms import ProjectForm
from django.urls import reverse_lazy

class ProjectCreateView(CreateView):
    model = Project
    form_class = ProjectForm
    template_name = 'project_create.html'
    success_url = reverse_lazy('project_list')

    def form_valid(self, form):
        response = super().form_valid(form)  # Sauvegarde l'objet Project
        attachments = self.request.FILES.getlist('attachments')  # Récupère la liste des fichiers
        for file in attachments:
            attachment = Attachment.objects.create(file=file)  # Crée un objet Attachment
            self.object.attachments.add(attachment)  # Lie le fichier au projet
        return response
  1. Vue TaskCreateView pour créer une tâche :
from django.views.generic import CreateView
from .models import Task, Attachment
from .forms import TaskForm
from django.urls import reverse_lazy

class TaskCreateView(CreateView):
    model = Task
    form_class = TaskForm
    template_name = 'task_create.html'
    success_url = reverse_lazy('task_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        attachments = self.request.FILES.getlist('attachments')
        for file in attachments:
            attachment = Attachment.objects.create(file=file)
            self.object.attachments.add(attachment)
        return response

Explications :

  • getlist('attachments') : Récupère tous les fichiers joints uploadés via le formulaire.
  • self.object.attachments.add(attachment) : Lie chaque fichier téléchargé à l'objet Project ou Task.

Étape 5 : Templates pour les formulaires

Objectif

Nous devons maintenant créer les templates HTML pour afficher les formulaires d'ajout de projets et de tâches avec des fichiers joints.

Implémentation

  1. Template pour créer un projet (project_create.html) :
<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Créer le projet</button>
</form>
  1. Template pour créer une tâche (task_create.html) :
<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Créer la tâche</button>
</form>

Explications :

  • enctype="multipart/form-data" : Nécessaire pour permettre l'upload de fichiers dans le formulaire.
  • {{ form.as_p }} : Génère les champs du formulaire, y compris l'input pour l'upload de fichiers.

Étape 6 : Améliorations évolutives (Dropzone.js, etc.)

Objectif

Tu peux facilement ajouter Dropzone.js pour offrir une interface de glisser-déposer et de copier-coller pour les fichiers joints. Cela permet de rendre l'expérience utilisateur plus fluide, mais tu peux l'ajouter plus tard sans changer ta logique back-end.

  1. Ajout de Dropzone.js : Suis l'exemple que nous avons vu précédemment pour intégrer Dropzone.js en tant qu'amélioration front-end.

  2. Réutilisation du backend : La logique côté serveur ne change pas. Tu récupères toujours les fichiers via self.request.FILES.getlist('attachments').


Résumé des étapes

  1. Modèle Attachment : Crée un modèle réutilisable pour gérer les fichiers.
  2. Ajout du champ ManyToManyField dans les modèles : Relie le modèle Attachment à d'autres modèles comme Project ou Task.
  3. Création des formulaires : Gère l'upload de plusieurs fichiers dans des formulaires de type ModelForm.
  4. Vues basées sur des classes : Implémente les vues pour traiter les fichiers joints lors de la création ou mise à jour d'un objet.
  5. Templates HTML : Gère l'upload via des formulaires simples, avec la possibilité d'ajouter Dropzone.js plus tard.

Ce guide te permet d'avoir une architecture robuste et évolutive pour gérer des fichiers joints dans plusieurs modèles, tout en offrant une base solide pour intégrer des améliorations front-end comme Dropzone.js ultérieurement.