emmett-framework / emmett

The web framework for inventors
BSD 3-Clause "New" or "Revised" License
1.06k stars 71 forks source link

Possible bug in database sets validator #184

Closed josejachuf closed 7 years ago

josejachuf commented 7 years ago

@gi0baro,

In w0.85 I could do this:

validation = {
    'doctor': {
        'in': {
            'dbset': lambda db: db(db.Doctor.id > 5), 
            'orderby': lambda doctor: ~doctor.rating,
            'label_field': 'title'
        }
    }
}

Where "title" is a rowatrr in "Doctor" But with w1.0 there is a: KeyError: 'title'

josejachuf commented 7 years ago

So I understand the problem is not in the validator, but in the behavior of rowatrr and the method as_list ()

Given the specific model I have:

class Provincia(Model):
    tablename = "provincias"
    nombre = Field('string', length=50)
    has_many({'localidades': 'Localidad'})
    validation = {
        'nombre': {'presence': True}
    }

class Localidad(Model):
    tablename = "localidades"
    nombre = Field('string', length=200)
    belongs_to({'provincia': 'Provincia'})
    validation = {
        'nombre': {'presence': True}
    }

    @rowattr('localidad')
    def _localidad(self, row):
        return '%s (%s)' % (row.nombre, row.provincia.nombre)

Working from the shell:

qry = (Localidad.id < 4)
rows = db(qry).select()

When we get the list we see that the rowatrr has not been injected:

rows_l = rows.as_list()
rows_l
[{'nombre': '25 de Mayo', 'provincia': 1L, 'id': 1L}, {'nombre': '3 de febrero', 'provincia': 1L, 'id': 2L}, {'nombre': 'A. Alsina', 'provincia': 1L, 'id': 3L}]

Then, if I get the first row, we see that the rowattr is injected:

rows[0].localidad
'25 de Mayo (Buenos Aires)'

rows_l = rows.as_list()
rows_l
[{'nombre': '25 de Mayo', '_localidad': '25 de Mayo (Buenos Aires)', 'provincia': 1L, 'id': 1L}, {'nombre': '3 de febrero', 'provincia': 1L, 'id': 2L}, {'nombre': 'A. Alsina', 'provincia': 1L, 'id': 3L}]

In the same way for the second record:

rows[1].localidad
'3 de febrero (Buenos Aires)'

rows_l = rows.as_list()
rows_l
[{'nombre': '25 de Mayo', '_localidad': '25 de Mayo (Buenos Aires)', 'provincia': 1L, 'id': 1L}, {'nombre': '3 de febrero', '_localidad': '3 de febrero (Buenos Aires)', 'provincia': 1L, 'id': 2L}, {'nombre': 'A. Alsina', 'provincia': 1L, 'id': 3L}]

A doubt, proque inject it with the name of the function (preceded by _) and not with the given name in the decorator.

This is the validator code items = [(r['id'], str(r['localidad'])) for (i, r) in enumerate(rows_l)] Traceback (most recent call last): File "", line 1, in KeyError: 'localidad'

josejachuf commented 7 years ago

I imagine behavior change is due to this [1]

[1] https://github.com/gi0baro/weppy/blob/1638139cd663e4d4c912e3a3d8fb8b9e4757abf0/CHANGES#L13

gi0baro commented 7 years ago

@josejachuf will inspect this accurately and release a bugfix in the next days.

gi0baro commented 7 years ago

@josejachuf this is fixed on master, will be published in 1.0.1 later today.