Как исправить ошибку: (psycopg2.ошибки.NotNullViolation) нулевое значение в столбце «id» нарушает ограничение not-null?

#python #postgresql #sqlalchemy

#python #postgresql #sqlalchemy

Вопрос:

Почему возникает ошибка ниже? Я знаю о db.session.add() методе, однако я хочу использовать необработанный SQL для обучения. Разве UUID не должен генерироваться автоматически? Может быть, я что-то упускаю в тексте postgresql или у меня неверный идентификатор в модели?

ошибка

 Error: (psycopg2.errors.NotNullViolation) null value in column "id" violates not-null constraint
DETAIL:  Failing row contains (null, testuser, email@test.com, pASsWorD, null, 2021-01-10 16:13:23.270353-08).
 

models.py

 from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy import DateTime
from sqlalchemy.sql import func

from .. import db

class Users(db.Model):
    __tablename__ = 'users'

    id = db.Column(
        UUID(as_uuid=True),
        primary_key=True,
        unique=True,
    )
    username = db.Column(
        db.String(120),
        unique=True,
        nullable=False
    )
    email = db.Column(
        db.String(120),
        unique=True,
        nullable=False
    )
    password = db.Column(
        db.String(120),
        nullable=False
    )
    updated_at = db.Column(
        DateTime(timezone=True),
        onupdate=func.now()
    )
    created_at = db.Column(
        DateTime(timezone=True),
        server_default=func.now()
    )
 

api.py

 from flask import Blueprint, request, jsonify
from sqlalchemy import text, exc
from types import SimpleNamespace
from ...models.users import db, Users

bp = Blueprint('api', __name__, url_prefix='/api/v1')

@bp.route('/users', methods=['POST'])
def users():
    if request.method == 'POST':
        try:
            response = dict(request.get_json())
            values = SimpleNamespace(**response)

            if all(response.values()):
                sql_insert_one = text(f"INSERT INTO users(username, email, password) VALUES ('{values.username}', '{values.email}', '{values.password}');")
                db.session.execute(sql_insert_one)
                db.session.commit()
                message = f"successfully added new user: {values.username}"
            else:
                message = f"error adding new user, values submitted: {values}"

            return jsonify(response)
        except Exception as err:
            print(f'Error: {err}') 
            return jsonify(f'"error":"{err}"')
 

Ответ №1:

Чтобы ответить на ваш вопрос «не должен ли UUID автоматически генерироваться?» Нет. Из документов postgresql: «основная база данных не включает в себя какую-либо функцию для генерации идентификаторов UUID» ссылка.

Вам нужно сгенерировать UUID самостоятельно, попробуйте uuid.

Или вы можете использовать db.Integer вместо db.UUID и SQLAlchemy сделает это последовательностью, и она автоматически сгенерирует id значение.

Комментарии:

1. sql_insert_one = text(f"INSERT INTO users(id, username, email, password) VALUES ('{uuid.uuid4().hex}', '{values.username}', '{values.email}', '{values.password}');") сработало, спасибо за вашу помощь.

Ответ №2:

В моем случае все в порядке с уровня кода. Но когда я перепроверяю запрос DDL таблицы (структура), автоинкремент недоступен на уровне таблицы.

 CREATE TABLE public.example_table (
id int4 NOT NULL,
table_name varchar(100) NULL,
created_at timestamptz(6) NOT NULL,
created_by_id int4 NULL,
CONSTRAINT "example_table_pkey" PRIMARY KEY (id)
 

);

Оно должно быть

 CREATE TABLE public.example_table (
id serial NOT NULL,
table_name varchar(100) NULL,
created_at timestamptz(6) NOT NULL,
created_by_id int4 NULL,
CONSTRAINT "example_table_pkey" PRIMARY KEY (id)
 

);

Убедитесь, что ваша структура таблицы. Это может быть полезно для кого-то