CreateView создание двух объектов модели

Я создал Form, где Пользователь устанавливает объект Alarm. Объект Alarm сохраняется в базе данных, как и ожидалось. Однако проблема в том, что другой объект, который содержит только информацию, заполненную в Form, также сохраняется в базе данных.

Я так понимаю, form_valid() за CreateView сохраняет форму. Я попробовал два решения, предложенные в другом запросе без успех. Я подозреваю, что проблема вызвана либо return super().form_valid(form), либо Alarm.objects.create() в create_alarm_object().

Views.py

class AlarmCreateView(LoginRequiredMixin, CreateView):
    """ CreateView for User to create the Alarm object """
    model = Alarm
    form_class = SetAlarmForm
    template_name = 'weather_alarm/set_alarm.html'
    login_url = "/login/"

    def form_valid(self, form):
        self.create_alarm_object(request, form)
        return super().form_valid(form)

    def get_success_url(self, **kwargs):
        return reverse("weather_alarm:active-alarm", kwargs={'pk':self.object.pk})

    def create_alarm_object(self, request, form):
        """ Function to get User's location from IP and create Alarm object """
        ...
        alarm_object = Alarm.objects.create(
            alarm_id=uuid.uuid4(),
            user=self.request.user,
            timezone=user_timezone,
            city=location.raw['address']['city'],
            country=location.raw['address']['country'],
            time=form.cleaned_data['time'].astimezone(pytz.timezone(user_timezone)),
            temp_conditional=form.cleaned_data['temp_conditional'],
            surf_conditional=form.cleaned_data['surf_conditional'],
            temp_max=form.cleaned_data['temp_max'],
            temp_min=form.cleaned_data['temp_min'],
            surf_max=form.cleaned_data['surf_max'],
            surf_min=form.cleaned_data['surf_min'],
        )
        alarm_object.save()

person Darcy    schedule 10.08.2018    source источник
comment
Вы можете не передавать аргумент request методу create_alarm_object.   -  person Sachin    schedule 11.08.2018


Ответы (1)


Вы правильно отладили. super вызов form_valid и метод create_alarm_object создают два объекта.

Как видно из реализации метода form_valid, он сохраняет форму и возвращает объект HttpResponseRedirect, используя success_url.

Либо не переопределяйте метод form_valid, либо используйте следующий код.

Решение:

def form_valid(self, form):
    self.create_alarm_object(self.request, form)
    return HttpResponseRedirect(self.get_success_url())

ИЗМЕНИТЬ:

Обновите метод create_alarm_object, чтобы установить self.object и удалить избыточный вызов save.

def create_alarm_object(self, request, form):
    self.object = Alarm.objects.create(...)
    # no `save` call needed, `create` already creates and returns the saved object.
person Sachin    schedule 10.08.2018
comment
Я попробовал предложенное позднее решение и получил следующую ошибку: AttributeError: 'NoneType' object has no attribute 'pk'. Обратите внимание, Primary_Key=True вместо alarm_id. Нужно ли ссылаться на alarm_id в get_success_url()? Однако я проверил базу данных, и теперь объект Alarm правильно сохраняет один объект! - person Darcy; 11.08.2018
comment
Извинения. return reverse("weather_alarm:active-alarm", kwargs={'pk':self.object.pk}) - person Darcy; 11.08.2018
comment
Это другая проблема. Хотя вы можете легко решить эту проблему, установив self.object в методе create_alarm_object тот, который вы создали. - person Sachin; 11.08.2018