emmett-framework / emmett

The web framework for inventors

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Empty select field returns empty string instead of None

SvenKeimpema opened this issue · comments

When submitting a form that has an empty select field, the Emmett framework's ORM module (emmett/orm/models.py) treats the empty string as a non-empty value. This probably occurs in the __set__ function at line 1154 where you are checking if the field is None which is not the case because the select html tag returns an empty string. Idk where the select field is parsed but it should probably need to check if it is an select html tag and then return None if nothing is selected.

Models:

class Requirement(Model):
    requirement_name = Field.string()
    description = Field.string()
    
class Taak(Model):
    #allow empty is set to true?
    refers_to({"requirement_id": "Requirement"},
              validation={'presence': True, 'allow': 'empty'})

controller:

@app.route("/add_taak")
@requires(auth.is_logged, url("/auth/login"))
async def taak():
    grid = await Taak.form()
    return dict(grid=grid)

config:

from emmett import App, url, redirect
from emmett.orm import Database
from emmett.sessions import SessionManager
from emmett.tools import Auth

app = App(__name__)
app.config.db.uri = "sqlite://storage.sqlite"
app.config.auth.hmac_key = "IJHOw2[038hr{}()Aujgf09uwWDO(00=-"
app.config.auth.single_template = True
app.config.auth.registration_verification = False

db = Database(app)
auth = Auth(app, db, user_model=User)

from .models.tables import *

db.define_models(Requirement,  Taak)

app.pipeline = [SessionManager.files(), db.pipe, auth.pipe]

auth_routes = auth.module(__name__)

I gonna inspect this carefully in the next few days.

Just a couple of things regarding the code you posted:

refers_to(
    {"requirement_id": "Requirement"},
    validation={'presence': True, 'allow': 'empty'}
)
  • validation is not a refers_to parameter. That code doesn't really do anything
  • presence set to True and allow set to empty are opposite conditions. They won't propagate correctly in the validation strategy. Also mind belongs_to and refers_to already configure presence validation for you.

quick question can refers_to already be null/None/empty by default? however that should't matter in this case because it should give an may-not-be empty exception or something then.

refers_to already won't require the field to be filled (is on the differences compared to belongs_to.
This is why I need some time to debug this, as it should work.

This is a possible fix in RowReferenceInt(helpers.py):

class RowReferenceInt(RowReferenceMixin, int):
    def __new__(cls, id, table: Table, *args: Any, **kwargs: Any):
        try:
            rv = super().__new__(cls, id, *args, **kwargs)
        except ValueError:
            return None
        int.__setattr__(rv, '_refmeta', RowReferenceMeta(table, int))
        int.__setattr__(rv, '_refrecord', None)
        return rv

this isn't a great sollution however it does work with what i have tested