Just to correct myself and register a working solution for the case:
The code below spits out the dropdown element HTML, which you can
manually insert into your SQLFORM HTML (replacing the default
dropdown) to acquire the desired result:
def gae_subject_biased_dropdown(teacher_id):
subjects = db(db.subjects.id>0).select(db.subjects.ALL)
teachers_subjects =
db(db.teachers_subjects.id>0).select(db.teachers_subjects.ALL).as_list()
ts = map(lambda x: {'teacher_id': x['teacher_id'], 'subject_id':
x['subject_id']}, teachers_subjects)
results = []
for subject in subjects:
dictkey = {'teacher_id': int(teacher_id), 'subject_id':
subject.id}
if dictkey in ts:
results.append([subject.id, subject.name,
teachers_subjects[ts.index(dictkey)]['count']])
else:
results.append([subject.id, subject.name, 0])
key = [res[0] for res in sorted(sorted(results, key=lambda x:
x[1]), key=lambda x: x[2], reverse=True)]
value = [res[1] for res in sorted(sorted(results, key=lambda x:
x[1]), key=lambda x: x[2], reverse=True)]
form = SQLFORM.factory(
Field('subject_id', label="Subject",
requires=IS_IN_SET(key, value, zero=None)))
return form[0][0]
It's damn ugly dict/list manipulation and can certainly be improved,
although possibly compromising readability.
Best regards,
Tiago Rosa
On Oct 12, 3:41 am, Tiago Rosa <[email protected]> wrote:
> Well, answering my own question, I've managed to get it to work with
> GAE with a kinda bizarre data juggling:
>
> The helper function that returns the form element to be inserted into
> the SQLFORM is now like this:
>
> def gae_subject_biased_dropdown(teacher_id):
> subjects = db(db.subjects.id>0).select(db.subjects.id,
> db.subjects.code)
> teachers_subjects =
> db(db.teachers_subjects.id>0).select(db.teachers_subjects.subject_id,
> db.teachers_subjects.teacher_id).as_list()
> results = []
> for subj in subjects:
> if {'teacher_id': int(teacher_id), 'subject_id': subj.id} in
> teachers_subjects:
> results.append([subj.id, subj.code, 1])
> else:
> results.append([subj.id, subj.code, 0])
> key = [res[0] for res in sorted(results, key=lambda x: x[2],
> reverse=True)]
> value = [res[1] for res in sorted(results, key=lambda x: x[2],
> reverse=True)]
> form = SQLFORM.factory(
> Field('subject_id', label="Subject",
> requires=IS_IN_SET(key, value,
> zero=None)))
> return form[0][0]
>
> On Oct 12, 1:15 am, Tiago Rosa <[email protected]> wrote:
>
> > An even deeper problem: how to do something like that in a GAE
> > environment? The BigTable-like datastore has a lot of query
> > restrictions.
>
> > On Oct 6, 9:25 pm, Tiago Rosa <[email protected]> wrote:
>
> > > Hello annet and Massimo!
>
> > > Thank you very much for your help! I still need some enlightenment
> > > though =)
>
> > > I've managed to make it work thanks to annet's tip. Here's how I am
> > > currently doing it:
>
> > > I have defined a helper function that takes a teacher_id and spits out
> > > the dropdown field (!) generated through annet's method:
>
> > > def subject_biased_dropdown(teacher_id):
> > > rows = db().select(db.subjects.id, db.subjects.code,
> > > left = db.teachers_subjects.on(
> > > (db.subjects.id==db.teachers_subjects.subject_id)&
> > > (db.teachers_subjects.teacher_id==teacher_id)),
> > > orderby=db.teachers_subjects.teacher_id|db.subjects.id)
> > > key = [row.id for row in rows]
> > > value = [row.name for row in rows]
> > > form = SQLFORM.factory(
> > > Field('subject_id', requires=IS_IN_SET(key,value,zero=None)))
> > > return form[0][0]
>
> > > And then, in the "evaluation/create" function of the "evaluation"
> > > controller, I replace the dropdown field in the autogenerated SQLFORM
> > > with the "biased" one that comes from the above function:
>
> > > def create():
> > > (...)
> > > form_add=SQLFORM(db.evaluations,
> > > (...)
> > > )
> > > form_add[0][0] = subject_biased_dropdown(prof_id)
> > > if form_add.accepts(request.vars, session):
> > > (...)
> > > return dict(form=form_add)
>
> > > Yes, it works, but I feel something strange about the way I'm
> > > implementing this. I guess I'm missing something obvious that would
> > > make it easier/more "best-practice-like". Defining the orderby at the
> > > model level seems like a better option, but I can't figure it out yet.
>
> > > Again, thank you very much for your help!
>
> > > Regards,
>
> > > Tiago Rosa
>
> > > On Oct 6, 2:01 pm, annet <[email protected]> wrote:
>
> > > > Massimo,
>
> > > > > you can pass orderby to IS_IN_DB
>
> > > > To which IS_IN_DB do I have to pass the orderby to get the same
> > > > result. The resultset reads like:
>
> > > > 1 1 a
> > > > 1 4 d
> > > > 1 7 9
> > > > None 2 b
> > > > None 3 c
> > > > None 5 e
> > > > None 6 f
>
> > > > The orderby: orderby=~db.teachers_subjects.teacher_id|db.subjects.id
> > > > first sorts it in reverse order by db.teachers_subjects.teacher_id and
> > > > then by db.subjects.id, to meet Tiago's requirement:
>
> > > > When creating a new evaluation for teacher t1, the items on the
> > > > subject dropdown should appear in the following order:
>
> > > > a //related
> > > > d //related
> > > > g //related
> > > > b
> > > > c
> > > > e
> > > > f
>
> > > > Annet.
>
>