def get_queryset(self):
        today = date.today()
        queryset = AktivitetDate.get_searchable().filter(
            start_date__gte=today
        ).select_related(
            'aktivitet',
            'aktivitet__organizer_forening',
        ).prefetch_related(
            'participant_groups',
            'participant_groups__participants',
            'sherpa2_participants',

            'aktivitet__counties',
            'aktivitet__municipalities',
            'aktivitet__co_organizers_forening',
            'aktivitet__organizer_forening__sites',
            'aktivitet__images',
            'aktivitet__category_tags',
        ).distinct()

        return queryset.all()
Esempio n. 2
0
def filter_aktivitet_dates(filter, user, active_forening, requested_forening):
    """
    Filters AktivitetDates based on:
    - The provided query parameters
    - The current user and their permissions
    - The currently active forening (note that this differs from the requested forening. Forening-admins may request
      aktivitetdates for a child-forening)
    Returns AktivitetDate objects.
    """
    if filter.get('kladd') == 'false':
        dates = AktivitetDate.get_searchable()
    else:
        dates = AktivitetDate.objects

    dates = dates.select_related(
        'aktivitet',
        'aktivitet__organizer_forening',
    ).prefetch_related(
        'participant_groups',
        'participant_groups__participants',
        'sherpa2_participants',
    )

    if filter.get('sok'):
        dates = dates.filter(
            Q(aktivitet__title__icontains=filter.get('sok')) |
            Q(aktivitet__code=filter.get('sok'))
        )

    today = date.today()
    if filter.get('tid') in ['denne_uke', 'neste_uke', 'neste_maned']:
        if filter.get('tid') == 'denne_uke':
            start = today - timedelta(days=today.weekday())
            end = today + timedelta(days=-start.weekday(), weeks=1)

        elif filter.get('tid') == 'neste_uke':
            start = today + timedelta(days=-today.weekday(), weeks=1)
            end = today + timedelta(days=-today.weekday(), weeks=2)

        else:
            (start_year, start_month) = divmod(today.month, 12)
            (end_year, end_month) = divmod(today.month + 1, 12)

            start = today.replace(year=today.year + start_year, month=start_month + 1, day=1)
            end = today.replace(year=today.year + end_year, month=end_month + 1, day=1)

        dates = dates.filter(start_date__gte=start, start_date__lt=end)
    elif filter.get('tid') != 'alle':
        dates = dates.filter(start_date__gte=today)

    dates = dates.order_by('start_date').distinct()

    # If the user is admin, include dates organized by the children of the active forening
    if user.is_admin_in_forening(active_forening):
        dates = dates.filter(
            Q(aktivitet__organizer_forening=requested_forening) |
            Q(aktivitet__co_organizers_forening=requested_forening) |
            Q(
                aktivitet__organizer_forening__parents=requested_forening,
                aktivitet__organizer_forening__type='turgruppe',
            ) |
            Q(
                aktivitet__co_organizers_forening__parents=requested_forening,
                aktivitet__co_organizers_forening__type='turgruppe',
            )
        )
    else:
        dates = dates.filter(
            Q(aktivitet__organizer_forening=requested_forening) |
            Q(aktivitet__co_organizers_forening=requested_forening)
        )
    return dates
Esempio n. 3
0
def filter_aktivitet_dates(filter):

    # To the next mainainer: The filter param is a mutateable query dict such that this util method
    # can split strings into lists which the template logic is dependent upon. If you find a better
    # way, please refactor this code.

    dates = AktivitetDate.get_searchable().select_related(
        'aktivitet',
        'aktivitet__organizer_forening',
    ).prefetch_related(
        'aktivitet__images',
        'aktivitet__organizer_forening__sites',
        'aktivitet__co_organizers_forening',
        'aktivitet__category_tags',
    )

    if filter.get('search', '') and len(filter['search'].strip()) > 2:
        words = filter['search'].split()

        dates = dates.filter(
            Q(reduce(lambda x, y: x & y, [
                Q(aktivitet__title__icontains=word)
                | Q(aktivitet__description__icontains=word)
                | Q(aktivitet__title_en__icontains=word)
                | Q(aktivitet__description_en__icontains=word)
                for word in words
            ]))
            | Q(aktivitet__code=filter['search'])
        )

    if filter.get('omrader', ''):
        filter['omrader'] = filter['omrader'].split(',')

        # Build the where clause to search all omrader for each filtered omrade
        # Use a list with the ANY construct repeated for each filtered omrade, and join them with OR
        constructs = ['%s = ANY ("omrader")'] * len(filter['omrader'])
        where_clause = ' OR '.join(constructs)
        dates = dates.extra(
            where=[where_clause],
            params=filter['omrader'],
        )

    if filter.get('categories', ''):
        filter['categories'] = filter['categories'].split(',')

        dates = dates.filter(aktivitet__category__in=filter['categories'])

    if filter.get('category_types', ''):
        filter['category_types'] = filter['category_types'].split(',')

        # Note that we're checking for both types and tags, and since objects may have the same tag specified twice,
        # it'll require an explicit distinct clause in our query
        dates = dates.filter(
            Q(aktivitet__category_type__in=filter['category_types']) |
            Q(aktivitet__category_tags__name__in=filter['category_types'])
        )

    # Note that the UI doesn't expose a control for the category_tags filter, but it can be used in widgets, which in
    # turn links to the full search with the same query parameters.
    if filter.get('category_tags', ''):
        filter['category_tags'] = filter['category_tags'].split(',')
        dates = dates.filter(
            aktivitet__category_tags__name__in=filter['category_tags'],
        )

    if filter.get('audiences', ''):
        filter['audiences'] = filter['audiences'].split(',')

        # Note the usage of 'overlap' here to combine multiple audiences by 'or'
        dates = dates.filter(aktivitet__audiences__overlap=filter['audiences'])

    if filter.get('difficulties', ''):
        filter['difficulties'] = filter['difficulties'].split(',')

        dates = dates.filter(aktivitet__difficulty__in=filter['difficulties'])

    try:
        if filter.get('lat_lng', '') and len(filter['lat_lng'].split(',')) == 2:
            filter['lat_lng'] = filter['lat_lng'].split(',')

            # Rule of thumb for buffer; 1 degree is about 100 km
            boundary = geos.Point(float(filter['lat_lng'][0]), float(filter['lat_lng'][1])).buffer(0.5)

            dates = dates.filter(aktivitet__start_point__within=boundary)
    except ValueError:
        pass

    # @TODO refactor to make use of django range query
    # https://docs.djangoproject.com/en/dev/ref/models/querysets/#range
    try:
        if filter.get('start_date', ''):
            dates = dates.filter(start_date__gte=datetime.strptime(filter['start_date'], "%d.%m.%Y").date())
        else:
            dates = dates.filter(start_date__gte=date.today())

        if filter.get('end_date'):
            dates = dates.filter(end_date__lte=datetime.strptime(filter['end_date'], "%d.%m.%Y").date())
    except (ValueError, KeyError):
        pass

    if filter.get('min_duration'):
        try:
            dates = dates.filter(duration_days__gte=filter['min_duration'])
        except ValueError:
            pass

    if filter.get('max_duration'):
        try:
            dates = dates.filter(duration_days__lte=filter['max_duration'])
        except ValueError:
            pass

    if filter.get('organizers', ''):
        filter['organizers'] = filter['organizers'].split(',')

        filter['foreninger'] = []
        filter['cabins'] = []

        for organizer in filter['organizers']:
            try:
                type, id = organizer.split(':')
                if type == 'forening':
                    filter['foreninger'].append(int(id))
                elif type == 'cabin':
                    filter['cabins'].append(id)
            except ValueError:
                continue

        if filter['foreninger'] or filter['cabins']:
            dates = dates.filter(
                Q(aktivitet__organizer_forening__in=filter['foreninger']) |
                Q(aktivitet__co_organizers_forening__in=filter['foreninger']) |
                Q(aktivitet__organizer_cabin__in=filter['cabins']) |
                Q(aktivitet__co_organizers_cabin__overlap=filter['cabins'])
            )

    dates = dates.distinct()

    return filter, dates
Esempio n. 4
0
def index(request):
    turledere = cache.get('admin.turleder_count')
    if turledere is None:
        turledere = Turleder.objects.only(
            # Select only the related approved forening, and only the ID from that model
            'forening_approved',
            'forening_approved__id',
        ).select_related(
            # Join the related forening into this query as we'll traverse that later
            'forening_approved',
        ).distinct(
            # The Turleder model may have >1 references to a user, so select distinctly on user
            'user',
        )

        # Make sure the lazy queryset has been evaluated before caching it
        len(turledere)

        cache.set('admin.turleder_count', turledere, 60 * 60 * 24 * 14)

    turleder_stats = {
        'total': len(turledere),
        # Filter on the local forening in code - it's prefetched, so that's much faster, and it lets us cache the
        # entire query instead of having a seperate cache key per forening
        'local': len([t for t in turledere if t.forening_approved == request.active_forening]),
    }

    aktiviteter = cache.get('admin.aktivitet_count.%s' % request.active_forening.id)
    if aktiviteter is None:
        aktiviteter = AktivitetDate.get_searchable().filter(
            Q(aktivitet__organizer_forening=request.active_forening) |
            Q(aktivitet__co_organizers_forening=request.active_forening),
            start_date__gte=date.today(),
        ).count()
        cache.set('admin.aktivitet_count', aktiviteter, 60 * 60 * 6)

    dashboard_stats = {
        'turledere': turleder_stats,
        'aktiviteter': aktiviteter,
    }

    betablog = cache.get('admin.betablog')
    BETABLOG_ITEM_COUNT = 4
    if betablog is None:
        try:
            betablog = []
            librato.increment('sherpa.requests.betablog')
            r = requests.get("http://beta.dnt.no/", params={'feed': 'rss2'})
            channel = ET.fromstring(r.content).find('channel')
            for item in channel.findall('item')[:BETABLOG_ITEM_COUNT]:
                content = item.find('description').text
                image = None
                m = re.search('<img.*?src="(.*?)" ', content)
                if m is not None:
                    image = m.group(1)
                pub_date = datetime.strptime(item.find('pubDate').text[:-6], "%a, %d %b %Y %H:%M:%S")

                betablog.append({
                    'title': item.find('title').text,
                    'link': item.find('link').text,
                    'content': content,
                    'image': image,
                    'pub_date': pub_date,
                    'is_new': pub_date > datetime.now() - timedelta(days=7),
                })
        except:
            logger.warning(
                "Kunne ikke hente innhold fra betabloggen",
                exc_info=sys.exc_info(),
                extra={'request': request}
            )

        cache.set('admin.betablog', betablog, 60 * 60 * 12)

    context = {
        'betablog': betablog,
        'dashboard_stats': dashboard_stats,
    }
    return render(request, 'central/admin/dashboard.html', context)
Esempio n. 5
0
def index(request):
    turleder_stats = cache.get('admin.turleder_count')
    if turleder_stats is None:
        turledere = Turleder.objects.only(
            # Select only the related approved forening, and only the ID from that model
            'forening_approved',
            'forening_approved__id',
        ).select_related(
            # Join the related forening into this query as we'll traverse that later
            'forening_approved',
        ).distinct(
            # The Turleder model may have >1 references to a user, so select distinctly on user
            'user',
        )

        turleder_stats = {
            'total': len(turledere),
            'all': {
                f.id: len([t for t in turledere if t.forening_approved == f])
                for f in Forening.objects.only('id')
            },
        }
        cache.set('admin.turleder_count', turleder_stats, 60 * 60 * 24 * 14)

    # Set a shortcut key for the count for the current active forening, outside of cache logic
    turleder_stats['active_forening'] = turleder_stats['all'].get(request.active_forening.id, 0)

    aktiviteter = cache.get('admin.aktivitet_count.%s' % request.active_forening.id)
    if aktiviteter is None:
        aktiviteter = AktivitetDate.get_searchable().filter(
            Q(aktivitet__organizer_forening=request.active_forening) |
            Q(aktivitet__co_organizers_forening=request.active_forening),
            start_date__gte=date.today(),
        ).count()
        cache.set('admin.aktivitet_count.%s' % request.active_forening.id, aktiviteter, 60 * 60 * 6)

    dashboard_stats = {
        'turledere': turleder_stats,
        'aktiviteter': aktiviteter,
    }

    # Get info on user announcements
    active_count = UserAnnouncement.objects.filter(
        # Set to be published before now()
        Q(pub_date__isnull=True) |
        Q(pub_date__lte=datetime.now()),

        # Set to be unpublished after now()
        Q(unpub_date__isnull=True) |
        Q(unpub_date__gt=datetime.now()),
    ).count()

    upcoming_count = UserAnnouncement.objects.filter(
        # Set to be unpublished after now()
        Q(unpub_date__isnull=True) |
        Q(unpub_date__gt=datetime.now()),

        # Set to be unpublished before now()
        pub_date__gt=datetime.now(),
    ).count()

    context = {
        'user_announcements_active_count': active_count,
        'user_announcements_upcoming_count': upcoming_count,
        'dashboard_stats': dashboard_stats,
    }
    return render(request, 'central/admin/dashboard.html', context)
    def parse(self, widget_options, site, preview_context):
        aktivitet_dates = AktivitetDate.get_searchable().filter(
            start_date__gte=date.today(),
        ).select_related(
            'aktivitet',
            'aktivitet__organizer_forening',
        ).prefetch_related(
            'aktivitet__images',
            'aktivitet__co_organizers_forening',
        )

        #
        # Note that all widget search filters should match the behavior in the standard search view. Not only for
        # consistency's sake, but also because we'll want to link from the widget to the full search with the same
        # search parameters repeated; expecting the full search to display the exact same results.
        #

        url_query_parameters = {}

        # Apply audience filters, if any
        if len(widget_options['audiences']) > 0:
            # Note the usage of 'overlap' here to combine multiple audiences by 'or'
            aktivitet_dates = aktivitet_dates.filter(aktivitet__audiences__overlap=widget_options['audiences'])
            url_query_parameters['audiences'] = ",".join(widget_options['audiences'])

        # Apply category filters, if any
        if len(widget_options['categories']) > 0:
            aktivitet_dates = aktivitet_dates.filter(
                aktivitet__category__in=widget_options['categories'],
            )
            url_query_parameters['categories'] = ",".join(widget_options['categories'])

        # Apply category type filters, if any
        if len(widget_options['category_types']) > 0:
            # Note that we're checking for both types and tags, and since objects may have the same tag specified twice,
            # it'll require an explicit distinct clause in our query
            aktivitet_dates = aktivitet_dates.filter(
                Q(aktivitet__category_type__in=widget_options['category_types']) |
                Q(aktivitet__category_tags__name__in=widget_options['category_types'])
            )
            url_query_parameters['category_types'] = ",".join(widget_options['category_types'])

        # Apply category tag filters, if any
        if len(widget_options['category_tags']) > 0:
            aktivitet_dates = aktivitet_dates.filter(
                aktivitet__category_tags__name__in=widget_options['category_tags'],
            )

            # Note that the full search UI doesn't expose a control for this parameter, so the initial page load will
            # work, but when one changes any other filter, the category_tags filter will be cleared, which is suboptimal
            url_query_parameters['category_tags'] = ",".join(widget_options['category_tags'])

        # Apply organizer filter, if any
        if len(widget_options['organizers']) > 0:
            foreninger = []
            cabins = []

            for organizer in widget_options['organizers']:
                type, id = organizer.split(':')
                if type == 'forening':
                    foreninger.append(id)
                elif type == 'cabin':
                    cabins.append(id)

            # This will always be true (since we checked organizers length above), but just to be explicit: The filter
            # should not be executed if both lists are empty.
            if len(foreninger) > 0 or len(cabins) > 0:
                aktivitet_dates = aktivitet_dates.filter(
                    Q(aktivitet__organizer_forening__in=foreninger) |
                    Q(aktivitet__co_organizers_forening__in=foreninger) |
                    Q(aktivitet__organizer_cabin__in=cabins) |
                    Q(aktivitet__co_organizers_cabin__overlap=cabins)
                )

            url_query_parameters['organizers'] = ",".join(widget_options['organizers'])

        limit = widget_options.get('limit', 50)
        aktivitet_dates = aktivitet_dates.distinct()
        total = aktivitet_dates.count()
        more_activities_count = total - limit

        aktivitet_dates = aktivitet_dates.order_by('start_date')[:limit]
        see_more_query_params = "&".join([
            "%s=%s" % (urlencode(key), urlencode(value))
            for key, value in url_query_parameters.items()
        ])

        show_images = widget_options.get('show_images', False)

        return {
            'aktivitet_dates': aktivitet_dates,
            'see_more_query_params': see_more_query_params,
            'total': total,
            'limit': limit,
            'more_activities_count': more_activities_count,
            'show_images': show_images,
        }