33
33
"""
34
34
from django .db .models .query import Q
35
35
from django .http import HttpResponseBadRequest , HttpResponse
36
+ from django .http import HttpResponseRedirect
36
37
37
- import datetime
38
- import json
39
- import operator
38
+ from esp . program . modules . base import ProgramModuleObj
39
+ from esp . program . modules . base import main_call , aux_call , needs_admin
40
+ from esp . web . util import render_to_response
40
41
41
- from esp .program .modules .base import ProgramModuleObj , main_call , aux_call , needs_admin
42
- from esp .cache import cache_function
43
- from esp .web .util import render_to_response
44
- from esp .utils .query_utils import nest_Q
45
-
46
- from esp .program .models import ClassSubject , ClassFlag , ClassFlagType , ClassCategories
47
- from esp .program .models .class_ import STATUS_CHOICES_DICT
42
+ from esp .program .models import ClassFlag , ClassFlagType
48
43
from esp .program .forms import ClassFlagForm
49
44
from esp .users .models import ESPUser
50
45
51
46
52
47
class ClassFlagModule (ProgramModuleObj ):
53
- doc = """ Flag classes, such as for further review. Find all classes matching certain flags, and so on. """
48
+ doc = """Flag classes, such as for further review."""
49
+
54
50
@classmethod
55
51
def module_properties (cls ):
56
52
return {
57
- "admin_title" : "Class Flags" ,
58
- "link_title" : "Manage Class Flags" ,
59
- "module_type" : "manage" ,
60
- "seq" : 100 ,
61
- }
53
+ "admin_title" : "Class Flags" ,
54
+ "link_title" : "Manage Class Flags" ,
55
+ "module_type" : "manage" ,
56
+ "seq" : 100 ,
57
+ }
62
58
63
59
class Meta :
64
60
proxy = True
65
-
61
+
66
62
def teachers (self , QObject = False ):
67
63
fts = ClassFlagType .get_flag_types (self .program )
68
64
t = {}
@@ -74,170 +70,19 @@ def teachers(self, QObject = False):
74
70
else :
75
71
t ['flag_%s' % flag_type .id ] = ESPUser .objects .filter (q ).distinct ()
76
72
return t
77
-
73
+
78
74
def teacherDesc (self ):
79
75
fts = ClassFlagType .get_flag_types (self .program )
80
76
descs = {}
81
77
for flag_type in fts :
82
78
descs ['flag_%s' % flag_type .id ] = """Teachers who have a class with the "%s" flag.""" % flag_type .name
83
79
return descs
84
80
85
- def jsonToQuerySet (self , j ):
86
- '''Takes a dict from classflags and returns a QuerySet.
87
-
88
- The dict is decoded from the json sent by the javascript in
89
- /manage///classflags/; the format is specified in the docstring of
90
- classflags() below.
91
- '''
92
- base = ClassSubject .objects .filter (parent_program = self .program )
93
- time_fmt = "%m/%d/%Y %H:%M"
94
- query_type = j ['type' ]
95
- value = j .get ('value' )
96
- if 'flag' in query_type :
97
- lookups = {}
98
- if 'id' in value :
99
- lookups ['flag_type' ] = value ['id' ]
100
- for time_type in ['created' , 'modified' ]:
101
- when = value .get (time_type + '_when' )
102
- lookup = time_type + '_time'
103
- if when == 'before' :
104
- lookup += '__lt'
105
- elif when == 'after' :
106
- lookup += '__gt'
107
- if when :
108
- lookups [lookup ] = datetime .datetime .strptime (value [time_type + '_time' ], time_fmt )
109
- if 'not' in query_type :
110
- # Due to https://code.djangoproject.com/ticket/14645, we have
111
- # to write this query a little weirdly.
112
- return base .exclude (id__in = ClassFlag .objects .filter (** lookups ).values ('subject' ))
113
- else :
114
- return base .filter (nest_Q (Q (** lookups ), 'flags' ))
115
- elif query_type == 'category' :
116
- return base .filter (category = value )
117
- elif query_type == 'not category' :
118
- return base .exclude (category = value )
119
- elif query_type == 'status' :
120
- return base .filter (status = value )
121
- elif query_type == 'not status' :
122
- return base .exclude (status = value )
123
- elif 'scheduled' in query_type :
124
- lookup = 'sections__meeting_times__isnull'
125
- if 'some sections' in query_type :
126
- # Get classes with sections with meeting times.
127
- return base .filter (** {lookup : False })
128
- elif 'not all sections' in query_type :
129
- # Get classes with sections with meeting times.
130
- return base .filter (** {lookup : True })
131
- elif 'all sections' in query_type :
132
- # Exclude classes with sections with no meeting times.
133
- return base .exclude (** {lookup : True })
134
- elif 'no sections' in query_type :
135
- # Exclude classes with sections with meeting times.
136
- return base .exclude (** {lookup : False })
137
- else :
138
- # Here value is going to be a list of subqueries. First, evaluate them.
139
- subqueries = [self .jsonToQuerySet (query_json ) for query_json in value ]
140
- if query_type == 'all' :
141
- return reduce (operator .and_ , subqueries )
142
- elif query_type == 'any' :
143
- return reduce (operator .or_ , subqueries )
144
- elif query_type == 'none' :
145
- return base .exclude (pk__in = reduce (operator .or_ , subqueries ))
146
- elif query_type == 'not all' :
147
- return base .exclude (pk__in = reduce (operator .and_ , subqueries ))
148
- else :
149
- raise ESPError ('Invalid json for flag query builder!' )
150
-
151
- def jsonToEnglish (self , j ):
152
- '''Takes a dict from classflags and returns something human-readable.
153
-
154
- The dict is decoded from the json sent by the javascript in
155
- /manage///classflags/; the format is specified in the docstring of
156
- classflags() below.
157
- '''
158
- query_type = j ['type' ]
159
- value = j .get ('value' )
160
- if 'flag' in query_type :
161
- if 'id' in value :
162
- base = (query_type [:- 4 ] + 'the flag "' +
163
- ClassFlagType .objects .get (id = value ['id' ]).name + '"' )
164
- elif 'not' in query_type :
165
- base = 'not flags'
166
- else :
167
- base = 'any flag'
168
- modifiers = []
169
- for time_type in ['created' , 'modified' ]:
170
- if time_type + '_when' in value :
171
- modifiers .append (time_type + " " +
172
- value [time_type + '_when' ] + " " +
173
- value [time_type + '_time' ])
174
- base += ' ' + ' and ' .join (modifiers )
175
- return base
176
- elif 'category' in query_type :
177
- return (query_type [:- 8 ] + 'the category "' +
178
- str (ClassCategories .objects .get (id = value )) + '"' )
179
- elif 'status' in query_type :
180
- statusname = STATUS_CHOICES_DICT [int (value )].capitalize ()
181
- return query_type [:- 6 ]+ 'the status "' + statusname + '"'
182
- elif 'scheduled' in query_type :
183
- return query_type
184
- else :
185
- subqueries = [self .jsonToEnglish (query ) for query in value ]
186
- return query_type + " of (" + ', ' .join (subqueries )+ ")"
187
-
188
81
@main_call
189
82
@needs_admin
190
83
def classflags (self , request , tl , one , two , module , extra , prog ):
191
- '''An interface to query for some boolean expression of flags.
192
-
193
- The front-end javascript will allow the user to build a query, then
194
- POST it in the form of a json. The response to said post should be the
195
- list of classes matching the flag query.
196
-
197
- The json should be a single object, with keys 'type' and 'value'. The
198
- type of 'value' depends on the value of 'type':
199
- * If 'type' is 'flag' or 'not flag', 'value' should be an object,
200
- with some or all of the keys 'id', 'created_time', 'modified_time'
201
- (all should be strings).
202
- * If 'type' is 'category', 'not category', 'status', or
203
- 'not status', 'value' should be a string.
204
- * If 'type' is 'some sections scheduled',
205
- 'not all sections scheduled', 'all sections scheduled', or
206
- 'no sections scheduled', 'value' should be omitted.
207
- * If 'type' is 'all', 'any', 'none', or 'not all', 'value' should
208
- be an array of objects of the same form.
209
- '''
210
- # Grab the data from either a GET or a POST.
211
- # We allow a GET request to make them linkable, and POST requests for
212
- # some kind of backwards-compatibility with the way the interface
213
- # previously worked.
214
- if request .method == 'GET' :
215
- if 'query' in request .GET :
216
- data = request .GET ['query' ]
217
- else :
218
- data = None
219
- else :
220
- data = request .POST ['query' ]
221
- context = {
222
- 'flag_types' : ClassFlagType .get_flag_types (self .program ),
223
- 'prog' : self .program ,
224
- }
225
- if data is None :
226
- # We should display the query builder interface.
227
- fts = ClassFlagType .get_flag_types (self .program )
228
- context ['categories' ] = self .program .class_categories .all ()
229
- return render_to_response (self .baseDir ()+ 'flag_query_builder.html' , request , context )
230
- else :
231
- # They've sent a query, let's process it.
232
- decoded = json .loads (data )
233
- # The prefetch lets us do basically all of the processing on the template level.
234
- queryset = self .jsonToQuerySet (decoded ).distinct ().order_by ('id' ).prefetch_related (
235
- 'flags' , 'flags__flag_type' , 'teachers' , 'category' , 'sections' )
236
- english = self .jsonToEnglish (decoded )
237
- context ['queryset' ]= queryset
238
- context ['english' ]= english
239
- return render_to_response (self .baseDir ()+ 'flag_results.html' , request , context )
240
-
84
+ """Deprecated, use the ClassSearchModule instead."""
85
+ return HttpResponseRedirect ('classsearch' )
241
86
242
87
@aux_call
243
88
@needs_admin
0 commit comments