15

How can I get the required validator in SQLAlchemy? Actually I just wanna be confident the user filled all required field in a form. I use PostgreSQL, but it doesn't make sense, since the tables created from Objects in my models.py file:

 from sqlalchemy import (
    Column,
    Integer,
    Text,
    DateTime,
    )

from sqlalchemy.ext.declarative import declarative_base

from sqlalchemy.orm import (
    scoped_session,
    sessionmaker,
    )

from zope.sqlalchemy import ZopeTransactionExtension

from pyramid.security import (
    Allow,
    Everyone,
    )

Base = declarative_base()


class Article(Base):
    """ The SQLAlchemy declarative model class for a Article object. """
    __tablename__ = 'article'

    id = Column(Integer, primary_key=True)
    name = Column(Text, nullable=False, unique=True)
    url = Column(Text, nullable=False, unique=True)
    title = Column(Text)
    preview = Column(Text)
    content = Column(Text)
    cat_id = Column(Integer, nullable=False)
    views = Column(Integer)
    popular = Column(Integer)
    created = Column(DateTime)

    def __unicode__(self):
        return unicode(self.name)

So this nullable=False doesn't work, because the records added in any case with empty fields. I can of course set the restrictions at the database level by set name to NOT NULL for example. But there must be something about validation in SQLAlchemy isn't it? I came from yii php framework, there it's not the problem at all.

Mark Hildreth
  • 42,023
  • 11
  • 120
  • 109
James May
  • 1,371
  • 3
  • 20
  • 37
  • 4
    Keep in mind that SQLAlchemy is not designed to be a validation framework: instead, it is a database toolkit that additionally can be used as an ORM. Things like the `nullable` parameter are there to help you with getting SQLAlchemy to generate the SQL CREATE scripts (setting the column to `NOT NULL`). So, SQLAlchemy is designed to leave the validation concerns to you (using `validates` as described below), to the database itself (like using the `CheckConstraint`), or to other software (like [WTForms](http://wtforms.readthedocs.org/en/latest/)). – Mark Hildreth Dec 22 '13 at 14:44

1 Answers1

31

By empty fields I guess you mean an empty string rather than a NULL. A simple method is to add validation, e.g.:

class Article(Base):
    ...
    name = Column(Text, unique=True)
    ...

    @validates('name')
    def validate_name(self, key, value):
        assert value != ''
        return value

To implement it at a database level you could also use a check constraint, as long as the database supports it:

class Article(Base):
    ...
    name = Column(Text, CheckConstraint('name!=""')
    ...
psq
  • 367
  • 5
  • 12
aquavitae
  • 17,414
  • 11
  • 63
  • 106
  • Thank you buddy. It worked fine. But actually i have no idea how to recognize which validator has been fired in views.py ? I only can catch the AssertionError, but ther's no information about which field was wrong. – James May Dec 21 '13 at 12:28
  • 1
    So either raise a custom exception or add an error message, e.g. `assert name != '', 'Name cannot be empty'` or `if name == ''; raise NyNameError` – aquavitae Dec 21 '13 at 13:13
  • 10
    One important thing to remember, that validates decorator function only validates attributes when they are set. If you create an Article and you don't set the name in your code, then the validation function decorated will never be triggered and it will insert the record into the database without the name attribute having a value. – Zoltan Fedor Oct 09 '17 at 19:31
  • 8
    Don't use `assert value != ''` because running `python` with the `-O` option would strip out `assert` statements. https://docs.python.org/3/using/cmdline.html#cmdoption-o – Arseniy Banayev Feb 01 '20 at 16:59