Как реализовать автоматическое создание записей по полю ManyToManyField:
Я хочу создать атчивки для юзера, для понимания вот сами таблички:
class User(BaseUser, models.Model):
objects = BaseUserManager()
is_organization = models.BooleanField(default=False)
class UserAchievement(models.Model):
name = models.CharField(max_length=128, unique=True)
description = models.CharField(max_length=256)
final_value = models.SmallIntegerField()
progress_right_now = models.FloatField(default=0)
given_exp = models.SmallIntegerField()
#image = models.ImageField()
class UsersAchievements(models.Model):
user = models.ManyToManyField(to=User)
achievement = models.ManyToManyField(to=UserAchievement)
is_achieved = models.BooleanField(default=False)
Сделал промежуточную табличку и для будущей логики нужное поле, чтобы позже проверять выполнена атчивка или нет, но вопрос в том, как бы правильней при создании юзера создавать ему записи в таблице UsersAchievements по всем существующим атчивкам, делать это сигналом пост_сев? или переопределить метод save модели юзер? Пытался реализовать 2 вариант, но сталкивался с ошибками
Direct assignment to the forward side of a many-to-many set is prohibited. Use user.set() instead. User' object has no attribute 'userachievements_set'
Потому хочу спросить как лучше правильнее и как именно это реализовать?
сейчас пробую сделать сигнал:
@receiver(post_save, sender=User)
def create_users_achievements(sender, instance, created, **kwargs):
if created and not instance.usersachievements_set.exists():
achievements = UserAchievement.objects.all()
instance.usersachievements_set.set(achievements)
но возникает следующая ошибка -
TypeError at /admin/custom_user/user/add/
Field 'id' expected a number but got <UserAchievement: название - Тест, опыт - 20>.
Третья таблица лишняя. Ее Django сам создаст. Просто в поле user добавь поле m2m на модель ачивок
Для того, чтобы автоматически создавать обьекты achievements для созданого юзера через связь many2many, я решил использовать сигналы.
Например:
@receiver(post_save, sender=User)
def create_user_achievements(sender, instance, created, **kwargs):
if created:
all_achievements = UserAchievement.objects.all()
for achievement in all_achievements:
user_achievement_status = UserAchievementStatus.objects.create(
user=instance,
achievement=achievement,
)
instance.achievements.set([achievement])
Более подробно в документации Many-to-many relationships.