Many to Many Beziehung

Bisher hatten wir uns auschließlich mit 1-N Beziehungen befasst, genauergesagt mit dem ForeignKey - Feld des Django-Models, der sogenannten One-to-Many Beziehung. Nun wollen wir uns mit einer weiteren Beziehung befassen, nämlich der M-N Beziehung, auch bekannt als Many-to-Many Beziehung.

Eine M-N Beziehung zeichnet sich in relationalen Datenbanken dadurch aus, dass sie nur mithilfe einer Zwischentabelle abgebildet werden kann. Django ist hier aber extrem zuvorkommend. Durch das Anlegen eines ManytoMany Felds wird von Django diese Tabelle generiert, wir haben damit weiter nichts zu tun.

Das Tag Modell

Wir wollen für unsere Events die Möglichkeit haben, sie mit diversen Begriffen zu taggen, zum Beispiel Freizeit oder Weekend Fun. Jeder Tag kann mehreren Events zugeordnet werden und jeder Event hat mehere Tags.

Hier noch kurz das UML-Modell unserer Anwendung und die neue Tag-Klasse, wie sie in Verbindung zum Event steht.

../_images/uml_class_4.png
class Tag(models.Model):
    description = models.TextField(blank=True, null=True)
    icon = models.CharField(max_length=19)
    name = models.CharField(
        max_length=99,
        unique=True,
    )
    slug = models.SlugField(unique=True)

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.name)
        super().save(*args, **kwargs)

    def __str__(self):
        return self.name

Wenn wir die nötigen Migrationen durchführen, wird jetzt ein Tag-Model angelegt.

python manage.py makemigrations events
python manage.py migrate events

Um das Model in der Admin verfügbar zu machen, fügen wir noch diesen Code in die event_manager/events/admin.py ein:

from .models import Category, Event, Tag

# registrieren das Tag-Model
admin.site.register(Tag)

Wenn wir uns jetzt auf der Adminoberfläche per Browser einloggen, sollten wir das Tag-Model jetzt sehen können. Probeweise legen wir ein paar Tags an.

MISSING: IMAGE

Das Event Modell

Nun müssen wir nur noch unser Event-Model unter event_manager/events/models.py anpassen.

Im Event-Model definieren wir mit einem ManyToMany - Feld die M-N Beziehung. Auch hier nutzen wir den related_name, wir wir das schon beim ForeignKey-Feld gemacht hatten.

class Event(DateMixin):

[..]

author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="events")
# das hier eintragen:
tags = models.ManyToManyField(Tag, related_name="events", blank=True)

class Meta:
    ordering = ["name"]
    [..]

Mit blank=True sagen wir, dass Tags optional sind.

Nun muss die App nochmal migriert werden.

python manage.py makemigrations events
python manage.py migrate events

Wenn wir uns jetzt auf der Adminoberfläche per Browser einloggen, sollten wir den Events nun die vorhin erstellten Tags zurordnen können.

Hier einige Beispiele, wie man mit diesen beiden Models arbeiten würde.

>> from events.models import Event, Tag
>> # Zwei Tags anlegen
>> tag1 = Tag.objects.create(name="Summer and Sun")
>> tag2 = Tag.objects.create(name="City")
>> # einen Event selektieren
>> event1 = Event.objects.all().first()
>> # diesem Event zwei Tags zurordnen mit add
>> event1.tags.add(tag1)
>> event1.tags.add(tag2)
>> # Alle Events auflisten, die tag2 zugeordnet sind
>> tag2.events.all()
>> # Alle Tags eines Events auflisten
>> event1.tags.all()

MISSING: IMAGE

Weitere Beispiele zur ManyToMany-Beziehung findet sich in der Django-Doku: * https://docs.djangoproject.com/en/stable/topics/db/examples/many_to_many/