Django application has a GM2MField that combines the features of the standard Django "ManyToManyField" and "GenericForeignKey".
Installation:
pip install django-gm2m
Django’s contenttype framework must be (django.contrib.contenttypes) mentionned in the INSTALLED_APPS.
INSTALLED_APPS = [
...
'django.contrib.contenttypes',
...
'gm2m',
]
Uses Of django-gm2m:
1. reverse relations
2. prefetching
3. Allows you to customize the deletion behaviour
Example Models:
from django.db import models
class Videos(models.Model):
name = models.CharField(maxlength=100)
class Articles(models.Model):
name = models.CharField(maxlength=100)
If you want to have a field for the preferred videos and articles of a User, you need to add GM2MField to the User model.
from gm2m import GM2MField
class User(models.Model):
email = models.CharField(maxlength=100)
username = models.CharField(maxlength=100)
related = models.GM2MField()
Now you can add videos, articles to the related set.
Creating User object:
user = User.objects.create(email="[email protected]", username="[email protected]")
video = Videos.objects.create(name="video")
article = Articles.objects.create(name="sample document")
user.related.add(video)
user.related.add(article)
or you can add both videos, articles instances.
user.related = [video, article]
From User instance, you can fetch all related videos, articles set or you can filter model using the "Model" or "Model__in" keywords.
list(user.related) # This provides list of model objects
list(user.related.filter(Model=Videos)) # This provides list of user related video instances
list(user.related.filter(Model__in=[Videos, Articles]))
GM2MField provides automatic reverse relations when an instance is added.
We have seen how to access videos, articles of a given user.
Here we see how to access list of all the users with the given Video or Article instance.
list(video.user_set) # This provides list of user instances
With the user reverse relation, we can also use lookup chains in your queries, can also perform add, remove, clear, set operations
[each.email for each in Video.objects.filter(user__email='[email protected]')]
We can also list the models related to GM2MField using get_related_models method
User.related.get_related_models()
this will give article, video objects as they are already added to user using GM2MField
2. Prefetching
GM2MField provides prefetching in the same way with ManyToManyField
User.objects.all().prefetch_related('related')
3. Allows you to customize the deletion behaviour
By default, when a source or target model instance is deleted, all relations linking this instance are deleted. It is possible to change this behavior with the on_delete, on_delete_src keyword arguments when creating the GM2MField.
from gm2m.deletion import DO_NOTHING
class User(models.Model):
preferred_videos = GM2MField(Movie, 'Documentary', on_delete=DO_NOTHING)
But be ensure that the database remains consistent after the deletion operation.