Объект изменяется после его фиксации с помощью SQL Alchemy

#python #flask #sqlalchemy #flask-sqlalchemy

#python #flask #sqlalchemy #flask-sqlalchemy

Вопрос:

Возможно, я упускаю что-то очень простое, но у меня есть сайт Flask, на котором у меня есть тест для людей. В моей базе данных есть TestAttempt таблица, которая определяется следующим образом:

 class TestAttempt(db.Model, UserMixin):
    user_id = db.Column(db.Integer,db.ForeignKey(User.id, ondelete='CASCADE'), primary_key=True)
    attempt_number = db.Column(db.Integer)
    attempt_data = db.Column(db.String(1000))
    timestamps = db.Column(db.String(1000))
    score = db.Column(db.Integer)
    begin_time = db.Column(db.String(20))
  

Сайт настроен для предварительного и последующего тестирования, поэтому attempt_number поле должно быть либо 1 или 2 . У меня есть вызываемая функция get_or_create_test_attempt() , которая делает то, что написано на tin. Если у пользователя уже есть открытая попытка, она возвращается; в противном случае создается новая. Первоначально он был определен следующим образом:

 def get_or_create_test_attempt(user_id, attempt_id):
    attempt = TestAttempt.query.filter_by(user_id=user_id, attempt_number=attempt_id).first()
    if attempt == None:
        new_attempt = TestAttempt(user_id=user_id, attempt_number=attempt_id, begin_time=str(datetime.now().strftime("%m%d%Y%H%M%S")))
        db.session.add(new_attempt)
        db.session.commit()
        return new_attempt
    else:
        return attempt
  

Это не сработало: он получил первую попытку без проблем, но всякий раз, когда я указывал 2 как attempt_id , он продолжал возвращать первую. Я добавил несколько операторов печати, чтобы попытаться определить, что происходит, и рассказать немного истории:

 def get_or_create_test_attempt(user_id, attempt_id):
    print("Asked for:", user_id, attempt_id)
    attempt = TestAttempt.query.filter_by(user_id=user_id, attempt_number=attempt_id).first()
    if attempt == None:
        new_attempt = TestAttempt(user_id=user_id, attempt_number=attempt_id, begin_time=str(datetime.now().strftime("%m%d%Y%H%M%S")))
        print("Created:", new_attempt.user_id, new_attempt.attempt_number)
        db.session.add(new_attempt)
        db.session.commit()
        print("After commit:", new_attempt.user_id, new_attempt.attempt_number)
        return new_attempt
    else:
        return attempt
  

Я получил следующий вывод, когда я запрашивал с attempt_id помощью of 2 и user_id of 1160 :

 Asked for: 1160 2
Created: 1160 2
After commit: 1160 1
Recieved: 1160 1
  

ПРИМЕЧАНИЕ: я также добавил «полученную» часть после вызова функции, например:

 attempt = get_or_create_test_attempt(current_user.id, attempt_id)
print("Recieved:", attempt.user_id, attempt.attempt_number)
  

В отчаянии я попытался запустить новый запрос для объекта, который я только что создал, но он показал то же поведение:

 def get_or_create_test_attempt(user_id, attempt_id):
    print("Asked for:", user_id, attempt_id)
    attempt = TestAttempt.query.filter_by(user_id=user_id, attempt_number=attempt_id).first()
    if attempt == None:
        new_attempt = TestAttempt(user_id=user_id, attempt_number=attempt_id, begin_time=str(datetime.now().strftime("%m%d%Y%H%M%S")))
        print("Created:", new_attempt.user_id, new_attempt.attempt_number)
        db.session.add(new_attempt)
        db.session.commit()
        print("After commit:", new_attempt.user_id, new_attempt.attempt_number)
        new_attempt = TestAttempt.query.filter_by(user_id=user_id, attempt_number=attempt_id).first()
        print("After new query:", new_attempt.user_id, new_attempt.attempt_number, "tand query was fed:", user_id, attempt_id)
        return new_attempt
    else:
        return attempt
  

И вывод, сбивающий с толку:

 Asked for: 1160 2
Created: 1160 2
After commit: 1160 1
After new query: 1160 1         and query was fed: 1160 2
Recieved: 1160 1
  

Обратите внимание, что если я сначала начну посттестирование, то это будет «преобладающий» тест — если я попытаюсь получить доступ / создать попытку с attempt_number помощью of 1 , она всегда выдает попытку с attempt_number помощью of 2 . Также обратите внимание, что, даже если функция не возвращает объект corect, он создается, потому что я вижу его с правильными параметрами в базе данных.

Я понятия не имею, что может быть причиной такого поведения. Приветствуется любой ввод.

Ответ №1:

Ваш user_id столбец равен a primary_key , у вас будет только 1 запись пользователя в вашей таблице, т. Е. Вы не сможете выполнить вторую попытку с тем же user_id самым . Вы могли бы попробовать создать составной первичный ключ из ваших user_id attempt_number столбцов and .