4141from django .http import Http404 , HttpResponse , HttpResponsePermanentRedirect
4242from ietf .idrfc .idrfc_wrapper import IdWrapper ,RfcWrapper ,IdRfcWrapper
4343from ietf .utils import normalize_draftname
44+ from django .conf import settings
4445
4546class SearchForm (forms .Form ):
4647 name = forms .CharField (required = False )
@@ -252,6 +253,206 @@ def search_query(query_original):
252253 meta ['advanced' ] = True
253254 return (results ,meta )
254255
256+ if settings .USE_DB_REDESIGN_PROXY_CLASSES :
257+ from doc .models import *
258+ from person .models import *
259+ from group .models import *
260+
261+ class SearchForm (forms .Form ):
262+ name = forms .CharField (required = False )
263+ rfcs = forms .BooleanField (required = False ,initial = True )
264+ activeDrafts = forms .BooleanField (required = False ,initial = True )
265+ oldDrafts = forms .BooleanField (required = False ,initial = False )
266+ lucky = forms .BooleanField (required = False ,initial = False )
267+
268+ by = forms .ChoiceField (choices = [(x ,x ) for x in ('author' ,'group' ,'area' ,'ad' ,'state' )], required = False , initial = 'wg' , label = 'Foobar' )
269+ author = forms .CharField (required = False )
270+ group = forms .CharField (required = False )
271+ area = forms .ModelChoiceField (Group .objects .filter (type = "area" , state = "active" ).order_by ('name' ), empty_label = "any area" , required = False )
272+ ad = forms .ChoiceField (choices = (), required = False )
273+ # FIXME: state needs a sort
274+ state = forms .ModelChoiceField (IesgDocStateName .objects .all (), empty_label = "any state" , required = False )
275+ subState = forms .ChoiceField (choices = (), required = False )
276+
277+ def __init__ (self , * args , ** kwargs ):
278+ super (SearchForm , self ).__init__ (* args , ** kwargs )
279+ responsible = Document .objects .values_list ('ad' , flat = True ).distinct ()
280+ active_ads = list (Email .objects .filter (role__name = "ad" ,
281+ role__group__type = "area" ,
282+ role__group__state = "active" )
283+ .select_related ('person' ))
284+ inactive_ads = list (Email .objects .filter (pk__in = responsible )
285+ .exclude (pk__in = [x .pk for x in active_ads ])
286+ .select_related ('person' ))
287+ extract_last_name = lambda x : x .get_name ().split (' ' )[- 1 ]
288+ active_ads .sort (key = extract_last_name )
289+ inactive_ads .sort (key = extract_last_name )
290+
291+ # FIXME: -99
292+ self .fields ['ad' ].choices = c = [('' , 'any AD' )] + [(ad .pk , ad .get_name ()) for ad in active_ads ] + [('-99' , '------------------' )] + [(ad .pk , ad .get_name ()) for ad in inactive_ads ]
293+ self .fields ['subState' ].choices = [('' , 'any substate' ), ('0' , 'no substate' )] + [(n .slug , n .name ) for n in DocInfoTagName .objects .filter (slug__in = ('point' , 'ad-f-up' , 'need-rev' , 'extpty' ))]
294+ def clean_name (self ):
295+ value = self .cleaned_data .get ('name' ,'' )
296+ return normalize_draftname (value )
297+ def clean (self ):
298+ q = self .cleaned_data
299+ # Reset query['by'] if needed
300+ for k in ('author' ,'group' ,'area' ,'ad' ):
301+ if (q ['by' ] == k ) and not q [k ]:
302+ q ['by' ] = None
303+ if (q ['by' ] == 'state' ) and not (q ['state' ] or q ['subState' ]):
304+ q ['by' ] = None
305+ # Reset other fields
306+ for k in ('author' ,'group' ,'area' ,'ad' ):
307+ if q ['by' ] != k :
308+ self .data [k ] = ""
309+ q [k ] = ""
310+ if q ['by' ] != 'state' :
311+ self .data ['state' ] = ""
312+ self .data ['subState' ] = ""
313+ q ['state' ] = ""
314+ q ['subState' ] = ""
315+ return q
316+
317+ def search_query (query_original ):
318+ query = dict (query_original .items ())
319+ drafts = query ['activeDrafts' ] or query ['oldDrafts' ]
320+ if (not drafts ) and (not query ['rfcs' ]):
321+ return ([], {})
322+
323+ # Non-ASCII strings don't match anything; this check
324+ # is currently needed to avoid complaints from MySQL.
325+ # FIXME: this should be fixed if it's still a problem
326+ for k in ['name' ,'author' ,'group' ]:
327+ try :
328+ tmp = str (query .get (k , '' ))
329+ except :
330+ query [k ] = '*NOSUCH*'
331+
332+ # Start by search InternetDrafts
333+ idresults = []
334+ rfcresults = []
335+ MAX = 500
336+
337+ docs = InternetDraft .objects .all ()
338+
339+ # name
340+ if query ["name" ]:
341+ docs = docs .filter (Q (docalias__name__icontains = query ["name" ]) |
342+ Q (title__icontains = query ["name" ])).distinct ()
343+
344+ # rfc/active/old check buttons
345+ allowed = []
346+ disallowed = []
347+
348+ def add (allow , states ):
349+ l = allowed if allow else disallowed
350+ l .extend (states )
351+
352+ add (query ["rfcs" ], ['rfc' ])
353+ add (query ["activeDrafts" ], ['active' ])
354+ add (query ["oldDrafts" ], ['repl' , 'expired' , 'auth-rm' , 'ietf-rm' ])
355+
356+ docs = docs .filter (state__in = allowed ).exclude (state__in = disallowed )
357+
358+ # radio choices
359+ by = query ["by" ]
360+ if by == "author" :
361+ # FIXME: this is full name, not last name as hinted in the HTML
362+ docs = docs .filter (authors__person__name__icontains = query ["author" ])
363+ elif by == "group" :
364+ docs = docs .filter (group__acronym = query ["group" ])
365+ elif by == "area" :
366+ docs = docs .filter (Q (group__parent = query ["area" ]) |
367+ Q (ad__role__name = "ad" ,
368+ ad__role__group = query ["area" ]))
369+ elif by == "ad" :
370+ docs = docs .filter (ad = query ["ad" ])
371+ elif by == "state" :
372+ if query ["state" ]:
373+ docs = docs .filter (iesg_state = query ["state" ])
374+ if query ["subState" ]:
375+ docs = docs .filter (tags = query ["subState" ])
376+
377+ # evaluate and fill in values with aggregate queries to avoid
378+ # too many individual queries
379+ results = list (docs .select_related ("state" , "iesg_state" , "ad" , "ad__person" , "std_level" , "intended_std_level" , "group" )[:MAX ])
380+
381+ rfc_aliases = dict (DocAlias .objects .filter (name__startswith = "rfc" , document__in = [r .pk for r in results ]).values_list ("document_id" , "name" ))
382+ # canonical name
383+ for r in results :
384+ if r .pk in rfc_aliases :
385+ r .canonical_name = rfc_aliases [r .pk ]
386+ else :
387+ r .canonical_name = r .name
388+
389+ result_map = dict ((r .pk , r ) for r in results )
390+
391+ # events
392+ event_types = ("published_rfc" ,
393+ "changed_ballot_position" ,
394+ "started_iesg_process" ,
395+ "new_revision" )
396+ for d in rfc_aliases .keys ():
397+ for e in event_types :
398+ setattr (result_map [d ], e , None )
399+
400+ for e in Event .objects .filter (doc__in = rfc_aliases .keys (), type__in = event_types ).order_by ('-time' ):
401+ r = result_map [e .doc_id ]
402+ if not getattr (r , e .type ):
403+ # sets e.g. r.published_date = e for use in proxy wrapper
404+ setattr (r , e .type , e )
405+
406+ # obsoleted/updated by
407+ for d in rfc_aliases :
408+ r = result_map [d ]
409+ r .obsoleted_by_list = []
410+ r .updated_by_list = []
411+
412+ xed_by = RelatedDocument .objects .filter (doc_alias__name__in = rfc_aliases .values (), relationship__in = ("obs" , "updates" )).select_related ('doc_alias__document_id' )
413+ rel_rfc_aliases = dict (DocAlias .objects .filter (name__startswith = "rfc" , document__in = [rel .document_id for rel in xed_by ]).values_list ('document_id' , 'name' ))
414+ for rel in xed_by :
415+ r = result_map [rel .doc_alias .document_id ]
416+ if rel .relationship_id == "obs" :
417+ attr = "obsoleted_by_list"
418+ else :
419+ attr = "updated_by_list"
420+
421+ getattr (r , attr ).append (int (rel_rfc_aliases [rel .document_id ][3 :]))
422+
423+
424+ # sort
425+ def sort_key (d ):
426+ if d .canonical_name .startswith ('rfc' ):
427+ return (2 , "%06d" % int (d .canonical_name [3 :]))
428+ elif d .state_id == "active" :
429+ return (1 , d .canonical_name )
430+ else :
431+ return (3 , d .canonical_name )
432+
433+ results .sort (key = sort_key )
434+
435+ meta = {}
436+ if len (docs ) == MAX :
437+ meta ['max' ] = MAX
438+ if query ['by' ]:
439+ meta ['advanced' ] = True
440+
441+ # finally wrap in old wrappers
442+
443+ wrapped_results = []
444+ for r in results :
445+ draft = None
446+ rfc = None
447+ if not r .name .startswith ('rfc' ):
448+ draft = IdWrapper (r )
449+ if r .name .startswith ('rfc' ) or r .pk in rfc_aliases :
450+ rfc = RfcWrapper (r )
451+ wrapped_results .append (IdRfcWrapper (draft , rfc ))
452+
453+ return (wrapped_results , meta )
454+
455+
255456def search_results (request ):
256457 if len (request .REQUEST .items ()) == 0 :
257458 return search_main (request )
@@ -288,6 +489,8 @@ def by_ad(request, name):
288489 break
289490 if not ad_id :
290491 raise Http404
492+ if settings .USE_DB_REDESIGN_PROXY_CLASSES :
493+ ad_id = i .person .email ()[1 ]
291494 form = SearchForm ({'by' :'ad' ,'ad' :ad_id ,
292495 'rfcs' :'on' , 'activeDrafts' :'on' , 'oldDrafts' :'on' })
293496 if not form .is_valid ():
@@ -298,11 +501,17 @@ def by_ad(request, name):
298501
299502@cache_page (15 * 60 ) # 15 minutes
300503def all (request ):
301- active = InternetDraft .objects .all ().filter (status = 1 ).order_by ("filename" ).values ('filename' )
302- rfc1 = InternetDraft .objects .all ().filter (status = 3 ).order_by ("filename" ).values ('filename' ,'rfc_number' )
303- rfc_numbers1 = InternetDraft .objects .all ().filter (status = 3 ).values_list ('rfc_number' , flat = True )
304- rfc2 = RfcIndex .objects .all ().exclude (rfc_number__in = rfc_numbers1 ).order_by ('rfc_number' ).values ('rfc_number' ,'draft' )
305- dead = InternetDraft .objects .all ().exclude (status__in = [1 ,3 ]).order_by ("filename" ).select_related ('status__status' )
504+ if settings .USE_DB_REDESIGN_PROXY_CLASSES :
505+ active = (dict (filename = n ) for n in InternetDraft .objects .filter (state = "active" ).order_by ("name" ).values_list ('name' , flat = True ))
506+ rfc1 = (dict (filename = d , rfc_number = int (n [3 :])) for d , n in DocAlias .objects .filter (document__state = "rfc" , name__startswith = "rfc" ).exclude (document__name__startswith = "rfc" ).order_by ("document__name" ).values_list ('document__name' ,'name' ).distinct ())
507+ rfc2 = (dict (rfc_number = r , draft = None ) for r in sorted (int (n [3 :]) for n in Document .objects .filter (name__startswith = "rfc" ).values_list ('name' , flat = True )))
508+ dead = InternetDraft .objects .exclude (state__in = ("active" , "rfc" )).select_related ("state" ).order_by ("name" )
509+ else :
510+ active = InternetDraft .objects .all ().filter (status = 1 ).order_by ("filename" ).values ('filename' )
511+ rfc1 = InternetDraft .objects .all ().filter (status = 3 ).order_by ("filename" ).values ('filename' ,'rfc_number' )
512+ rfc_numbers1 = InternetDraft .objects .all ().filter (status = 3 ).values_list ('rfc_number' , flat = True )
513+ rfc2 = RfcIndex .objects .all ().exclude (rfc_number__in = rfc_numbers1 ).order_by ('rfc_number' ).values ('rfc_number' ,'draft' )
514+ dead = InternetDraft .objects .all ().exclude (status__in = [1 ,3 ]).order_by ("filename" ).select_related ('status__status' )
306515 return render_to_response ('idrfc/all.html' , {'active' :active , 'rfc1' :rfc1 , 'rfc2' :rfc2 , 'dead' :dead }, context_instance = RequestContext (request ))
307516
308517@cache_page (15 * 60 ) # 15 minutes
0 commit comments