0

Good day to all stackoverflow web2py Guru's here....

I found this link and its 2 years old now. I have a problem and I don't know how to code it.

I have 2 Entities(Tables) and it's a M:M relationship

First table: The Instructors (Advisers) Second table: The Lists of Students

now Advisers handled many students and students have many advisers right?

so I create a third table and I named it to Student_Adviser

School Year

db.define_table('school_year',
            Field('sy',),
            Field('current_year', 'boolean'))

List of Students

db.define_table('student_list',
            Field('lastname'),
            Field('firstname'))

these are the fields in Student_Adviser

db.define_table('stud_adviser',
            Field('sy_id', 'reference school_year', label='School Year'),
            Field('adv_id', 'reference auth_user', label='Adviser'),
            Field('stud_id', 'reference student_list', label='Student', unique=True)
           )

in the controller

def getStudent():
    form = SQLFORM.grid(db.Student_List, csv=False, create=False, selectable=(need code here))
    return locals()

I ask this kind of question because it help the Advisers to get the list of students by activating multiple check boxes so after he/she choose the students he/she will click the submit button and viola all the checked data will automatically add to the Student_Adviser table. Is my idea is possible in web2py?

ADDITIONAL 1:

Please also add a code that will automatic insert also the auth_user.id who is logged-in.

Let's say when Instructor 1 auth_user.id is 1

Instructor 1 is logged-in so all the transaction he/she will do the default value of adv_id in Student_Adviser table will always be 1 and so on.

ADDITIONAL 2:

I'm getting an error when I tried to manual add the data in the Student_Adviser table using the db interface.

btw how will I post a Traceback error? the Code Sample won't work in Traceback. I can't post the error because it will destroy the format... but this is the last line of error code (please based the table in Student_Adviser).

IntegrityError: foreign key constraint failed
Community
  • 1
  • 1
MeSH
  • 101
  • 1
  • 10
  • In the grid, you are showing the Student_Adviser table, yet you seem to want to allow the selection of records (i.e., students) that are not yet in the table. Do you instead want to show a list of students, allow the adviser to select individual students, and then add a related set of records to the Student_Adviser table? – Anthony Sep 28 '15 at 14:31
  • aw! I'm sorry I didn't notice that.. yup I want the Adviser to select the students in the Student_List and after the selection is done when the submit button is clicked then all the selected students will be inserted to the Student_Adviser... I'll edit my code now. Sorry for late reply I just fell asleep. – MeSH Sep 28 '15 at 16:29
  • @Anthony I tried to manual data insert in the Student_Adviser using the SQLFORM.grid bu it give me error... please see the error on the last area of my post – MeSH Sep 28 '15 at 16:55

1 Answers1

1

Something like this should do it:

@auth.requires_login()
def getStudent():
    db.stud_adviser.sy_id.default = db.school_year(current_year=True).id
    db.stud_adviser.adv_id.default = auth.user_id
    def add_students(ids):
        for id in ids:
            db.stud_adviser.insert(stud_id=id)
    form = SQLFORM.grid(db.student_list, create=False, selectable=add_students,
                        csv=False)
    return dict(form=form)

The selectable argument is a callback function, which receives the list of record IDs selected in the grid. The add_students function supplied as that argument loops through the IDs and inserts a new record in the stud_adviser table for each one. Because the school year and adviser IDs should be the same for each record, they are set by setting the default attributes of their respective fields (for the school year, I assume you want the ID of the current school year) -- by excluding those fields from the .insert() call, the default values will be inserted automatically.

Note, to display more useful details in the grid (rather than the school year, adviser, and student record IDs), you can define the "format" attribute on each of the tables:

db.define_table('school_year',
     Field('sy'),
     Field('current_year', 'boolean'),
     format='%(sy)s')

db.define_table('student_list',
     Field('lastname'),
     Field('firstname'),
     format='%(lastname)s')

Because the db.auth_user table is defined automatically (with a default "format" attribute), you must change its "format" attribute after the fact -- so, somewhere after calling auth.define_tables():

db.auth_user._format = '%(last_name)s'

With the "format" attributes defined as above, now any reference field that references these tables will get a default "represent" attribute based on the "format" attribute of the referenced table. This will control the display of the reference field values in the grid (as well as in SQLFORMs and SQLTABLEs).

Anthony
  • 25,466
  • 3
  • 28
  • 57
  • thanks! it works! also the error gone when I will manual input the data in the db page.... I'll modify the code so that instead the school_year.id will be show it will mask (i don't know the right term for that) and the result will be the "sy" field. – MeSH Sep 29 '15 at 09:43
  • is it possible that every time the instructor retrieve the data from Student_Adviser table instead of using the ID.. it will use for: School_Year = sy (which value is "2015-16-1"), Adviser = auth_user.last_name (which value is 'Walker') and last Student = student_list.lastname (which value is "James"). – MeSH Sep 29 '15 at 14:39
  • Sure. You can define a "represent" attribute for each field that controls how it is displayed. Even easier, for *reference* fields, if you define the "format" attribute of the referenced table, you get a default "represent" attribute based on it (you also get a default `IS_IN_DB` validator). I have edited the answer to show how to do this. – Anthony Sep 29 '15 at 19:23
  • aw! I'm late.. I just post a new question since I remember that in the rule if the question has been answer and you have additional question that are not relative you must create a new one. By the way thanks for the reply I will test the code... – MeSH Sep 29 '15 at 19:35
  • the adviser and student work. But the School Year is still displaying the ID. I add the format in the db1.py plus in the function all worked but the School Year is the same.. it display the ID... By the way we can concatenate the lastname of the student and firstname in the grid? Since lastname can be the same but we can accurate identify if we put firstname. – MeSH Sep 29 '15 at 19:46
  • I got it work in the Student field. I edit your code and this is the result: format='%s, %s' % ('%(lastname)s', '%(firstname)s') and the lasname and firstname was concatenated. but the remaining problem still the School Year still it display the ID instead of the "2015-16-1" value even if I put this code "format='%(sy)s'" – MeSH Sep 29 '15 at 20:01
  • I answered you [new question](http://stackoverflow.com/a/32833280/440323). Note, `format='%s, %s' % ('%(lastname)s', '%(firstname)s')` should simply be `format='%(lastname)s, %(firstname)s'`. – Anthony Sep 30 '15 at 15:32
  • If the school year isn't showing as expected, I'm guessing it is because your code is slightly different from what you have shown in your question. For example, when defining the `sy_id` field, if you explicitly add a `requires` argument, you will lose both the default `IS_IN_DB` validator and the default `reference` attribute. If you'd like, open a separate question about that, and be sure to show your exact code. – Anthony Sep 30 '15 at 15:35
  • a quick question... I think no need to post a new question since this question is very small hope your reply it asap... in SQLFORM.grid it is possible the user will only show his/her students instead all the data in the Student_Adviser table? because when I test your code and log-in another account and I add a new student... when the process is finish I saw also the other students of the other user.... – MeSH Oct 12 '15 at 08:25
  • hope this is [clear](http://s23.postimg.org/uujji2jpn/Untitled.png) if you can't picture out what I'm trying to do. – MeSH Oct 12 '15 at 09:18
  • The short answer is that the first argument to the grid can be a DAL query rather than a whole table. For more details, it would probably be best to open a new question. – Anthony Oct 12 '15 at 12:53
  • thanks for the reply! you truly help me a lot! I'll ask a new question after 1-2 hours... I will try it myself... – MeSH Oct 12 '15 at 13:17
  • hey! I think I got the right code.... this is my code and I tried and it work! "form = SQLFORM.grid(db.stud_adviser.adv_id==auth.user_id, csv=False, create=False, details=False, editable=False)" is there any alternative code for it? or this the right code? I base my code to the pdf :) – MeSH Oct 12 '15 at 13:26