Exemplo n.º 1
0
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),
    )
Exemplo n.º 2
0
def view_docket(request, pk, slug):
    docket = get_object_or_404(Docket, pk=pk)
    if not is_bot(request):
        with suppress_autotime(docket, ['date_modified']):
            cached_count = docket.view_count
            docket.view_count = F('view_count') + 1
            docket.save()
            docket.view_count = cached_count + 1

    try:
        fave = Favorite.objects.get(docket_id=docket.pk, user=request.user)
    except (ObjectDoesNotExist, TypeError):
        # Not favorited or anonymous user
        favorite_form = FavoriteForm(
            initial={
                'docket_id': docket.pk,
                'name': trunc(best_case_name(docket), 100, ellipsis='...'),
            })
    else:
        favorite_form = FavoriteForm(instance=fave)

    de_list = docket.docket_entries.all().prefetch_related('recap_documents')
    form = DocketEntryFilterForm(request.GET)
    if form.is_valid():
        cd = form.cleaned_data
        if cd.get('entry_gte'):
            de_list = de_list.filter(entry_number__gte=cd['entry_gte'])
        if cd.get('entry_lte'):
            de_list = de_list.filter(entry_number__lte=cd['entry_lte'])
        if cd.get('filed_after'):
            de_list = de_list.filter(date_filed__gte=cd['filed_after'])
        if cd.get('filed_before'):
            de_list = de_list.filter(date_filed__lte=cd['filed_before'])
        if cd.get('order_by') == DocketEntryFilterForm.DESCENDING:
            de_list = de_list.order_by('-entry_number')

    paginator = Paginator(de_list, 100, orphans=5)
    page = request.GET.get('page')
    try:
        docket_entries = paginator.page(page)
    except PageNotAnInteger:
        docket_entries = paginator.page(1)
    except EmptyPage:
        docket_entries = paginator.page(paginator.num_pages)

    return render(
        request,
        'view_docket.html',
        {
            'docket': docket,
            'parties':
            docket.parties.exists(),  # Needed to show/hide parties tab.
            'docket_entries': docket_entries,
            'form': form,
            'favorite_form': favorite_form,
            'get_string': make_get_string(request),
            'timezone': COURT_TIMEZONES.get(docket.court_id, 'US/Eastern'),
            'private': docket.blocked,
        })
Exemplo n.º 3
0
def view_opinion(request, pk, _):
    """Using the cluster ID, return the cluster of opinions.

    We also test if the cluster ID is a favorite for the user, and send data
    if needed. If it's a favorite, we send the bound form for the favorite so
    it can populate the form on the page. If it is not a favorite, we send the
    unbound form.
    """
    # Look up the court, cluster, title and favorite information
    cluster = get_object_or_404(OpinionCluster, pk=pk)
    title = ", ".join([
        s for s in [
            trunc(best_case_name(cluster), 100, ellipsis="..."),
            cluster.citation_string,
        ] if s.strip()
    ])
    has_downloads = False
    for sub_opinion in cluster.sub_opinions.all():
        if sub_opinion.local_path or sub_opinion.download_url:
            has_downloads = True
            break
    get_string = make_get_string(request)

    try:
        fave = Favorite.objects.get(cluster_id=cluster.pk, user=request.user)
    except (ObjectDoesNotExist, TypeError):
        # Not favorited or anonymous user
        favorite_form = FavoriteForm(
            initial={
                "cluster_id": cluster.pk,
                "name": trunc(best_case_name(cluster), 100, ellipsis="..."),
            })
    else:
        favorite_form = FavoriteForm(instance=fave)

    citing_clusters = get_citing_clusters_with_cache(cluster, is_bot(request))

    return render(
        request,
        "view_opinion.html",
        {
            "title": title,
            "cluster": cluster,
            "has_downloads": has_downloads,
            "favorite_form": favorite_form,
            "get_string": get_string,
            "private": cluster.blocked,
            "citing_clusters": citing_clusters,
            "top_authorities": cluster.authorities_with_data[:5],
            "authorities_count": len(cluster.authorities_with_data),
        },
    )
Exemplo n.º 4
0
def view_docket(request, pk, _):
    docket = get_object_or_404(Docket, pk=pk)
    if not is_bot(request):
        docket.view_count = F('view_count') + 1
        docket.save()

    try:
        fave = Favorite.objects.get(docket_id=docket.pk, user=request.user)
    except (ObjectDoesNotExist, TypeError):
        # Not favorited or anonymous user
        favorite_form = FavoriteForm(
            initial={
                'docket_id': docket.pk,
                'name': trunc(best_case_name(docket), 100, ellipsis='...'),
            })
    else:
        favorite_form = FavoriteForm(instance=fave)

    de_list = docket.docket_entries.all()
    form = DocketEntryFilterForm(request.GET)
    if form.is_valid():
        cd = form.cleaned_data
        if cd.get('entry_gte'):
            de_list = de_list.filter(entry_number__gte=cd['entry_gte'])
        if cd.get('entry_lte'):
            de_list = de_list.filter(entry_number__lte=cd['entry_lte'])
        if cd.get('filed_after'):
            de_list = de_list.filter(date_filed__gte=cd['filed_after'])
        if cd.get('filed_before'):
            de_list = de_list.filter(date_filed__lte=cd['filed_before'])
        if cd.get('order_by') == DocketEntryFilterForm.DESCENDING:
            de_list = de_list.order_by('-entry_number')

    paginator = Paginator(de_list, 500, orphans=25)
    page = request.GET.get('page')
    try:
        docket_entries = paginator.page(page)
    except PageNotAnInteger:
        docket_entries = paginator.page(1)
    except EmptyPage:
        docket_entries = paginator.page(paginator.num_pages)

    return render(
        request, 'view_docket.html', {
            'docket': docket,
            'docket_entries': docket_entries,
            'form': form,
            'favorite_form': favorite_form,
            'get_string': make_get_string(request),
            'private': docket.blocked,
        })
Exemplo n.º 5
0
def view_docket(request, pk, _):
    docket = get_object_or_404(Docket, pk=pk)
    if not is_bot(request):
        docket.view_count = F('view_count') + 1
        docket.save()

    try:
        fave = Favorite.objects.get(docket_id=docket.pk, user=request.user)
    except (ObjectDoesNotExist, TypeError):
        # Not favorited or anonymous user
        favorite_form = FavoriteForm(initial={
            'docket_id': docket.pk,
            'name': trunc(best_case_name(docket), 100, ellipsis='...'),
        })
    else:
        favorite_form = FavoriteForm(instance=fave)

    de_list = docket.docket_entries.all()
    form = DocketEntryFilterForm(request.GET)
    if form.is_valid():
        cd = form.cleaned_data
        if cd.get('entry_gte'):
            de_list = de_list.filter(entry_number__gte=cd['entry_gte'])
        if cd.get('entry_lte'):
            de_list = de_list.filter(entry_number__lte=cd['entry_lte'])
        if cd.get('filed_after'):
            de_list = de_list.filter(date_filed__gte=cd['filed_after'])
        if cd.get('filed_before'):
            de_list = de_list.filter(date_filed__lte=cd['filed_before'])
        if cd.get('order_by') == DocketEntryFilterForm.DESCENDING:
            de_list = de_list.order_by('-entry_number')

    paginator = Paginator(de_list, 500, orphans=25)
    page = request.GET.get('page')
    try:
        docket_entries = paginator.page(page)
    except PageNotAnInteger:
        docket_entries = paginator.page(1)
    except EmptyPage:
        docket_entries = paginator.page(paginator.num_pages)

    return render(request, 'view_docket.html', {
        'docket': docket,
        'docket_entries': docket_entries,
        'form': form,
        'favorite_form': favorite_form,
        'get_string': make_get_string(request),
        'private': docket.blocked,
    })
Exemplo n.º 6
0
def financial_disclosures_fileserver(request, pk, slug, filepath):
    """Serve up the financial disclosure files."""
    response = HttpResponse()
    file_loc = os.path.join(settings.MEDIA_ROOT, filepath.encode('utf-8'))
    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
    filename = filepath.split('/')[-1]
    response['Content-Disposition'] = 'inline; filename="%s"' % \
                                      filename.encode('utf-8')
    response['Content-Type'] = magic.from_file(file_loc, mime=True)
    if not is_bot(request):
        tally_stat('financial_reports.static_file.served')
    return response
Exemplo n.º 7
0
        def wrapper(*args, **kwargs):
            t1 = time.time()
            result = f(*args, **kwargs)  # Run the view
            t2 = time.time()

            if settings.DEVELOPMENT:
                # Disable tracking during development.
                return result

            request = args[0]  # Request is always first arg.
            if check_bots and is_bot(request):
                return result

            url = request.build_absolute_uri()
            referer = request.META.get("HTTP_REFERER", "")
            url_domain = tldextract.extract(url)
            ref_domain = tldextract.extract(referer)
            if url_domain == ref_domain:
                # Referer domain is same as current. Don't count b/c it'll be
                # caught by client-side Matomo tracker already.
                return result

            try:
                # See: https://developer.matomo.org/api-reference/tracking-api
                requests.get(
                    settings.MATOMO_URL,
                    timeout=timeout,
                    params={
                        "idsite": settings.MATOMO_SITE_ID,
                        "rec": 1,  # Required but unexplained in docs.
                        "url": url,
                        "download": url,
                        "apiv": 1,
                        "urlref": referer,
                        "ua": request.META.get("HTTP_USER_AGENT", ""),
                        "gt_ms": int((t2 - t1) * 1000),  # Milliseconds
                        "send_image": 0,
                    },
                )
            except RequestException:
                logger.debug(
                    "Matomo tracking request had an error (likely "
                    "timeout?) out for URL: %s" % url
                )
            return result
Exemplo n.º 8
0
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'] = 'inline; 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
Exemplo n.º 9
0
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
Exemplo n.º 10
0
    def wrapper(*args, **kwargs):
        t1 = time.time()
        result = func(*args, **kwargs)  # Run the view
        t2 = time.time()

        if settings.DEVELOPMENT:
            # Disable tracking during development.
            return result

        request = args[0]  # Request is always first arg.
        if check_bots and is_bot(request):
            return result

        url = request.build_absolute_uri()
        referer = request.META.get('HTTP_REFERER', '')
        url_domain = tldextract.extract(url)
        ref_domain = tldextract.extract(referer)
        if url_domain == ref_domain:
            # Referer domain is same as current. Don't count b/c it'll be
            # caught by client-side Piwik tracker already.
            return result

        try:
            # See: https://developer.matomo.org/api-reference/tracking-api
            requests.get(
                settings.PIWIK_URL,
                timeout=timeout,
                verify=False,  # Our Piwik has self-signed cert.
                params={
                    'idsite': settings.PIWIK_SITE_ID,
                    'rec': 1,  # Required but unexplained in docs.
                    'url': url,
                    'download': url,
                    'apiv': 1,
                    'urlref': referer,
                    'ua': request.META.get('HTTP_USER_AGENT', ''),
                    'gt_ms': int((t2 - t1) * 1000),  # Milliseconds
                    'send_image': 0,
                },
            )
        except RequestException:
            logger.info("Piwik tracking request had an error (likely "
                        "timeout?) out for URL: %s" % url)
        return result
Exemplo n.º 11
0
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(request, 'visualization_home.html', {
        'visualizations': visualizations,
        'private': False,
    })
Exemplo n.º 12
0
def render_visualization_page(request, pk, embed):
    viz = get_object_or_404(SCOTUSMap, pk=pk)

    if not is_bot(request):
        cached_value = viz.view_count

        with suppress_autotime(viz, ["date_modified"]):
            viz.view_count = F("view_count") + 1
            viz.save()

        # To get the new value, you either need to get the item from the DB a
        # second time, or just manipulate it manually....
        viz.view_count = cached_value + 1

    status = None
    if viz.deleted:
        status = statuses.HTTP_410_GONE
    else:
        if viz.published is False and viz.user != request.user:
            # Not deleted, private and not the owner
            status = statuses.HTTP_401_UNAUTHORIZED

    if embed:
        if all([viz.published is True, viz.deleted is False]):
            # Log the referer if it's set, and the item is live.
            referer_url = request.META.get("HTTP_REFERER")
            if referer_url is not None:
                referer, created = Referer.objects.get_or_create(
                    url=referer_url,
                    map_id=viz.pk,
                )
                if created:
                    # Spawn a task to try to get the title of the page.
                    get_title.delay(referer.pk)
        template = "visualization_embedded.html"
    else:
        template = "visualization.html"
    return render(request,
                  template, {
                      "viz": viz,
                      "private": True
                  },
                  status=status)
Exemplo n.º 13
0
def mapper_homepage(request: HttpRequest) -> HttpResponse:
    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(
        request,
        "visualization_home.html",
        {"visualizations": visualizations, "private": False},
    )
Exemplo n.º 14
0
def view_docket(request, pk, slug):
    docket, context = core_docket_data(request, pk)
    if not is_bot(request):
        with suppress_autotime(docket, ['date_modified']):
            cached_count = docket.view_count
            docket.view_count = F('view_count') + 1
            docket.save()
            docket.view_count = cached_count + 1

    de_list = docket.docket_entries.all().prefetch_related('recap_documents')
    form = DocketEntryFilterForm(request.GET)
    if form.is_valid():
        cd = form.cleaned_data
        if cd.get('entry_gte'):
            de_list = de_list.filter(entry_number__gte=cd['entry_gte'])
        if cd.get('entry_lte'):
            de_list = de_list.filter(entry_number__lte=cd['entry_lte'])
        if cd.get('filed_after'):
            de_list = de_list.filter(date_filed__gte=cd['filed_after'])
        if cd.get('filed_before'):
            de_list = de_list.filter(date_filed__lte=cd['filed_before'])
        if cd.get('order_by') == DocketEntryFilterForm.DESCENDING:
            de_list = de_list.order_by('-recap_sequence_number',
                                       '-entry_number')

    paginator = Paginator(de_list, 200, orphans=10)
    page = request.GET.get('page')
    try:
        docket_entries = paginator.page(page)
    except PageNotAnInteger:
        docket_entries = paginator.page(1)
    except EmptyPage:
        docket_entries = paginator.page(paginator.num_pages)

    context.update({
        'parties': docket.parties.exists(),  # Needed to show/hide parties tab.
        'docket_entries': docket_entries,
        'form': form,
        'get_string': search_utils.make_get_string(request),
    })
    return render(request, 'view_docket.html', context)
Exemplo n.º 15
0
def view_docket(request, pk, slug):
    docket, context = core_docket_data(request, pk)
    if not is_bot(request):
        with suppress_autotime(docket, ['date_modified']):
            cached_count = docket.view_count
            docket.view_count = F('view_count') + 1
            docket.save()
            docket.view_count = cached_count + 1

    de_list = docket.docket_entries.all().prefetch_related('recap_documents')
    form = DocketEntryFilterForm(request.GET)
    if form.is_valid():
        cd = form.cleaned_data
        if cd.get('entry_gte'):
            de_list = de_list.filter(entry_number__gte=cd['entry_gte'])
        if cd.get('entry_lte'):
            de_list = de_list.filter(entry_number__lte=cd['entry_lte'])
        if cd.get('filed_after'):
            de_list = de_list.filter(date_filed__gte=cd['filed_after'])
        if cd.get('filed_before'):
            de_list = de_list.filter(date_filed__lte=cd['filed_before'])
        if cd.get('order_by') == DocketEntryFilterForm.DESCENDING:
            de_list = de_list.order_by('-recap_sequence_number',
                                       '-entry_number')

    paginator = Paginator(de_list, 200, orphans=10)
    page = request.GET.get('page')
    try:
        docket_entries = paginator.page(page)
    except PageNotAnInteger:
        docket_entries = paginator.page(1)
    except EmptyPage:
        docket_entries = paginator.page(paginator.num_pages)

    context.update({
        'parties': docket.parties.exists(),  # Needed to show/hide parties tab.
        'docket_entries': docket_entries,
        'form': form,
        'get_string': search_utils.make_get_string(request),
    })
    return render(request, 'view_docket.html', context)
Exemplo n.º 16
0
def view_docket(request, pk, slug):
    docket, context = core_docket_data(request, pk)
    if not is_bot(request):
        with suppress_autotime(docket, ["date_modified"]):
            cached_count = docket.view_count
            docket.view_count = F("view_count") + 1
            docket.save()
            docket.view_count = cached_count + 1

    de_list = docket.docket_entries.all().prefetch_related("recap_documents")
    form = DocketEntryFilterForm(request.GET)
    if form.is_valid():
        cd = form.cleaned_data
        if cd.get("entry_gte"):
            de_list = de_list.filter(entry_number__gte=cd["entry_gte"])
        if cd.get("entry_lte"):
            de_list = de_list.filter(entry_number__lte=cd["entry_lte"])
        if cd.get("filed_after"):
            de_list = de_list.filter(date_filed__gte=cd["filed_after"])
        if cd.get("filed_before"):
            de_list = de_list.filter(date_filed__lte=cd["filed_before"])
        if cd.get("order_by") == DocketEntryFilterForm.DESCENDING:
            de_list = de_list.order_by("-recap_sequence_number",
                                       "-entry_number")

    paginator = Paginator(de_list, 200, orphans=10)
    page = request.GET.get("page")
    try:
        docket_entries = paginator.page(page)
    except PageNotAnInteger:
        docket_entries = paginator.page(1)
    except EmptyPage:
        docket_entries = paginator.page(paginator.num_pages)

    context.update({
        "parties": docket.parties.exists(),  # Needed to show/hide parties tab.
        "docket_entries": docket_entries,
        "form": form,
        "get_string": make_get_string(request),
    })
    return render(request, "view_docket.html", context)
Exemplo n.º 17
0
def render_visualization_page(request, pk, embed):
    viz = get_object_or_404(SCOTUSMap, pk=pk)

    if not is_bot(request):
        cached_value = viz.view_count

        with suppress_autotime(viz, ['date_modified']):
            viz.view_count = F('view_count') + 1
            viz.save()

        # To get the new value, you either need to get the item from the DB a
        # second time, or just manipulate it manually....
        viz.view_count = cached_value + 1

    status = None
    if viz.deleted:
        status = statuses.HTTP_410_GONE
    else:
        if viz.published is False and viz.user != request.user:
            # Not deleted, private and not the owner
            status = statuses.HTTP_401_UNAUTHORIZED

    if embed:
        if all([viz.published is True, viz.deleted is False]):
            # Log the referer if it's set, and the item is live.
            referer_url = request.META.get('HTTP_REFERER')
            if referer_url is not None:
                referer, created = Referer.objects.get_or_create(
                    url=referer_url, map_id=viz.pk,
                )
                if created:
                    # Spawn a task to try to get the title of the page.
                    get_title.delay(referer.pk)
        template = 'visualization_embedded.html'
    else:
        template = 'visualization.html'
    return render(request, template, {
        'viz': viz,
        'private': True
    }, status=status)
Exemplo n.º 18
0
def increment_view_count(obj, request):
    """Increment the view count of an object in the DB

    Three tricks in this simple function:

      1. If it's a robot viewing the page, don't increment.
      2. Make sure not to update the "date_modified" fields.
      3. Do this using an atomic DB query for performance and don't reload from
         the database after the increment (which would take another query).

    :param obj: A django object containing a view_count parameter
    :param request: A django request so we can detect if it's a bot
    :return: Nothing. The obj is passed by reference
    """
    if not is_bot(request):
        cached_value = obj.view_count

        with suppress_autotime(obj, ["date_modified"]):
            obj.view_count = F("view_count") + 1
            obj.save()

        # To get the new value, you either need to get the item from the DB a
        # second time, or just manipulate it manually....
        obj.view_count = cached_value + 1
Exemplo n.º 19
0
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", "show_alert_modal"])
    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.GET.copy()))
            render_dict.update({"alert_form": alert_form})
            return render(request, "search.html", render_dict)

    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")

            # Ensure we get nothing from the future.
            mutable_GET = request.GET.copy()  # Makes it mutable
            mutable_GET["filed_before"] = date.today()

            # Load the render_dict with good results that can be shown in the
            # "Latest Cases" section
            render_dict.update(
                do_search(
                    mutable_GET,
                    rows=5,
                    override_params={"order_by": "dateFiled desc"},
                    facet=False,
                    cache_key="homepage-data-o",
                ))
            # Get the results from the oral arguments as well
            render_dict.update({
                "results_oa":
                do_search(
                    mutable_GET,
                    rows=5,
                    override_params={
                        "order_by": "dateArgued desc",
                        "type": SEARCH_TYPES.ORAL_ARGUMENT,
                    },
                    facet=False,
                    cache_key="homepage-data-oa",
                )["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.
            stats = get_homepage_stats()
            render_dict.update(stats)

            return render(request, "homepage.html", render_dict)
        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.GET.copy()))
            # Set the value to the query as a convenience
            alert_form.fields["name"].widget.attrs["value"] = render_dict[
                "search_summary_str"]
            render_dict.update({"alert_form": alert_form})
            return render(request, "search.html", render_dict)
Exemplo n.º 20
0
def get_related_clusters_with_cache(cluster, request):
    """Use Solr to get related opinions with Solr-MoreLikeThis query

    :param cluster: The cluster we're targeting
    :param request: Request object for checking if user is permitted
    :return: Tuple[List, List, Dict] Related clusters, sub-opinion IDs and URL parameters
    """

    # By default all statuses are included
    available_statuses = dict(DOCUMENT_STATUSES).values()
    url_search_params = {"stat_" + v: "on" for v in available_statuses}

    if is_bot(request):
        # If it is a bot or is not beta tester, return empty results
        return [], [], url_search_params

    conn = sunburnt.SolrInterface(settings.SOLR_OPINION_URL, mode="r")

    # Opinions that belong to the targeted cluster
    sub_opinion_ids = cluster.sub_opinions.values_list("pk", flat=True)

    # Use cache if enabled
    mlt_cache_key = "mlt-cluster:%s" % cluster.pk
    related_clusters = (caches["db_cache"].get(mlt_cache_key)
                        if settings.RELATED_USE_CACHE else None)

    if related_clusters is None:
        # Cache is empty

        # Turn list of opinion IDs into list of Q objects
        sub_opinion_queries = [conn.Q(id=sub_id) for sub_id in sub_opinion_ids]

        # Take one Q object from the list
        sub_opinion_query = sub_opinion_queries.pop()

        # OR the Q object with the ones remaining in the list
        for item in sub_opinion_queries:
            sub_opinion_query |= item

        # Set MoreLikeThis parameters
        # (see https://lucene.apache.org/solr/guide/6_6/other-parsers.html#OtherParsers-MoreLikeThisQueryParser)
        mlt_params = {
            "fields": "text",
            "count": settings.RELATED_COUNT,
            "maxqt": settings.RELATED_MLT_MAXQT,
            "mintf": settings.RELATED_MLT_MINTF,
            "minwl": settings.RELATED_MLT_MINWL,
            "maxwl": settings.RELATED_MLT_MAXWL,
            "maxdf": settings.RELATED_MLT_MAXDF,
        }

        mlt_query = (conn.query(sub_opinion_query).mlt(
            **mlt_params).field_limit(
                fields=["id", "caseName", "absolute_url"]))

        if settings.RELATED_FILTER_BY_STATUS:
            # Filter results by status (e.g., Precedential)
            mlt_query = mlt_query.filter(
                status_exact=settings.RELATED_FILTER_BY_STATUS)

            # Update URL parameters accordingly
            url_search_params = {
                "stat_" + settings.RELATED_FILTER_BY_STATUS: "on"
            }

        mlt_res = mlt_query.execute()

        if mlt_res.more_like_this is not None:
            # Only a single sub opinion
            related_clusters = mlt_res.more_like_this.docs
        elif mlt_res.more_like_these is not None:
            # Multiple sub opinions

            # Get result list for each sub opinion
            sub_docs = [
                sub_res.docs
                for sub_id, sub_res in mlt_res.more_like_these.items()
            ]

            # Merge sub results by interleaving
            # - exclude items that are sub opinions
            related_clusters = [
                item for pair in zip(*sub_docs) for item in pair
                if item["id"] not in sub_opinion_ids
            ]

            # Limit number of results
            related_clusters = related_clusters[:settings.RELATED_COUNT]
        else:
            # No MLT results are available (this should not happen)
            related_clusters = []

        cache.set(mlt_cache_key, related_clusters,
                  settings.RELATED_CACHE_TIMEOUT)

    return related_clusters, sub_opinion_ids, url_search_params
Exemplo n.º 21
0
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),
            )
Exemplo n.º 22
0
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(request, 'search.html', render_dict)

    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')

            # Ensure we get nothing from the future.
            request.GET = request.GET.copy()  # Makes it mutable
            request.GET['filed_before'] = date.today()

            homepage_cache_key = 'homepage-data'
            homepage_dict = cache.get(homepage_cache_key)
            if homepage_dict is not None:
                return render(request, 'homepage.html', homepage_dict)

            # 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',
                          facet=False))
            # Get the results from the oral arguments as well
            oa_dict = do_search(request,
                                rows=5,
                                order_by='dateArgued desc',
                                type='oa',
                                facet=False)
            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())

            six_hours = 60 * 60 * 6
            cache.set(homepage_cache_key, render_dict, six_hours)
            return render(request, 'homepage.html', render_dict)
        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))
            # Set the value to the query as a convenience
            alert_form.fields['name'].widget.attrs['value'] = \
                render_dict['search_summary_str']
            render_dict.update({'alert_form': alert_form})
            return render(request, 'search.html', render_dict)
Exemplo n.º 23
0
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),
            )
Exemplo n.º 24
0
def view_opinion(request, pk, _):
    """Using the cluster ID, return the cluster of opinions.

    We also test if the cluster ID is a favorite for the user, and send data
    if needed. If it's a favorite, we send the bound form for the favorite so
    it can populate the form on the page. If it is not a favorite, we send the
    unbound form.
    """
    # Look up the court, cluster, title and favorite information
    cluster = get_object_or_404(OpinionCluster, pk=pk)
    title = ', '.join([s for s in [
        trunc(best_case_name(cluster), 100, ellipsis="..."),
        cluster.citation_string,
    ] if s.strip()])
    has_downloads = False
    for sub_opinion in cluster.sub_opinions.all():
        if sub_opinion.local_path or sub_opinion.download_url:
            has_downloads = True
            break
    get_string = search_utils.make_get_string(request)

    try:
        fave = Favorite.objects.get(cluster_id=cluster.pk, user=request.user)
    except (ObjectDoesNotExist, TypeError):
        # Not favorited or anonymous user
        favorite_form = FavoriteForm(initial={
            'cluster_id': cluster.pk,
            'name': trunc(best_case_name(cluster), 100, ellipsis='...'),
        })
    else:
        favorite_form = FavoriteForm(instance=fave)

    if not is_bot(request):
        # Get the citing results from Solr for speed. Only do this for humans
        # to save on disk usage.
        conn = sunburnt.SolrInterface(settings.SOLR_OPINION_URL, mode='r')
        q = {
            'q': 'cites:({ids})'.format(
                ids=' OR '.join([str(pk) for pk in
                                 (cluster.sub_opinions
                                  .values_list('pk', flat=True))])
            ),
            'rows': 5,
            'start': 0,
            'sort': 'citeCount desc',
            'caller': 'view_opinion',
        }
        citing_clusters = conn.raw_query(**q).execute()
    else:
        citing_clusters = None

    return render(request, 'view_opinion.html', {
        'title': title,
        'cluster': cluster,
        'has_downloads': has_downloads,
        'favorite_form': favorite_form,
        'get_string': get_string,
        'private': cluster.blocked,
        'citing_clusters': citing_clusters,
        'top_authorities': cluster.authorities[:5],
    })
Exemplo n.º 25
0
def view_opinion(request, pk, _):
    """Using the cluster ID, return the cluster of opinions.

    We also test if the cluster ID is a favorite for the user, and send data
    if needed. If it's a favorite, we send the bound form for the favorite so
    it can populate the form on the page. If it is not a favorite, we send the
    unbound form.
    """
    # Look up the court, cluster, title and favorite information
    cluster = get_object_or_404(OpinionCluster, pk=pk)
    title = ", ".join([
        s for s in [
            trunc(best_case_name(cluster), 100, ellipsis="..."),
            cluster.citation_string,
        ] if s.strip()
    ])
    has_downloads = False
    for sub_opinion in cluster.sub_opinions.all():
        if sub_opinion.local_path or sub_opinion.download_url:
            has_downloads = True
            break
    get_string = search_utils.make_get_string(request)

    try:
        fave = Favorite.objects.get(cluster_id=cluster.pk, user=request.user)
    except (ObjectDoesNotExist, TypeError):
        # Not favorited or anonymous user
        favorite_form = FavoriteForm(
            initial={
                "cluster_id": cluster.pk,
                "name": trunc(best_case_name(cluster), 100, ellipsis="..."),
            })
    else:
        favorite_form = FavoriteForm(instance=fave)

    if not is_bot(request):
        # Get the citing results from Solr for speed. Only do this for humans
        # to save on disk usage.
        conn = sunburnt.SolrInterface(settings.SOLR_OPINION_URL, mode="r")
        q = {
            "q":
            "cites:({ids})".format(ids=" OR ".join([
                str(pk)
                for pk in (cluster.sub_opinions.values_list("pk", flat=True))
            ])),
            "rows":
            5,
            "start":
            0,
            "sort":
            "citeCount desc",
            "caller":
            "view_opinion",
        }
        citing_clusters = conn.raw_query(**q).execute()
    else:
        citing_clusters = None

    return render(
        request,
        "view_opinion.html",
        {
            "title": title,
            "cluster": cluster,
            "has_downloads": has_downloads,
            "favorite_form": favorite_form,
            "get_string": get_string,
            "private": cluster.blocked,
            "citing_clusters": citing_clusters,
            "top_authorities": cluster.authorities_with_data[:5],
            "authorities_count": len(cluster.authorities_with_data),
        },
    )
Exemplo n.º 26
0
def view_opinion(request, pk, _):
    """Using the cluster ID, return the cluster of opinions.

    We also test if the cluster ID is a favorite for the user, and send data
    if needed. If it's a favorite, we send the bound form for the favorite so
    it can populate the form on the page. If it is not a favorite, we send the
    unbound form.
    """
    # Look up the court, cluster, title and favorite information
    cluster = get_object_or_404(OpinionCluster, pk=pk)
    title = ', '.join([
        s for s in [
            trunc(best_case_name(cluster), 100, ellipsis="..."),
            cluster.citation_string,
        ] if s.strip()
    ])
    has_downloads = False
    for sub_opinion in cluster.sub_opinions.all():
        if sub_opinion.local_path or sub_opinion.download_url:
            has_downloads = True
            break
    get_string = search_utils.make_get_string(request)

    try:
        fave = Favorite.objects.get(cluster_id=cluster.pk, user=request.user)
    except (ObjectDoesNotExist, TypeError):
        # Not favorited or anonymous user
        favorite_form = FavoriteForm(
            initial={
                'cluster_id': cluster.pk,
                'name': trunc(best_case_name(cluster), 100, ellipsis='...'),
            })
    else:
        favorite_form = FavoriteForm(instance=fave)

    if not is_bot(request):
        # Get the citing results from Solr for speed. Only do this for humans
        # to save on disk usage.
        conn = sunburnt.SolrInterface(settings.SOLR_OPINION_URL, mode='r')
        q = {
            'q':
            'cites:({ids})'.format(ids=' OR '.join([
                str(pk)
                for pk in (cluster.sub_opinions.values_list('pk', flat=True))
            ])),
            'rows':
            5,
            'start':
            0,
            'sort':
            'citeCount desc',
            'caller':
            'view_opinion',
        }
        citing_clusters = conn.raw_query(**q).execute()
    else:
        citing_clusters = None

    return render(
        request, 'view_opinion.html', {
            'title': title,
            'cluster': cluster,
            'has_downloads': has_downloads,
            'favorite_form': favorite_form,
            'get_string': get_string,
            'private': cluster.blocked,
            'citing_clusters': citing_clusters,
            'top_authorities': cluster.authorities[:5],
        })
Exemplo n.º 27
0
def get_related_clusters_with_cache(cluster, request):
    """Use Solr to get related opinions with Solr-MoreLikeThis query

    :param cluster: The cluster we're targeting
    :param request: Request object for checking if user is permitted
    :return: Tuple[List, List] Related clusters and sub-opinion IDs
    """
    if is_bot(request) or not is_related_beta_user(request):
        # If it is a bot or is not beta tester, return empty results
        return [], []

    conn = sunburnt.SolrInterface(settings.SOLR_OPINION_URL, mode="r")

    # Opinions that belong to the targeted cluster
    sub_opinion_ids = cluster.sub_opinions.values_list("pk", flat=True)

    # Use cache if enabled
    mlt_cache_key = "mlt-cluster:%s" % cluster.pk
    related_clusters = (
        caches["db_cache"].get(mlt_cache_key)
        if settings.RELATED_USE_CACHE
        else None
    )

    if related_clusters is None:
        # Cache is empty

        # Turn list of opinion IDs into list of Q objects
        sub_opinion_queries = [conn.Q(id=sub_id) for sub_id in sub_opinion_ids]

        # Take one Q object from the list
        sub_opinion_query = sub_opinion_queries.pop()

        # OR the Q object with the ones remaining in the list
        for item in sub_opinion_queries:
            sub_opinion_query |= item

        mlt_query = (
            conn.query(sub_opinion_query)
            .mlt(
                "text",
                count=settings.RELATED_COUNT,
                maxqt=settings.RELATED_MLT_MAXQT,
                mintf=settings.RELATED_MLT_MINTF,
                minwl=settings.RELATED_MLT_MINWL,
                maxwl=settings.RELATED_MLT_MAXWL,
            )
            .field_limit(fields=["id", "caseName", "absolute_url"])
        )
        mlt_res = mlt_query.execute()

        if mlt_res.more_like_this is not None:
            # Only a single sub opinion
            related_clusters = mlt_res.more_like_this.docs
        elif mlt_res.more_like_these is not None:
            # Multiple sub opinions

            # Get result list for each sub opinion
            sub_docs = [
                sub_res.docs
                for sub_id, sub_res in mlt_res.more_like_these.items()
            ]

            # Merge sub results by interleaving
            # - exclude items that are sub opinions
            related_clusters = [
                item
                for pair in zip(*sub_docs)
                for item in pair
                if item["id"] not in sub_opinion_ids
            ]

            # Limit number of results
            related_clusters = related_clusters[: settings.RELATED_COUNT]
        else:
            # No MLT results are available (this should not happen)
            related_clusters = []

        cache.set(
            mlt_cache_key, related_clusters, settings.RELATED_CACHE_TIMEOUT
        )

    return related_clusters, sub_opinion_ids
Exemplo n.º 28
0
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(request, 'search.html', render_dict)

    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')

            # Ensure we get nothing from the future.
            request.GET = request.GET.copy()  # Makes it mutable
            request.GET['filed_before'] = date.today()

            # 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',
                                         facet=False))
            # Get the results from the oral arguments as well
            oa_dict = do_search(request, rows=5, order_by='dateArgued desc',
                                type='oa', facet=False)
            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(request, 'homepage.html', render_dict)
        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(request, 'search.html', render_dict)