Циклическая запись в serializer.save() в среде Django REST

У меня есть функция в DRF, где я хочу сказать системе обновить «всех», скажем, я хочу дать всем, кто вошел в систему сегодня, бесплатный приз и хочу сохранить этот список (я понимаю, что этот пример глупый, это просто я пытаюсь чтобы обобщить мой вариант использования). Он будет запрашивать, какие пользователи вошли в систему сегодня, а затем я хочу пройтись по этим пользователям, чтобы создать новое действие по вручению им приза.

Похоже, что при записи сохраняется только последнее значение в цикле.

            time_threshold = datetime.now() - timedelta(hours=12)
            signed_in_list = Activity.objects.filter(created__gte=time_threshold, activity="signed in")
            for activity in signed_in_list:
                serializer.save(user=activity.user_id, activity="gets free prize")
            headers = self.get_success_headers(serializer.data)
            return Response(serializer.data, status=status.HTTP_201_CREATED,
                   headers=headers)

Я пытаюсь сделать так, чтобы для каждого идентификатора пользователя, возвращаемого из «signed_in_list», было написано новое действие.

Я ожидал, что для каждого user_id в цикле будет записана новая запись Activity, но она выполняет только последний user_id в цикле. Это заставляет меня думать, что serializer.save работает, но переопределяет себя каждый раз в цикле (по сравнению с выполнением записи в БД).


person probbins222    schedule 24.02.2017    source источник


Ответы (2)


Вы ссылаетесь на «для пользователя в» и «user.id», когда на самом деле это не пользователь, а те объекты, на которые вы ссылаетесь, являются действиями.

В идеале я хотел бы увидеть ваш сериализатор, но, учитывая, что вы передали тот же аргумент, что и команда queryset, я предполагаю, что моделью сериализатора является Activity?

В этом случае вы пытаетесь сохранить новое действие с тем же идентификатором первичного ключа, что и предыдущее существующее действие, которое было возвращено в вашем наборе запросов. Это обновление, но для запуска обновления в сериализаторе экземпляр Activity необходимо передать в сериализатор при его инициализации. В общем, будь то модели Django или сериализаторы DRF, вам никогда не нужно передавать идентификатор для сохранения, особенно существующий идентификатор.

Предполагая, что у вас есть внешний ключ в модели действий под названием «пользователь», который ссылается на модель пользователя, которую вы можете сделать:

time_threshold = datetime.now() - timedelta(hours=12) signed_in_list = Activity.objects.filter(created__gte=time_threshold, activity="signed in") for activity in signed_in_list: serializer.save(user=activity.user, activity="gets free prize") headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Что касается «user=activity.user», переданного в качестве аргумента ключевого слова для serializer.save(), это то, как вы сделали бы это при сохранении модели. Я думаю, что то же самое с сериализаторами DRF, я не уверен на 100%, но если это не сработает, вы можете попробовать user=activity.user.id

person user3261477    schedule 24.02.2017
comment
спасибо за комментарий, я думаю, что он запутался, когда я попытался сделать его более общим для вопроса. Я исправил его, чтобы он соответствовал логике кода, на который вы указали. Это просто похоже на то, что serializer.save выполняется только в конце функции создания, а не выполняется каждый раз в этом цикле. - person probbins222; 25.02.2017
comment
В приведенном выше примере он по-прежнему выполняет запись в БД только для последнего элемента в списке. - person probbins222; 25.02.2017

Я смог решить это. Вместо serializer.save я обновил запрос и рекурсивно вызвал свою функцию создания

 def create(self, request, *args, **kwargs):
        time_threshold = datetime.now() - timedelta(hours=12)
        signed_in_list = Activity.objects.filter(created__gte=time_threshold, activity="signed in")
        for activity in signed_in_list:
            request.data["user"] = activity.user
            self.create(request, *args, **kwargs)   
        return Response(status=status.HTTP_201_CREATED)
person probbins222    schedule 25.02.2017