Join and get queryset accordring to many to many field
I have MyUser model with ForeignKey and ManyToMany related fields city and skills:
class MyUser(AbstractBaseUser):
email = models.EmailField()
skills = models.ManyToManyField('jobs.Skill')
class Skill(models.Model):
name = models.CharField()
suppose this my table data in database
{'email': 'some@email.com', 'skills': ['Python', 'Java']},
{'email': 'another@email.com', 'skills': ['JavaScript', 'C#', 'Python']}
>>> MyUser.objects.all().count()
output is 2 but iwant
MyUser.objects. ..........
answer to 5 my like following data
{'email': 'some@email.com', 'city': 'London', 'skills': 'Python'},
{'email': 'some@email.com', 'city': 'London', 'skills': 'Java'},
{'email': 'another@email.com', 'city': 'Berlin', 'skills': 'JavaScript'},
{'email': 'another@email.com', 'city': 'Berlin', 'skills': 'C#'},
{'email': 'another@email.com', 'city': 'Berlin', 'skills': 'Python'},
You can use annoate()
, with Count aggregation and values()
to get the desired output so:
from django.db.models import Count
all_users = MyUser.objects.annotate(num_skills=Count('skills')).values('email', 'num_skills')
data = []
for single_user in all_users:
email = single_user['email']
num_skills = single_user['num_skills']
skills = MyUser.objects.get(email=email).skills.all()
for skill in skills:
data.append({'email': email, 'city': 'London', 'skills': skill.name})
print(data)
Obviously, not a good solution as city
value is hardcoded to London
and Berlin
for the first and second user respectively.
You can simply query like this:
MyUser.objects.values('email', 'city', 'skills__name')
You can also rename the skills__name
field like this:
MyUser.objects.annotate(skill=F('skills__name')).values('email', 'city', 'skill')