0

Using web2py, I am having trouble submitting (?) a form based on a table using list:reference. I have a table db.game that references to db.game_events in one of its columns called game_event.

The form for db.game is accepted, but when I try to reach the data in the column game_events, that uses list:reference reffering to db.game_events, the column is empty according to the built in web2py grid.

I can see that the information is correctly posted to the database, showing the items in brackets in the supposedly empty column. Since I am using the built in web2py grid, I am assuming the collection of the rows is correct and that the problem lies elsewhere.

If I use the "Add record to database"-titled button in the web2py console (the black button with the plus-sign), and use the form there, the game_events column shows the items.

So; if I try to use {{=form}} in the application, the game_event-column is treated as empty, but if I use the built in "Add record to database", the information is there. The question is simply; why can I not use {{=form}} for db.game anywhere in the application, when the built in form works fine? I have tried to simply use {{=form}} and not custom.

To make it even more confusing, if I edit any game in db.game in the web2py grid, and press "submit" without altering any information, the game_event column in the rows for db.game correctly show the game_events.

I have been stuck on this forever, I really would appreciate help! Thanks.

Code in db.py

db.define_table(
    'game',
    Field('name', label='Tävlingsnamn'),
    Field('status', requires=IS_IN_SET(define_game_status),default='started'),
    Field('registration_start_date', 'date', requires = IS_DATE(format=('%Y-%m-%d')),label=T('Registrering öppnar')),
    Field('registration_end_date', 'date', requires = IS_DATE(format=('%Y-%m-%d')),label=T('Registrering stänger')),
    Field('start_date','date',requires = IS_DATE(format=('%Y-%m-%d')),label=T('Start date')),
    Field('end_date','date',requires = IS_DATE(format=('%Y-%m-%d')),label=T('End date')),
    Field('tracs_available','integer', requires=IS_IN_SET(define_track_amount), widget=div_radio_widget, label=T('Tracks')),
    Field('tracs_available_sprint','integer', requires=IS_IN_SET(define_track_amount), widget=div_radio_widget, label=T('Sprint tracks')),
    Field('game_type', requires=IS_IN_SET(define_game_type),default='Inactive', label=T('Type of event')),
    Field('description','text',label=T('Description')),
    Field('game_event',type='list:reference db.game_events', label='Tävlingsgren'),
    format = '%(name)s')

db.game.game_event.requires=IS_IN_DB(db,'game_events.id','%(name)s',multiple=True)

db.define_table(
    'event_class',
    Field('name'),
    format = '%(name)s')

db.define_table(
    'game_events',
    Field('name'),
    Field('class_name', requires=IS_IN_DB(db,db.event_class.name,'%(name)s')),
    Field('event_type', requires=IS_IN_SET(define_game_event_types)),
    format ='%(id)s')

Code in the controller registration.py

#FORM GAMES
def create_game():
    #Form handling  
    #FORM
    form = SQLFORM(db.game)
    request.vars._formname = 'game'

    form.custom.widget.name.update(_placeholder="ex Skelleftespelen") 

    #Registration of results in view            
    if form.accepts(request.vars, session, formname='game'):    
            print("accepted")
            response.flash = 'Tävlingen har skapats!'
            #game_rows = db(db.game).select(orderby=db.game.name)
            return dict(form=form)    

    elif form.errors:
        response.flash = 'form has errors' 

    return dict(form=form)

Code in the view create_game.html

  <div class="game_name">
            <h4>
                Tävling
            </h4> 
                {{=form.custom.begin}}
                Namn <div>{{=form.custom.widget.name}}</div>      
                Första anmälningsdag <div>{{=form.custom.widget.registration_start_date}}</div>
                Sista anmälningsdag <div>{{=form.custom.widget.registration_end_date}}</div>
                Första tävlingsdag <div>{{=form.custom.widget.start_date}}</div>
                Sista tävlingsdag <div>{{=form.custom.widget.end_date}}</div>
                Sort <div>{{=form.custom.widget.game_type}}</div>
                Sort <div>{{=form.custom.widget.status}}</div>         
                Löparbanor <div>{{=form.custom.widget.tracs_available}}</div>
                Sprintbanor <div>{{=form.custom.widget.tracs_available_sprint}}</div> 
                Beskrivning och/eller information <div>{{=form.custom.widget.description}}</div>          
      Grenar</br></br>
      <p style="background:#FFE066; font-weight:bold;">
          Notera: för att välja grenar måste samtliga önskade grenar att markeras med ctrl + musklick.
        </p>
                <div>{{=form.custom.widget.game_event}}</div>               
                <span id="submit_result">{{=form.custom.submit}}</span>
                {{=form.custom.end}}
    </div> 
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

0

When you define a reference or list:reference field, if you don't specify the requires attribute within the call to Field(), you will get a default requires attribute (i.e., validator) as well as a default represent attribute that controls how the field is displayed in forms and the grid. However, in order to get the default requires and represent attributes, you must define the referenced table before defining the referencing field (otherwise, the referencing field does not have enough information to create the validator and represent attributes, both of which incorporate the format attribute of the referenced table).

So, just move the definition of db.game_events so it comes before the definition of db.game. Also, in that case, there is no need to explicitly set the value of db.game.game_event.requires, as it will be assigned a default value exactly the same as the one you are assigning.

More generally, if you don't like the default representation of a field's values in forms/grids, you can always set the field's represent attribute to control the display.

As an aside, prefer type='list:reference game_events' over type='list:reference db.game_events' (the latter works but is not officially supported).

Anthony
  • 25,466
  • 3
  • 28
  • 57
  • Hm, even after I have changed the order in db.py and use type='list:reference game_events', it still does not work properly. The form submits without errors, the information is clearly in the database when I use the database administration to check, but the game_events row is still treated as if it's empty. For some reason I can still only use the web2py-console button to add games with game_events that I can reach in the controller, not a {{=form}}. This problem really baffles me... – Anna Päärni Aug 07 '16 at 10:25
  • *it's not the game_events row that is treated as empty, I mean the game_events column in the game-table. – Anna Päärni Aug 07 '16 at 10:31
  • 1
    You will need to update your question and show the code you are using. You mention using a grid, but you show no code creating or displaying a grid. You also mention a problem using `{{=form}}`, but you show no code where that `form` object is generated, nor is it clear how that is relevant if the problem is with a grid/table display (unless the `form` object is a grid). Please clarify exactly what code you are using and exactly what you see where. – Anthony Aug 07 '16 at 16:11