sqlobject_play / file revision
summary |
shortlog |
changelog |
tags | edit |
manifest |
changeset |
file |
revisions |
annotate |
diff |
raw
m2m_versus_sqljoin.py
| author | Luke Opperman <luke@loppear.com> |
| Fri May 16 23:54:31 2008 -0500 (3 months ago) | |
| changeset 0 | 5cf57a8ce206 |
| permissions | -rw-r--r-- |
SQLObject: Using ManyToMany and SQLRelatedJoin
1 """
2 >>> sqlhub.processConnection = connectionForURI('sqlite:/:memory:')
3
4 >>> Term.createTable()
5 []
6 >>> Question.createTable(createJoinTables=False)
7 []
8 >>> tea = Term(name='Tea')
9 >>> age = Term(name='Age')
10 >>> why = Question(name='Why?')
11 >>> what = Question(name='What?')
12
13 >>> tea, age
14 (<Term 1 name='Tea'>, <Term 2 name='Age'>)
15 >>> why, what
16 (<Question 1 name='Why?'>, <Question 2 name='What?'>)
17
18
19 #### First, SQLRelatedJoin
20
21 >>> list(tea.questions_srj)
22 []
23 >>> tea.addQuestion_srj(why)
24 >>> tea.addQuestion_srj(what)
25 >>> list(tea.questions_srj)
26 [<Question 1 name='Why?'>, <Question 2 name='What?'>]
27
28 >>> tea.removeQuestion_srj(what)
29 >>> list(tea.questions_srj)
30 [<Question 1 name='Why?'>]
31
32 >>> list(why.terms_srj)
33 [<Term 1 name='Tea'>]
34
35
36 #### Second, ManyToMany
37
38 >>> list(age.questions_m2m)
39 []
40 >>> age.questions_m2m.add(why)
41 >>> age.questions_m2m.add(what)
42 >>> list(age.questions_m2m)
43 [<Question 1 name='Why?'>, <Question 2 name='What?'>]
44
45 >>> age.questions_m2m.remove(what)
46 >>> list(age.questions_m2m)
47 [<Question 1 name='Why?'>]
48
49 # Note, these are accessing the same underlying table, interchangeably
50 >>> list(why.terms_m2m)
51 [<Term 1 name='Tea'>, <Term 2 name='Age'>]
52
53 # ManyToMany also has a convenience for creating new objects
54 # related to an existing one:
55 >>> cat = what.terms_m2m.create(name='Cat')
56 >>> cat
57 <Term 3 name='Cat'>
58 >>> list(cat.questions_srj)
59 [<Question 2 name='What?'>]
60
61
62 #### Selection filtering, aggregates etc is the same for both
63 # as a SelectResults we've been forcing with list()
64
65 >>> list(why.terms_m2m.filter(Term.q.name.startswith('T')))
66 [<Term 1 name='Tea'>]
67 >>> why.terms_srj.count()
68 2
69
70 # Historical detail that should probably be cleaned up:
71 # these generate functionally-equivalent but not identical SQL clauses
72 >>> print why.terms_srj
73 SELECT term.id, term.name FROM term, question, question_term WHERE ((term.id = question_term.term_id) AND ((question_term.question_id = question.id) AND (question.id = 1)))
74 >>> print why.terms_m2m
75 SELECT term.id, term.name FROM term, question_term WHERE (((term.id) = (question_term.term_id)) AND ((question_term.question_id) = (1)))
76
77 """
78
79 from sqlobject import *
80
81
82 class Term(SQLObject):
83 name = StringCol()
84
85 questions_m2m = ManyToMany('Question')
86 questions_srj = SQLRelatedJoin('Question', addRemoveName='Question_srj')
87
88 term_questions_o2m = OneToMany('TermQuestion')
89 term_questions_smj = SQLMultipleJoin('TermQuestion')
90
91 class Question(SQLObject):
92 name = StringCol()
93
94 terms_m2m = ManyToMany('Term')
95 terms_srj = SQLRelatedJoin('Term')
96
97 question_terms_o2m = OneToMany('TermQuestion')
98 question_terms_smj = SQLMultipleJoin('TermQuestion')
99
100 class TermQuestion(SQLObject):
101 """
102 Finally, you can define a class for the intermediate table
103 that uses OneToMany / SQLMultipleJoin for the references
104 and directly create instances of it, but if you add any
105 additional columns to this table you can no longer use the
106 add/remove/create convenience methods. You can still use
107 the ManyToMany / SQLRelatedJoins to select.
108
109 This requires that we create the tables a little differently,
110 as SQLObject wants a single primary key column for its classes.
111
112 >>> TermQuestion.dropTable()
113 >>> TermQuestion.createTable()
114 []
115 >>> dog = Term(name='Dog')
116 >>> why = Question.selectBy(name='Why?').getOne()
117 >>> list(dog.term_questions_smj)
118 []
119 >>> TermQuestion(term=dog, question=why)
120 <TermQuestion 1 termID=4 questionID=1>
121 >>> list(dog.term_questions_o2m)
122 [<TermQuestion 1 termID=4 questionID=1>]
123
124 """
125 class sqlmeta:
126 table = 'question_term'
127
128 term = ForeignKey('Term')
129 question = ForeignKey('Question')
130
