コード例 #1
0
 def get(self, request):
     tracker, create = Tracker.objects.get_or_create(user=self.request.user)
     yesterday = date.today() - timedelta(days=1)
     if not create and tracker.date <= yesterday:
         tracker.days_row = 1 if tracker.date < yesterday else tracker.days_row + 1
         create = True
     if create:
         self.add_energy(tracker.days_row)
     tracker.save()
     serializer = TrackerSerializer(data=tracker.__dict__)
     serializer.is_valid(raise_exception=True)
     return Response(data=serializer.data, status=status.HTTP_201_CREATED if create else status.HTTP_200_OK)
コード例 #2
0
 def add_event_fields(fields, event, prefix):
     dumped_event = TrackerSerializer(models.Event, request).serialize([event])[
         0
     ]
     for key, value in dumped_event['fields'].items():
         if key not in ['canonical_url', 'name', 'short', 'timezone']:
             continue
         try:
             value = DjangoJSONEncoder().default(value)
         except TypeError:
             pass
         fields[prefix + '__' + key] = value
     fields[prefix + '__datetime'] = DjangoJSONEncoder().default(
         event.datetime.astimezone(pytz.utc)
     )
     fields[prefix + '__public'] = str(event)
コード例 #3
0
 def add_run_fields(fields, run, prefix):
     dumped_run = TrackerSerializer(models.SpeedRun, request).serialize([run])[0]
     for key, value in dumped_run['fields'].items():
         if key not in [
             'canonical_url',
             'endtime',
             'name',
             'starttime',
             'display_name',
             'order',
         ]:
             continue
         try:
             value = DjangoJSONEncoder().default(value)
         except TypeError:
             pass
         fields[prefix + '__' + key] = value
     fields[prefix + '__public'] = str(run)
コード例 #4
0
 def add_parent_fields(fields, parent, prefix):
     dumped_bid = TrackerSerializer(models.Bid, request).serialize([parent])[0]
     for key, value in dumped_bid['fields'].items():
         if key not in [
             'canonical_url',
             'name',
             'state',
             'goal',
             'allowuseroptions',
             'option_max_length',
             'total',
             'count',
         ]:
             continue
         try:
             value = DjangoJSONEncoder().default(value)
         except TypeError:
             pass
         fields[prefix + '__' + key] = value
     fields[prefix + '__public'] = str(parent)
コード例 #5
0
ファイル: api.py プロジェクト: SavePointMN/donation-tracker
def search(request):
    search_params = QueryDict.copy(request.GET)
    search_type = single(search_params, 'type')
    queries = present(search_params, 'queries')
    donor_names = present(search_params, 'donor_names')
    all_comments = present(search_params, 'all_comments')
    tech_notes = present(search_params, 'tech_notes')
    Model = modelmap.get(search_type, None)
    if Model is None:
        raise KeyError('%s is not a recognized model type' % search_type)
    if queries and not request.user.has_perm('tracker.view_queries'):
        raise PermissionDenied
    # TODO: move these to a lookup table?
    if donor_names:
        if search_type != 'donor':
            raise KeyError('"donor_names" can only be applied to donor searches')
        if not request.user.has_perm('tracker.view_usernames'):
            raise PermissionDenied
    if all_comments:
        if search_type != 'donation':
            raise KeyError('"all_comments" can only be applied to donation searches')
        if not request.user.has_perm('tracker.view_comments'):
            raise PermissionDenied
    if tech_notes:
        if search_type != 'run':
            raise KeyError('"tech_notes" can only be applied to run searches')
        if not request.user.has_perm('tracker.can_view_tech_notes'):
            raise PermissionDenied

    offset = int(single(search_params, 'offset', 0))
    limit = getattr(settings, 'TRACKER_PAGINATION_LIMIT', DEFAULT_PAGINATION_LIMIT)
    limit_param = int(single(search_params, 'limit', limit))
    if limit_param > limit:
        raise ValueError('limit can not be above %d' % limit)
    if limit_param < 1:
        raise ValueError('limit must be at least 1')
    limit = min(limit, limit_param)

    qs = search_filters.run_model_query(search_type, search_params, request.user,)

    qs = qs[offset : (offset + limit)]

    # Django 3.1 doesn't like Model.Meta.ordering when combined with annotations, so this guarantees the
    # correct subset when using annotations, even if it does result in an extra query
    if search_type in annotations:
        qs = (
            Model.objects.filter(pk__in=(m.pk for m in qs))
            .annotate(**annotations[search_type])
            .order_by()
        )
    if search_type in related:
        qs = qs.select_related(*related[search_type])
    if search_type in prefetch:
        qs = qs.prefetch_related(*prefetch[search_type])

    include_fields = included_fields.get(search_type, {})

    result = TrackerSerializer(Model, request).serialize(
        qs, fields=include_fields.get('__self__', None)
    )
    objs = {o.id: o for o in qs}

    related_cache = {}

    for obj in result:
        base_obj = objs[int(obj['pk'])]
        if hasattr(base_obj, 'visible_name'):
            obj['fields']['public'] = base_obj.visible_name()
        else:
            obj['fields']['public'] = str(base_obj)
        for a in annotations.get(search_type, {}):
            func = annotation_coercions.get(search_type, {}).get(a, str)
            obj['fields'][a] = func(getattr(base_obj, a))
        for prefetched_field in prefetch.get(search_type, []):
            if '__' in prefetched_field:
                continue
            obj['fields'][prefetched_field] = [
                po.id for po in getattr(base_obj, prefetched_field).all()
            ]
        for related_field in related.get(search_type, []):
            related_object = base_obj
            for field in related_field.split('__'):
                if not related_object:
                    break
                if not related_object._meta.get_field(field).serialize:
                    related_object = None
                else:
                    related_object = getattr(related_object, field)
            if not related_object:
                continue
            if related_object not in related_cache:
                related_cache[related_object] = (
                    TrackerSerializer(type(related_object), request).serialize(
                        [related_object], fields=include_fields.get(related_field, None)
                    )
                )[0]
            related_data = related_cache[related_object]
            for field, values in related_data['fields'].items():
                if field.endswith('id'):
                    continue
                obj['fields'][related_field + '__' + field] = values
            if hasattr(related_object, 'visible_name'):
                obj['fields'][
                    related_field + '__public'
                ] = related_object.visible_name()
            else:
                obj['fields'][related_field + '__public'] = str(related_object)
        if search_type == 'donor' and not donor_names:
            donor_privacy_filter(obj['fields'])
        elif search_type == 'donation' and not all_comments:
            donation_privacy_filter(obj['fields'])
        elif search_type == 'run' and not tech_notes:
            run_privacy_filter(obj['fields'])
    resp = HttpResponse(
        json.dumps(result, ensure_ascii=False, cls=DjangoJSONEncoder),
        content_type='application/json;charset=utf-8',
    )
    if queries:
        return HttpResponse(
            json.dumps(connection.queries, ensure_ascii=False, indent=1),
            content_type='application/json;charset=utf-8',
        )
    # TODO: cache control for certain kinds of searches
    return resp