Как сделать связь M2M не по ID, а по другому полю?

В Django для создания связи Many-to-Many (М2М) используется поле ManyToManyField, которое по умолчанию создает связь по ID моделей. Однако, в некоторых случаях, возникает необходимость установить связь по другому полю, отличному от ID. Для этого можно воспользоваться параметром to_field.

Предположим, у нас есть две модели: User и Group. Мы хотим установить связь М2М между этими моделями не по ID пользователя и ID группы, а по полю name пользователей и полю name групп.

Пример моделей:

from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)
    groups = models.ManyToManyField('Group', related_name='users', to_field='name')

class Group(models.Model):
    name = models.CharField(max_length=100)

В примере выше, в поле M2M groups модели User мы устанавливаем параметр to_field='name', который указывает Django использовать значение поля name для установки связи, а не поле ID.

Теперь, когда мы создаем объекты User и Group, мы можем использовать имена, а не ID для установки связей:

# Создание группы
group1 = Group.objects.create(name='Group 1')

# Создание пользователей и установление связей с группой
user1 = User.objects.create(name='User 1')
user1.groups.add(group1)

user2 = User.objects.create(name='User 2')
group1.users.add(user2)

В результате, у нас будет установлена связь между объектами User и Group по полю name. Для доступа к связанным объектам можно использовать обратные связи, указанные в related_name. Например, чтобы получить группы пользователя, можно обратиться к полю groups:

user = User.objects.get(name='User 1')
user.groups.all()  # Вернет queryset со связанными группами пользователя

Таким образом, с помощью параметра to_field мы можем настроить связь М2М в Django не по ID, а по другому полю моделей.