Compléments sur les modèles Django

Nous allons à présent explorer quelques modèles de relations classiques de Django. Vous trouverez leur documentation. Les plus utilisés sont de type ManyToOne avec des ForeignKey ou les relations ManyToMany.

Les Foreign Keys

Si on a par exemple de Task et de Users et une ou plusieurs tâches assignées à un utilisateur, on crée une ForeignKey utilisateur vers le modèle de User.

class User(models.Model):
    username = models.CharField(max_length=150)

    def __str__(self):
        return self.username


class Task(models.Model):
    name = models.CharField(max_length=250)
    description = models.TextField()
    creation_date = models.DateField(auto_now_add=True)
    # ../..
    closed = models.BooleanField(default=False)
    utilisateur = models.ForeignKey(User, on_delete=models.CASCADE, related_name="tasks")

    def __str__(self):
        return self.name

Indication

text

Notez l’attribut related_name=tasks qui permettra de retrouver aisément toutes les tâches assignées à un utilisateur user avec l’appel : user.tasks.all():

ManyToMany

Si on considère un modèle avec des Utilisateurs, des Emails et des Listes de Diffusion, on peut considérer qu’un utilisateur peut avoir plusieurs adresses mail, qu’une liste de diffusion contient différents emails et qu’un email peut apparaitre dans plusieurs listes de diffusion :

_images/UserEmailLIsteDiffusion.png

On peut alors déclarer ces entités :

"""models.py"""

# utilisateurs
class Utilisateur(models.Model):
    nom = models.CharField(max_length=30)

    def __str__(self):
        return "%s %s" % (self.prenom, self.nom)

# emails
class Email(models.Model):
    mail = models.CharField(max_length=30)
    user = models.ForeignKey(Utilisateur, on_delete=models.CASCADE,null=True, related_name='emails')

    def __str__(self):
        return self.mail

# listes de diffusion
class ListeDiffusion(models.Model):
    listeName = models.CharField(max_length=30)
    email = models.ManyToManyField(Email, related_name='listes')

    def __str__(self):
        return self.listeName

puis les manipuler :

from .models import Utilisateur, Email, ListeDiffusion


# On crée 2 utilisateurs
user1 = Utilisateur(nom='user1')
user2 = Utilisateur(nom='user2')

# On crée les mails associés
email1 = Email(mail='user1@baba.fr', user=user1)
email2 = Email(mail='user2@bibi.fr', user=user2)

# On crée 4 listes de diffusion
liste1 = ListeDiffusion(listeName='liste1')
liste2 = ListeDiffusion(listeName='liste2')
liste3 = ListeDiffusion(listeName='liste3')
liste4 = ListeDiffusion(listeName='liste4')

# on sauvegarde tout le monde
user1.save()
user2.save()
email1.save()
email2.save()
liste1.save()
liste2.save()
liste3.save()
liste4.save()

# on ajoute les emails à des listes
liste1.email.add(email1)
liste1.email.add(email2)
liste2.email.add(email1)
liste3.email.add(email1)
liste3.email.add(email2)
liste4.add(email2)

# Pour obtenir toutes les listes auxquelles l'email1 est abonné :
email1.listes.all()
# Et celles auxquelles l'email2 est abonné :
email2.listes.all()

On peut ensuite faire une petite vue du style :

#views.py
def email_detail(request, pk):
    email = Email.objects.get(pk=pk)
    user = email.user
    listes_abonnees = email.listes.all()
    template = 'email_detail.html'
    context = {'user': user, 'email': email.mail, 'listes': listes_abonnees }
    return render(request, template, context)

puis un template :

# template email_detail.html
<p>
Email : {{email}}
</p>
<p>
User : {{user}}
</p>
Listes de diffusion :
<ul>
{% for liste in listes %}
    <li>{{ liste }}</li>
{% endfor %}
</ul>

documentation

Les docs détaillées sont là :