diff --git a/gracedb/api.py b/gracedb/api.py index a083859707da330f1728bd9e880ff2ad647dbc77..e7e3f988e3e9159422bdfee1da8dfff586269b9c 100644 --- a/gracedb/api.py +++ b/gracedb/api.py @@ -40,6 +40,8 @@ from django.contrib.auth.models import User as DjangoUser MAX_FAILED_OPEN_ATTEMPTS = 5 +from forms import SimpleSearchForm + class LigoAuthentication(authentication.BaseAuthentication): def authenticate(self, request): try: @@ -94,8 +96,8 @@ class EventList(APIView): Retrieve events. You may use the following parameters: * `query=Q` : use any query string as one might use on the query page. - * `limit=N` : the maximum number of events in a response. (default: 10) - * `page=N` : events starting with the (limit*(page-1))th event. (default: 1) + * `count=N` : the maximum number of events in a response. (default: 10) + * `page=N` : events starting with the (count*(page-1))th event. (default: 1) * `orderby=O` : how to order events. (default: -created) Example: @@ -106,20 +108,7 @@ class EventList(APIView): parameters, `group`, `type` and a file part, `eventFile` containing the analysis data. - Groups: `Test` `CBC` `Burst` `Stochastic` `Coherent` - - Analysis Types: - - * `LM` : Low Mass - * `HM` : High Mass - * `GRB` : GRB - * `RD` : Ringdown - * `OM` : Omega - * `Q` : Q - * `X` : X - * `CWB` : CWB - * `MBTA` : MBTA Online - * `HWINJ` : Hardware Injection + Allowable groups and analysis types are listed in the root resource. Example: `curl -X POST -F "group=Test" -F "type=LM" -F "eventFile=@coinc.xml" --insecure --cert $X509_USER_PROXY https://gracedb.ligo.org/api/events/` @@ -133,56 +122,87 @@ class EventList(APIView): authentication_classes = (LigoAuthentication,) parser_classes = (parsers.MultiPartParser,) +# XXX Need a LIGOLW renderer +# def cli_search(request): +# assert request.ligouser +# from views import assembleLigoLw +# form = SimpleSearchForm(request.POST) +# if form.is_valid(): +# query = form.cleaned_data['query'] +# objects = Event.objects.filter(query).distinct() + +# if 'ligolw' in request.POST or 'ligolw' in request.GET: +# from glue.ligolw import utils +# if objects.count() > 1000: +# return Response("Too many events.", +# status=status.HTTP_400_BAD_REQUEST) +# xmldoc = assembleLigoLw(objects) +# response = HttpResponse(mimetype='application/xml') +# response['Content-Disposition'] = 'attachment; filename=gracedb-query.xml' +# utils.write_fileobj(xmldoc, response) +# return response + + def get(self, request): """I am the GET docstring for EventList""" + query = request.QUERY_PARAMS.get("query") - limit = request.QUERY_PARAMS.get("limit", PAGINATE_BY) - page = request.QUERY_PARAMS.get("page", 1) - orderby = request.QUERY_PARAMS.get("orderby", "-created") + count = request.QUERY_PARAMS.get("count", PAGINATE_BY) + start = request.QUERY_PARAMS.get("start", 0) + sort = request.QUERY_PARAMS.get("sort", "-created") + + events = Event.objects if query: - return Response("Query not implemented", - status=status.HTTP_400_BAD_REQUEST) - page = int(page) - limit = int(limit) - first = (page-1)*limit - events = Event.objects.order_by(orderby) - count = events.count() - last = max(0, (count / limit) - 1) + form = SimpleSearchForm(request.GET) + if form.is_valid(): + cooked_query = form.cleaned_data['query'] + events = events.filter(cooked_query).distinct() + else: + return Response("Invalid query", + status=status.HTTP_400_BAD_REQUEST) + events = events.order_by(sort) + + start = int(start) + count = int(count) + numRows = events.count() + last = max(0, (count / numRows) - 1) rv = {} rv['events'] = [eventToDict(e, request=request) - for e in events[first:first+limit]] + for e in events[start:start+count]] baseuri = reverse('event-list', request=request) - d = { 'limit' : limit, 'page' : 0, "orderby": orderby } + d = { 'start' : 0, "count": count, "sort": sort } + if query: d['query'] = query rv['first'] = baseuri + "?" + urllib.urlencode(d) - d['page'] = last + d['start'] = last rv['last'] = baseuri + "?" + urllib.urlencode(d) rv['self'] = request.build_absolute_uri() - if page != last: - d['page'] = page+1 + if start != last: + d['start'] = start+1 rv['next'] = baseuri + "?" + urllib.urlencode(d) - rv['total'] = count + rv['numRows'] = events.count() return Response(rv) def post(self, request, format=None): - rv = {} form = CreateEventForm(request.POST, request.FILES) - # XXX Implement this please. - return Response("Event creation not implemented yet.", - status=status.HTTP_400_BAD_REQUEST) - if form.is_valid(): - rv['valid'] = True - rv['efile'] = dir(request.FILES['eventFile']) event, warnings = _createEventFromForm(request, form) - rv['warnings'] = warnings - rv['graceid'] = event.graceid() - else: - rv['valid'] = False - rv['error'] = "" - for key in form.errors: - # as_text() not str() otherwise we get HTML. - rv['error'] += "%s: %s\n" % (key, form.errors[key].as_text()) - return Response(rv, status=status.HTTP_201_CREATED) + if event: + response = Response( + eventToDict(event, request=request), + status=status.HTTP_201_CREATED) + response["Location"] = reverse( + 'event-detail', + args=[event.graceid()], + request=request) + return response + else: # no event created + return Response({'warnings':warnings}, + status=status.HTTP_400_BAD_REQUEST) + else: # form not valid + rv = {} + rv['errors'] = ["%s: %s" % (key, form.errors[key].as_text()) + for key in form.errors] + return Response(rv, status=status.HTTP_400_BAD_REQUEST) class EventDetail(APIView): authentication_classes = (LigoAuthentication,)