Как обновить объект, когда создается несколько других связанных с ним объектов
Мне нужно добавить поле progress_level в мою модель пользователя, которое показывает, на каком этапе находится данный пользователь, поэтому я добавил поле в модель пользователя следующим образом:
progress_level = models.CharField(max_length=25, null=True, choices=USER_PROGRESS_LEVELS)
Я хочу, чтобы это поле автоматически обновлялось каждый раз, когда пользователь выполняет какое-либо действие. Например, если пользователь заполняет контактную информацию и информацию о документе и отправляет форму, уровень прогресса должен измениться на [1][0]. Я действительно не знаю, как это сделать, но я создал сигнал следующим образом:
@receiver(pre_save, sender=User, dispatch_uid='progress_change')
def progress(sender, instance, **kwargs):
user = instance
if DocumentInfo.objects.filter(user=user).exists() and ContactInfo.objects.filter(user=user).exists():
user.progress_level = USER_PROGRESS_LEVELS[1][0]
он работает нормально, но активируется только при сохранении модели User. как я могу предотвратить это? как я могу активировать этот сигнал каждый раз, когда это утверждение истинно? если есть лучший способ сделать это, пожалуйста, помогите мне. Я действительно не знаю, являются ли сигналы правильным способом сделать это.
Как насчет обновления метода сохранения модели?
models.py
class User(...):
...
document_info = models.OneToOneField(DocumentInfo, ...)
contact_info = models.OneToOneField(ContactInfo, ...)
def save(self, *args, **kwargs):
if self.document_info and self.contact_info:
self.progress_level = USER_PROGRESS_LEVELS[1][0]
return super().save(*args, **kwargs)
Вы хотите изменить значение progress_level там, где вы добавляете какой-то документ или полный контакт ... как насчет того, чтобы сделать это в методе сохранения или обновления модели документа или модели контакта ... контакт или модель документа, которые связаны с определенным пользователем, имеют метод сохранения или обновления может влиять на значение "progress_level" на модели пользователя через экземпляр пользователя. Вы можете получить экземпляр пользователя из модели документа в методе сохранения (потому что у вас есть внешний ключ) и проверить, что процесс был выполнен... увеличить "progress_level" для экземпляра пользователя. если вы не знаете, как это сделать в коде, дайте мне знать, чтобы я объяснил это на примере кода
Я предполагаю, что ваши модели имеют следующую форму:
class User(AbstractUser):
progress_level = models.IntegerField(null=True, default=0)
// some other field
class DocumentInfo(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
// some other field
Вы устанавливаете сериализатор для документа следующим образом:
class DocumentInfoSerializer(serializers.ModelSerializer):
user = UserSerializer(many=False, write_only=True)
class Meta:
model = DocumentInfo
fields = ('id', 'user', /* some other fields */)
read_only_fields = ('id',)
Теперь в модели DocumentInfo нужно закодировать метод сохранения следующим образом:
class DocumentInfoManager(models.Manager):
def create(self, user, **kwargs):
user_obj = User.objects.get(id=user.id)
user_obj.progress_level = 1 // set progress_level here
user.save() // user instance update here
document_obj = DocumentInfo(user=user, **kwargs)
document_obj.save()
return document_obj
class DocumentInfo(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
// some other field
objects = DocumentInfoManager() // this line is necessary
Вы определяете id в модели User. Обратите внимание, что в модели не обязательно определять поле id (primary_key) с аргументом инкремента ... django создает id для каждой модели автоматически