django - проблема с get_or_create - приводит к двум объектам, созданным в БД - PullRequest
6 голосов
/ 04 октября 2011

У меня есть таблица в моей базе данных postgresql, в которой хранится запись о состоянии часа.Для каждого месяца, проекта и пользователя мне нужно ровно одно состояние.Я использую метод get_or_create, чтобы либо создать «состояние», либо получить его, если оно уже существует.

HourRecordState.objects.get_or_create(user=request.user, project=project, month=month, year=year, defaults={'state': 0, 'modified_by': request.user})

После выполнения этого в течение примерно двух лет без проблем я наткнулся напроблема в том, что у меня есть один HourRecordState дважды в моей базе данных.Теперь каждый раз, когда вызывается метод get_or_create, он выдает следующую ошибку:

MultipleObjectsReturned: get () возвратил более одного HourRecordState - он возвратил 2

I'mИнтересно, как это могло случиться, что у меня есть две одинаковые записи в моей БД.Интересно, что они были созданы одновременно (секунды, а не проверенные миллисекунды).

Я проверил свой код, и у меня во всем проекте только один метод get_or_create для создания этого объекта.Других методов создания в коде нет.

Было бы здорово получить подсказку.

Обновление:

Объекты были созданы почти одновременно: Первый объект: 2011-10-04 11: 04: 35.491114 + 02 Второй объект: 2011-10-04 11: 04: 35.540002 + 02

И код:

    try:
        project_id_param = int(project_id_param)
        project = get_object_or_404(Project.objects, pk=project_id_param)

        #check activity status of project
        try:
            is_active_param = project.projectclassification.is_active
        except:
            is_active_param = 0
        if is_active_param == True:
            is_active_param = 1
        else:
            is_active_param = 0
        #show the jqgrid table and the hour record state form
        sub_show_hr_flag = True
        if project is not None:
            hour_record_state, created = HourRecordState.objects.get_or_create(user=request.user, project=project, month=month, year=year, defaults={'state': 0, 'modified_by': request.user})
            state = hour_record_state.state
            manage_hour_record_state_form = ManageHourRecordsStateForm(instance=hour_record_state)

            if not project_id_param is False:
                work_place_query= ProjectWorkPlace.objects.filter(project=project_id_param, is_active=True)
            else:
                work_place_query = ProjectWorkPlace.objects.none()
            work_place_dropdown = JQGridDropdownSerializer().get_dropdown_value_list_workplace(work_place_query)
    except Exception, e:
        project_id_param = False
        project = None
        request.user.message_set.create(message='Chosen project could not be found.')
        return HttpResponseRedirect(reverse('my_projects'))

1 Ответ

9 голосов
/ 04 октября 2011

Что ж, это не точный ответ на ваш вопрос, но я думаю, что вам следует изменить схему базы данных и перейти на использование ограничений UNIQUE, которые помогут вам сохранить целостность данных, так как уникальность будет применяться на уровне базы данных.

Если вы заявите, что для каждого месяца, пользователя и проекта вам необходимо ровно одно состояние, ваша модель должна выглядеть примерно так (с использованием ограничения unique_together):

class HourRecordState(models.Model):
    user = models.ForeignKey(User)
    project = models.ForeignKey(Project)
    month = models.IntegerField()
    year = models.IntegerField()
    # other fields...

    class Meta:
        unique_together = ((user, project, month, year),)

Поскольку get_or_create обрабатывается django как get и create, несколько процессов при определенных условиях могут создать один и тот же объект дважды, но если вы используете unique_together an исключение будет выдано, если попытка будет сделана ....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...