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()
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
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
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)
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, }