def send_emails(self, recipients): """Send the emails using the templates and contexts requested.""" email_subject = self.options['subject'] email_sender = self.options['sender'] txt_template = loader.get_template(self.options['template']) context = ast.literal_eval(self.options['context']) email_txt = txt_template.render(context) emails_sent_count = 0 messages = [] for recipient in recipients: messages.append(( email_subject, email_txt, email_sender, [recipient], )) emails_sent_count += 1 if not self.options['simulate']: send_mass_mail(messages, fail_silently=False) tally_stat('pr.emails.sent', inc=emails_sent_count) logger.info("Sent %s pr emails." % emails_sent_count) else: sys.stdout.write('Simulation mode. Imagine that we just sent %s ' 'emails!\n' % emails_sent_count)
def mapper_homepage(request): if not is_bot(request): tally_stat('visualization.scotus_homepage_loaded') visualizations = SCOTUSMap.objects.filter( published=True, deleted=False, ).annotate( Count('clusters'), ).filter( # Ensures that we only show good stuff on homepage clusters__count__gt=10, ).order_by( '-date_published', '-date_modified', '-date_created', )[:2] return render_to_response( 'visualization_home.html', { 'visualizations': visualizations, 'private': False, }, RequestContext(request), )
def serve_pagerank_file(request): """Serves the bulk pagerank file from the bulk data directory.""" file_loc = settings.BULK_DATA_DIR + "external_pagerank" file_name = file_loc.split('/')[-1] try: mimetype = magic.from_file(file_loc, mime=True) except IOError: raise Http404('Unable to locate external_pagerank file in %s' % settings.BULK_DATA_DIR) response = HttpResponse() response['X-Sendfile'] = os.path.join(file_loc) response['Content-Disposition'] = 'attachment; filename="%s"' % file_name.encode('utf-8') response['Content-Type'] = mimetype tally_stat('bulk_data.pagerank.served') return response
def serve_pagerank_file(request): """Serves the bulk pagerank file from the bulk data directory.""" file_loc = settings.BULK_DATA_DIR + "external_pagerank" file_name = file_loc.split('/')[-1] try: mimetype = magic.from_file(file_loc, mime=True) except IOError: raise Http404('Unable to locate external_pagerank file in %s' % settings.BULK_DATA_DIR) response = HttpResponse() response['X-Sendfile'] = os.path.join(file_loc) response[ 'Content-Disposition'] = 'attachment; filename="%s"' % file_name.encode( 'utf-8') response['Content-Type'] = mimetype tally_stat('bulk_data.pagerank.served') return response
def serve_static_file(request, file_path=''): """Sends a static file to a user. This serves up the static case files such as the PDFs in a way that can be blocked from search engines if necessary. We do four things: - Look up the document or audio file associated with the filepath - Check if it's blocked - If blocked, we set the x-robots-tag HTTP header - Serve up the file using Apache2's xsendfile """ response = HttpResponse() file_loc = os.path.join(settings.MEDIA_ROOT, file_path.encode('utf-8')) if file_path.startswith('mp3'): item = get_object_or_404(Audio, local_path_mp3=file_path) mimetype = 'audio/mpeg' elif file_path.startswith('recap'): # Create an empty object, and set it to blocked. No need to hit the DB # since all RECAP documents are blocked. item = RECAPDocument() item.blocked = True mimetype = 'application/pdf' else: item = get_object_or_404(Opinion, local_path=file_path) item.blocked = item.cluster.blocked try: mimetype = magic.from_file(file_loc, mime=True) except IOError: raise Http404 if item.blocked: response['X-Robots-Tag'] = 'noindex, noodp, noarchive, noimageindex' if settings.DEVELOPMENT: # X-Sendfile will only confuse you in a dev env. response.content = open(file_loc, 'r').read() else: response['X-Sendfile'] = file_loc file_name = file_path.split('/')[-1] response['Content-Disposition'] = 'attachment; filename="%s"' % \ file_name.encode('utf-8') response['Content-Type'] = mimetype if not is_bot(request): tally_stat('case_page.static_file.served') return response
class Command(BaseCommand): help = 'Sends the alert emails on a real time, daily, weekly or monthly ' \ 'basis.' def __init__(self, *args, **kwargs): super(Command, self).__init__(*args, **kwargs) self.connections = { 'o': sunburnt.SolrInterface(settings.SOLR_OPINION_URL, mode='r'), 'oa': sunburnt.SolrInterface(settings.SOLR_AUDIO_URL, mode='r'), } self.options = {} self.valid_ids = {} def add_arguments(self, parser): parser.add_argument( '--rate', required=True, choices=dict(FREQUENCY).keys(), help="The rate to send emails (%s)" % ', '.join(dict(FREQUENCY).keys()), ) parser.add_argument( '--simulate', action='store_true', default=False, help='Simulate the emails that would be sent using the console ' 'backend.', ) def run_query(self, alert, rate): results = [] error = False cd = {} try: logger.info("Now running the query: %s\n" % alert.query) # Set up the data data = search_utils.get_string_to_dict(alert.query) try: del data['filed_before'] except KeyError: pass data['order_by'] = 'score desc' logger.info(" Data sent to SearchForm is: %s\n" % data) search_form = SearchForm(data) if search_form.is_valid(): cd = search_form.cleaned_data if rate == 'rt' and len(self.valid_ids[cd['type']]) == 0: # Bail out. No results will be found if no valid_ids. return error, cd['type'], results cut_off_date = get_cut_off_date(rate) if cd['type'] == 'o': cd['filed_after'] = cut_off_date elif cd['type'] == 'oa': cd['argued_after'] = cut_off_date main_params = search_utils.build_main_query(cd) main_params.update({ 'rows': '20', 'start': '0', 'hl.tag.pre': '<em><strong>', 'hl.tag.post': '</strong></em>', 'caller': 'cl_send_alerts', }) if rate == 'rt': main_params['fq'].append( 'id:(%s)' % ' OR '.join( [str(i) for i in self.valid_ids[cd['type']]]), ) results = self.connections[cd['type']].raw_query( **main_params).execute() else: logger.info(" Query for alert %s was invalid\n" " Errors from the SearchForm: %s\n" % (alert.query, search_form.errors)) error = True except: traceback.print_exc() logger.info(" Search for this alert failed: %s\n" % alert.query) error = True logger.info(" There were %s results\n" % len(results)) return error, cd.get('type'), results def send_emails(self, rate): """Send out an email to every user whose alert has a new hit for a rate. """ users = User.objects.filter(alerts__rate=rate, ).distinct() alerts_sent_count = 0 for user in users: alerts = user.alerts.filter(rate=rate) logger.info("\n\nAlerts for user '%s': %s\n" "%s\n" % (user, alerts, '*' * 40)) not_donated_enough = user.profile.total_donated_last_year < \ settings.MIN_DONATION['rt_alerts'] if not_donated_enough and rate == 'rt': logger.info('\n\nUser: %s has not donated enough for their %s ' 'RT alerts to be sent.\n' % (user, len(alerts))) continue hits = [] for alert in alerts: error, alert_type, results = self.run_query(alert, rate) if error: continue # hits is a multi-dimensional array. It consists of alerts, # paired with a list of document dicts, of the form: # [[alert1, [{hit1}, {hit2}, {hit3}]], [alert2, ...]] try: if len(results) > 0: hits.append([alert, alert_type, results]) alert.date_last_hit = now() alert.save() # elif len(results) == 0 and alert.always_send_email: # hits.append([alert, alert_type, None]) # logger.info(" Sending results for negative alert " # "'%s'\n" % alert.name) except Exception, e: traceback.print_exc() logger.info(" Search failed on this alert: %s\n%s\n" % (alert.query, e)) if len(hits) > 0: alerts_sent_count += 1 send_alert(user.profile, hits, self.options['simulate']) elif self.options['verbosity'] >= 1: logger.info(" No hits. Not sending mail for this cl.\n") if not self.options['simulate']: tally_stat('alerts.sent.%s' % rate, inc=alerts_sent_count) logger.info("Sent %s %s email alerts." % (alerts_sent_count, rate))
def show_results(request): """ This view can vary significantly, depending on how it is called: - In its most simple form, it is called via GET and without any parameters. --> This loads the homepage. - It might also be called with GET *with* parameters. --> This loads search results. - It might be called with a POST. --> This attempts to save an alert. It also has a few failure modes it needs to support: - It must react properly to an invalid alert form. - It must react properly to an invalid or failing search form. All of these paths have tests. """ # Create a search string that does not contain the page numbers get_string = search_utils.make_get_string(request) get_string_sans_alert = search_utils.make_get_string( request, ['page', 'edit_alert']) render_dict = { 'private': True, 'get_string': get_string, 'get_string_sans_alert': get_string_sans_alert, } if request.method == 'POST': # The user is trying to save an alert. alert_form = CreateAlertForm(request.POST, user=request.user) if alert_form.is_valid(): cd = alert_form.cleaned_data # save the alert if request.POST.get('edit_alert'): # check if the user can edit this, or if they are url hacking alert = get_object_or_404( Alert, pk=request.POST.get('edit_alert'), user=request.user, ) alert_form = CreateAlertForm(cd, instance=alert, user=request.user) alert_form.save() action = "edited" else: alert_form = CreateAlertForm(cd, user=request.user) alert = alert_form.save(commit=False) alert.user = request.user alert.save() action = "created" messages.add_message(request, messages.SUCCESS, 'Your alert was %s successfully.' % action) # and redirect to the alerts page return HttpResponseRedirect(reverse("profile_alerts")) else: # Invalid form. Do the search again and show them the alert form # with the errors render_dict.update(do_search(request)) render_dict.update({'alert_form': alert_form}) return render_to_response( 'search.html', render_dict, RequestContext(request), ) else: # Either a search or the homepage if len(request.GET) == 0: # No parameters --> Homepage. if not is_bot(request): tally_stat('search.homepage_loaded') # Load the render_dict with good results that can be shown in the # "Latest Cases" section render_dict.update( do_search(request, rows=5, order_by='dateFiled desc')) # Get the results from the oral arguments as well oa_dict = do_search(request, rows=5, order_by='dateArgued desc', type='oa') render_dict.update({'results_oa': oa_dict['results']}) # But give it a fresh form for the advanced search section render_dict.update({'search_form': SearchForm(request.GET)}) ten_days_ago = make_aware(datetime.today() - timedelta(days=10), utc) alerts_in_last_ten = Stat.objects.filter( name__contains='alerts.sent', date_logged__gte=ten_days_ago).aggregate( Sum('count'))['count__sum'] queries_in_last_ten = Stat.objects.filter( name='search.results', date_logged__gte=ten_days_ago).aggregate( Sum('count'))['count__sum'] bulk_in_last_ten = Stat.objects.filter( name__contains='bulk_data', date_logged__gte=ten_days_ago).aggregate( Sum('count'))['count__sum'] r = redis.StrictRedis( host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DATABASES['STATS'], ) last_ten_days = [ 'api:v3.d:%s.count' % (date.today() - timedelta(days=x)).isoformat() for x in range(0, 10) ] api_in_last_ten = sum([ int(result) for result in r.mget(*last_ten_days) if result is not None ]) users_in_last_ten = User.objects.filter( date_joined__gte=ten_days_ago).count() opinions_in_last_ten = Opinion.objects.filter( date_created__gte=ten_days_ago).count() oral_arguments_in_last_ten = Audio.objects.filter( date_created__gte=ten_days_ago).count() days_of_oa = naturalduration( Audio.objects.aggregate(Sum('duration'))['duration__sum'], as_dict=True, )['d'] viz_in_last_ten = SCOTUSMap.objects.filter( date_published__gte=ten_days_ago, published=True, ).count() visualizations = SCOTUSMap.objects.filter( published=True, deleted=False, ).annotate(Count('clusters'), ).filter( # Ensures that we only show good stuff on homepage clusters__count__gt=10, ).order_by( '-date_published', '-date_modified', '-date_created', )[:1] render_dict.update({ 'alerts_in_last_ten': alerts_in_last_ten, 'queries_in_last_ten': queries_in_last_ten, 'opinions_in_last_ten': opinions_in_last_ten, 'oral_arguments_in_last_ten': oral_arguments_in_last_ten, 'bulk_in_last_ten': bulk_in_last_ten, 'api_in_last_ten': api_in_last_ten, 'users_in_last_ten': users_in_last_ten, 'days_of_oa': days_of_oa, 'viz_in_last_ten': viz_in_last_ten, 'visualizations': visualizations, 'private': False, # VERY IMPORTANT! }) return render_to_response('homepage.html', render_dict, RequestContext(request)) else: # User placed a search or is trying to edit an alert if request.GET.get('edit_alert'): # They're editing an alert if request.user.is_anonymous(): return HttpResponseRedirect( "{path}?next={next}{encoded_params}".format( path=reverse('sign-in'), next=request.path, encoded_params=quote("?" + request.GET.urlencode()))) else: alert = get_object_or_404(Alert, pk=request.GET.get('edit_alert'), user=request.user) alert_form = CreateAlertForm( instance=alert, initial={'query': get_string_sans_alert}, user=request.user, ) else: # Just a regular search if not is_bot(request): tally_stat('search.results') # Create bare-bones alert form. alert_form = CreateAlertForm(initial={ 'query': get_string, 'rate': "dly" }, user=request.user) render_dict.update(do_search(request)) render_dict.update({'alert_form': alert_form}) return render_to_response( 'search.html', render_dict, RequestContext(request), )
def register(request): """allow only an anonymous user to register""" redirect_to = request.GET.get('next', '') if 'sign-in' in redirect_to: # thus, we don't redirect people back to the sign-in form redirect_to = '' # security checks: # Light security check -- make sure redirect_to isn't garbage. if not redirect_to or ' ' in redirect_to: redirect_to = settings.LOGIN_REDIRECT_URL # Heavier security check -- redirects to http://example.com should # not be allowed, but things like /view/?param=http://example.com # should be allowed. This regex checks if there is a '//' *before* a # question mark. elif '//' in redirect_to and re.match(r'[^\?]*//', redirect_to): redirect_to = settings.LOGIN_REDIRECT_URL if request.user.is_anonymous(): if request.method == 'POST': try: stub_account = User.objects.filter( profile__stub_account=True, ).get( email__iexact=request.POST.get('email'), ) except User.DoesNotExist: stub_account = False if stub_account: form = UserCreationFormExtended(request.POST, instance=stub_account) else: form = UserCreationFormExtended(request.POST) if form.is_valid(): cd = form.cleaned_data if not stub_account: # make a new user that is active, but has not confirmed # their email address user = User.objects.create_user(cd['username'], cd['email'], cd['password1']) up = UserProfile(user=user) else: # Upgrade the stub account to make it a regular account. user = stub_account user.set_password(cd['password1']) user.username = cd['username'] up = stub_account.profile up.stub_account = False if cd['first_name']: user.first_name = cd['first_name'] if cd['last_name']: user.last_name = cd['last_name'] user.save() # Build and assign the activation key salt = hashlib.sha1(str(random.random())).hexdigest()[:5] up.activation_key = hashlib.sha1(salt + user.username).hexdigest() up.key_expires = now() + timedelta(days=5) up.save() email = emails['confirm_your_new_account'] send_mail(email['subject'], email['body'] % (user.username, up.activation_key), email['from'], [user.email]) email = emails['new_account_created'] send_mail( email['subject'] % up.user.username, email['body'] % (up.user.get_full_name() or "Not provided", up.user.email), email['from'], email['to'], ) tally_stat('user.created') return HttpResponseRedirect( reverse('register_success') + '?next=%s' % redirect_to) else: form = UserCreationFormExtended() return render_to_response("register/register.html", { 'form': form, 'private': False }, RequestContext(request)) else: # The user is already logged in. Direct them to their settings page as # a logical fallback return HttpResponseRedirect(reverse('view_settings'))
def register(request): """allow only an anonymous user to register""" redirect_to = request.GET.get('next', '') if 'sign-in' in redirect_to: # thus, we don't redirect people back to the sign-in form redirect_to = '' # security checks: # Light security check -- make sure redirect_to isn't garbage. if not redirect_to or ' ' in redirect_to: redirect_to = settings.LOGIN_REDIRECT_URL # Heavier security check -- redirects to http://example.com should # not be allowed, but things like /view/?param=http://example.com # should be allowed. This regex checks if there is a '//' *before* a # question mark. elif '//' in redirect_to and re.match(r'[^\?]*//', redirect_to): redirect_to = settings.LOGIN_REDIRECT_URL if request.user.is_anonymous(): if request.method == 'POST': try: stub_account = User.objects.filter( profile__stub_account=True, ).get( email__iexact=request.POST.get('email'), ) except User.DoesNotExist: stub_account = False if stub_account: form = UserCreationFormExtended( request.POST, instance=stub_account ) else: form = UserCreationFormExtended(request.POST) if form.is_valid(): cd = form.cleaned_data if not stub_account: # make a new user that is active, but has not confirmed # their email address user = User.objects.create_user( cd['username'], cd['email'], cd['password1'] ) up = UserProfile(user=user) else: # Upgrade the stub account to make it a regular account. user = stub_account user.set_password(cd['password1']) user.username = cd['username'] up = stub_account.profile up.stub_account = False if cd['first_name']: user.first_name = cd['first_name'] if cd['last_name']: user.last_name = cd['last_name'] user.save() # Build and assign the activation key salt = hashlib.sha1(str(random.random())).hexdigest()[:5] up.activation_key = hashlib.sha1( salt + user.username).hexdigest() up.key_expires = now() + timedelta(days=5) up.save() email = emails['confirm_your_new_account'] send_mail( email['subject'], email['body'] % (user.username, up.activation_key), email['from'], [user.email] ) email = emails['new_account_created'] send_mail( email['subject'] % up.user.username, email['body'] % ( up.user.get_full_name() or "Not provided", up.user.email ), email['from'], email['to'], ) tally_stat('user.created') return HttpResponseRedirect(reverse('register_success') + '?next=%s' % redirect_to) else: form = UserCreationFormExtended() return render_to_response("register/register.html", {'form': form, 'private': False}, RequestContext(request)) else: # The user is already logged in. Direct them to their settings page as # a logical fallback return HttpResponseRedirect(reverse('view_settings'))
def new_visualization(request): demo_viz = SCOTUSMap.objects.filter( published=True, deleted=False, ).annotate( Count('clusters'), ).filter( # Ensures that we only show good stuff on homepage clusters__count__gt=5, clusters__count__lt=15, ).order_by( '-date_published', '-date_modified', '-date_created', )[:1] context = { 'SCDB_LATEST_CASE': settings.SCDB_LATEST_CASE.isoformat(), 'demo_viz': demo_viz, 'private': True, } if request.method == 'POST': form = VizForm(request.POST) context['form'] = form if form.is_valid(): # Process the data in form.cleaned_data cd = form.cleaned_data start, end = reverse_endpoints_if_needed(cd['cluster_start'], cd['cluster_end']) viz = SCOTUSMap( user=request.user, cluster_start=start, cluster_end=end, title=cd['title'], notes=cd['notes'], ) build_kwargs = { 'parent_authority': end, 'visited_nodes': {}, 'good_nodes': {}, 'max_hops': 3, } t1 = time.time() try: g = viz.build_nx_digraph(**build_kwargs) except TooManyNodes: try: # Try with fewer hops. build_kwargs['max_hops'] = 2 g = viz.build_nx_digraph(**build_kwargs) msg = message_dict['fewer_hops_delivered'] messages.add_message(request, msg['level'], msg['message']) except TooManyNodes: # Still too many hops. Abort. tally_stat('visualization.too_many_nodes_failure') msg = message_dict['too_many_nodes'] messages.add_message(request, msg['level'], msg['message']) return render_to_response( 'new_visualization.html', context, RequestContext(request), ) if len(g.edges()) == 0: tally_stat('visualization.too_few_nodes_failure') msg = message_dict['too_few_nodes'] messages.add_message(request, msg['level'], msg['message']) return render_to_response( 'new_visualization.html', {'form': form, 'private': True}, RequestContext(request), ) t2 = time.time() viz.generation_time = t2 - t1 viz.save() viz.add_clusters(g) j = viz.to_json(g) jv = JSONVersion(map=viz, json_data=j) jv.save() return HttpResponseRedirect(reverse( 'view_visualization', kwargs={'pk': viz.pk, 'slug': viz.slug} )) else: context['form'] = VizForm() return render_to_response( 'new_visualization.html', context, RequestContext(request), )
def show_results(request): """ This view can vary significantly, depending on how it is called: - In its most simple form, it is called via GET and without any parameters. --> This loads the homepage. - It might also be called with GET *with* parameters. --> This loads search results. - It might be called with a POST. --> This attempts to save an alert. It also has a few failure modes it needs to support: - It must react properly to an invalid alert form. - It must react properly to an invalid or failing search form. All of these paths have tests. """ # Create a search string that does not contain the page numbers get_string = make_get_string(request) get_string_sans_alert = make_get_string(request, ['page', 'edit_alert']) render_dict = { 'private': True, 'get_string': get_string, 'get_string_sans_alert': get_string_sans_alert, } if request.method == 'POST': # The user is trying to save an alert. alert_form = CreateAlertForm(request.POST, user=request.user) if alert_form.is_valid(): cd = alert_form.cleaned_data # save the alert if request.POST.get('edit_alert'): # check if the user can edit this, or if they are url hacking alert = get_object_or_404( Alert, pk=request.POST.get('edit_alert'), user=request.user, ) alert_form = CreateAlertForm(cd, instance=alert, user=request.user) alert_form.save() action = "edited" else: alert_form = CreateAlertForm(cd, user=request.user) alert = alert_form.save(commit=False) alert.user = request.user alert.save() action = "created" messages.add_message(request, messages.SUCCESS, 'Your alert was %s successfully.' % action) # and redirect to the alerts page return HttpResponseRedirect(reverse("profile_alerts")) else: # Invalid form. Do the search again and show them the alert form # with the errors render_dict.update(do_search(request)) render_dict.update({'alert_form': alert_form}) return render_to_response( 'search.html', render_dict, RequestContext(request), ) else: # Either a search or the homepage if len(request.GET) == 0: # No parameters --> Homepage. if not is_bot(request): tally_stat('search.homepage_loaded') # Load the render_dict with good results that can be shown in the # "Latest Cases" section render_dict.update(do_search(request, rows=5, order_by='dateFiled desc')) # Get the results from the oral arguments as well oa_dict = do_search(request, rows=5, order_by='dateArgued desc', type='oa') render_dict.update({'results_oa': oa_dict['results']}) # But give it a fresh form for the advanced search section render_dict.update({'search_form': SearchForm(request.GET)}) # Get a bunch of stats. render_dict.update(get_homepage_stats()) return render_to_response( 'homepage.html', render_dict, RequestContext(request) ) else: # User placed a search or is trying to edit an alert if request.GET.get('edit_alert'): # They're editing an alert if request.user.is_anonymous(): return HttpResponseRedirect( "{path}?next={next}{encoded_params}".format( path=reverse('sign-in'), next=request.path, encoded_params=quote("?" + request.GET.urlencode()) )) else: alert = get_object_or_404( Alert, pk=request.GET.get('edit_alert'), user=request.user ) alert_form = CreateAlertForm( instance=alert, initial={'query': get_string_sans_alert}, user=request.user, ) else: # Just a regular search if not is_bot(request): tally_stat('search.results') # Create bare-bones alert form. alert_form = CreateAlertForm( initial={'query': get_string, 'rate': "dly"}, user=request.user ) render_dict.update(do_search(request)) render_dict.update({'alert_form': alert_form}) return render_to_response( 'search.html', render_dict, RequestContext(request), )
def show_results(request): """ This view can vary significantly, depending on how it is called: - In its most simple form, it is called via GET and without any parameters. --> This loads the homepage. - It might also be called with GET *with* parameters. --> This loads search results. - It might be called with a POST. --> This attempts to save an alert. It also has a few failure modes it needs to support: - It must react properly to an invalid alert form. - It must react properly to an invalid or failing search form. All of these paths have tests. """ # Create a search string that does not contain the page numbers get_string = search_utils.make_get_string(request) get_string_sans_alert = search_utils.make_get_string(request, ['page', 'edit_alert']) render_dict = { 'private': True, 'get_string': get_string, 'get_string_sans_alert': get_string_sans_alert, } if request.method == 'POST': # The user is trying to save an alert. alert_form = CreateAlertForm(request.POST, user=request.user) if alert_form.is_valid(): cd = alert_form.cleaned_data # save the alert if request.POST.get('edit_alert'): # check if the user can edit this, or if they are url hacking alert = get_object_or_404( Alert, pk=request.POST.get('edit_alert'), user=request.user, ) alert_form = CreateAlertForm(cd, instance=alert, user=request.user) alert_form.save() action = "edited" else: alert_form = CreateAlertForm(cd, user=request.user) alert = alert_form.save(commit=False) alert.user = request.user alert.save() action = "created" messages.add_message(request, messages.SUCCESS, 'Your alert was %s successfully.' % action) # and redirect to the alerts page return HttpResponseRedirect(reverse("profile_alerts")) else: # Invalid form. Do the search again and show them the alert form # with the errors render_dict.update(do_search(request)) render_dict.update({'alert_form': alert_form}) return render_to_response( 'search.html', render_dict, RequestContext(request), ) else: # Either a search or the homepage if len(request.GET) == 0: # No parameters --> Homepage. if not is_bot(request): tally_stat('search.homepage_loaded') # Load the render_dict with good results that can be shown in the # "Latest Cases" section render_dict.update(do_search(request, rows=5, order_by='dateFiled desc')) # Get the results from the oral arguments as well oa_dict = do_search(request, rows=5, order_by='dateArgued desc', type='oa') render_dict.update({'results_oa': oa_dict['results']}) # But give it a fresh form for the advanced search section render_dict.update({'search_form': SearchForm(request.GET)}) ten_days_ago = make_aware(datetime.today() - timedelta(days=10), utc) alerts_in_last_ten = Stat.objects.filter( name__contains='alerts.sent', date_logged__gte=ten_days_ago ).aggregate(Sum('count'))['count__sum'] queries_in_last_ten = Stat.objects.filter( name='search.results', date_logged__gte=ten_days_ago ).aggregate(Sum('count'))['count__sum'] bulk_in_last_ten = Stat.objects.filter( name__contains='bulk_data', date_logged__gte=ten_days_ago ).aggregate(Sum('count'))['count__sum'] r = redis.StrictRedis( host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DATABASES['STATS'], ) last_ten_days = ['api:v3.d:%s.count' % (date.today() - timedelta(days=x)).isoformat() for x in range(0, 10)] api_in_last_ten = sum( [int(result) for result in r.mget(*last_ten_days) if result is not None] ) users_in_last_ten = User.objects.filter( date_joined__gte=ten_days_ago ).count() opinions_in_last_ten = Opinion.objects.filter( date_created__gte=ten_days_ago ).count() oral_arguments_in_last_ten = Audio.objects.filter( date_created__gte=ten_days_ago ).count() days_of_oa = naturalduration( Audio.objects.aggregate( Sum('duration') )['duration__sum'], as_dict=True, )['d'] viz_in_last_ten = SCOTUSMap.objects.filter( date_published__gte=ten_days_ago, published=True, ).count() visualizations = SCOTUSMap.objects.filter( published=True, deleted=False, ).annotate( Count('clusters'), ).filter( # Ensures that we only show good stuff on homepage clusters__count__gt=10, ).order_by( '-date_published', '-date_modified', '-date_created', )[:1] render_dict.update({ 'alerts_in_last_ten': alerts_in_last_ten, 'queries_in_last_ten': queries_in_last_ten, 'opinions_in_last_ten': opinions_in_last_ten, 'oral_arguments_in_last_ten': oral_arguments_in_last_ten, 'bulk_in_last_ten': bulk_in_last_ten, 'api_in_last_ten': api_in_last_ten, 'users_in_last_ten': users_in_last_ten, 'days_of_oa': days_of_oa, 'viz_in_last_ten': viz_in_last_ten, 'visualizations': visualizations, 'private': False, # VERY IMPORTANT! }) return render_to_response( 'homepage.html', render_dict, RequestContext(request) ) else: # User placed a search or is trying to edit an alert if request.GET.get('edit_alert'): # They're editing an alert if request.user.is_anonymous(): return HttpResponseRedirect( "{path}?next={next}{encoded_params}".format( path=reverse('sign-in'), next=request.path, encoded_params=quote("?" + request.GET.urlencode()) )) else: alert = get_object_or_404( Alert, pk=request.GET.get('edit_alert'), user=request.user ) alert_form = CreateAlertForm( instance=alert, initial={'query': get_string_sans_alert}, user=request.user, ) else: # Just a regular search if not is_bot(request): tally_stat('search.results') # Create bare-bones alert form. alert_form = CreateAlertForm( initial={'query': get_string, 'rate': "dly"}, user=request.user ) render_dict.update(do_search(request)) render_dict.update({'alert_form': alert_form}) return render_to_response( 'search.html', render_dict, RequestContext(request), )