Maybe I'm missing something absurd, I'm not seeing, but this is my first app to study web2py. I am unable to enter the data in Table Movies, which has fields related to other tables.
The list is loaded, but it is not registered in Movies registration. Under the codes and the results.
db.py
Movie = db.define_table('movies',
Field('title','string', label = 'Title'),
Field('date_release','integer', label = 'Date Release'),
Field('duraction','integer', label = 'Duraction'),
Field('category','string','list:reference categories', label = 'Category'),
Field('actor','list:reference actors', label = 'Actor'),
Field('director','list:reference directors', label = 'Diretor'),
)
Category = db.define_table('categories',
Field('title','string', label = 'Title'),
)
validators.py
Movie.title.requires = [IS_NOT_EMPTY(), IS_NOT_IN_DB(db, 'movies.title')]
Movie.category.requires = IS_IN_DB(db, 'categories.title')
Movie.director.requires = IS_IN_DB(db, 'directors.name')
Movie.actor.requires = IS_IN_DB(db, 'actors.name')
Movie.duraction.requires = IS_INT_IN_RANGE(0, 1000)
Category.title.requires = IS_NOT_EMPTY()
movie.py
def add():
form = SQLFORM(Movie)
if form.process().accepted:
response.flash = "Successful! New movie added!"
redirect(URL('add'))
elif form.errors:
response.flash = 'Error'
else:
response.flash = 'Form, set data'
return dict(form = form)
List Load another tables - ok:
The items of list not record in DB:
The widgets displayed in the form are based on the IS_IN_DB
field validators you have specified, and there are three problems with the way you have coded them.
First, list:reference
fields, like standard reference
type fields, store the record IDs of the records they reference -- they do not store values of other fields within the referenced records. So, the second argument to the IS_IN_DB
validator should always be the ID field (e.g., categories.id
).
Second, although the field will store record IDs, you want the form widget to show some other more descriptive representation of each record, so you should specify the "label" argument of the IS_IN_DB
validator (e.g., label='%(title)s'
).
Third, list:reference
fields allow for multiple selections, so you must set the "multiple" argument of the IS_IN_DB
validator to True
. This will result in a multi-select widget in the form.
So, the resulting validator should look like this:
Movie.category.requires = IS_IN_DB(db, 'categories.id', label='%(title)s', multiple=True)
The above will allow multiple db.categories
IDs to be selected, though the form widget will display category titles rather than the actual IDs.
Now, all of the above can be made much easier if you instead define the referenced tables before the db.movies
table and specify a format
argument for each table:
Category = db.define_table('categories',
Field('title','string', label = 'Title'),
format='%(title)s')
Movie = db.define_table('movies',
...,
Field('category', 'list:reference categories', label = 'Category'),
...)
With the above code, there is no need to explicitly specify the IS_IN_DB
validator at all, as the db.movies.category
field will automatically get a default validator exactly like the one specified above (the format
attribute of the db.categories
table is used as the label
argument).
You might want to read the documentation on list:reference
fields and the IS_IN_DB
validator.
As an aside, you might consider specifying your field validators within the table definitions (via the requires
argument to Field()
), as this is more concise, keeps all schema-related details in one place, and eliminates the need to read and execute an additional model file on every request.