Присоединяйтесь и получайте кверисет в соответствии с полем многие ко многим

У меня есть модель MyUser с ForeignKey и ManyToMany связанными полями city и skills:

class MyUser(AbstractBaseUser):
    email = models.EmailField()
    skills = models.ManyToManyField('jobs.Skill')

class Skill(models.Model):
    name = models.CharField()

предположим, что это данные моей таблицы в базе данных

{'email': 'some@email.com',  'skills': ['Python', 'Java']},
{'email': 'another@email.com',  'skills': ['JavaScript', 'C#', 'Python']}
>>> MyUser.objects.all().count()

выход равен 2, но я хочу

MyUser.objects. ..........

ответьте на 5 моих вопросов, используя следующие данные

{'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'},

Вы можете использовать annoate(), с агрегацией Count и values() для получения желаемого результата так:

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)

Очевидно, что это не лучшее решение, так как значение city жестко закодировано в London и Berlin для первого и второго пользователя соответственно.

Вы можете просто запросить следующим образом:

MyUser.objects.values('email', 'city', 'skills__name')

Вы также можете переименовать поле skills__name следующим образом:

MyUser.objects.annotate(skill=F('skills__name')).values('email', 'city', 'skill')
Вернуться на верх