Ejemplo n.º 1
0
def test_get_column_controls_no_current_selection():
    columns = {"username": "******", "email": "Email"}
    url = URL("/")
    column, is_reverse = None, False

    controls = get_column_controls(url,
                                   columns,
                                   selected_column=None,
                                   is_reverse=False)

    assert controls == [
        ColumnControl(
            id="username",
            text="Username",
            url=URL("/?order=username"),
            is_forward_sorted=False,
            is_reverse_sorted=False,
        ),
        ColumnControl(
            id="email",
            text="Email",
            url=URL("/?order=email"),
            is_forward_sorted=False,
            is_reverse_sorted=False,
        ),
    ]
Ejemplo n.º 2
0
async def table(request):
    PAGE_SIZE = 10

    username = request.path_params["username"]
    table_id = request.path_params["table_id"]
    can_edit = check_can_edit(request, username)
    datasource = await load_datasource_or_404(username, table_id)

    # datasource = ElectionDataSource(app=app, year=year)
    columns = {
        key: field.title
        for key, field in datasource.schema.fields.items()
    }

    # Get some normalised information from URL query parameters
    current_page = pagination.get_page_number(url=request.url)
    order_column, is_reverse = ordering.get_ordering(url=request.url,
                                                     columns=columns)
    search_term = search.get_search_term(url=request.url)

    # Filter by any search term
    datasource = datasource.search(search_term)

    # Determine pagination info
    count = await datasource.count()
    total_pages = max(math.ceil(count / PAGE_SIZE), 1)
    current_page = max(min(current_page, total_pages), 1)
    offset = (current_page - 1) * PAGE_SIZE

    # Perform column ordering
    if order_column is not None:
        datasource = datasource.order_by(column=order_column,
                                         reverse=is_reverse)

    # Export
    export = request.query_params.get("export")
    if export == "json":
        queryset = await datasource.all()
        data = [{
            key: field.serialize(item.get(key))
            for key, field in datasource.schema.fields.items()
        } for item in queryset]
        content = json.dumps(data, indent=4)
        headers = {
            "Content-Disposition": f'attachment; filename="{table_id}.json"'
        }
        return Response(content, headers=headers)
    elif export == "csv":
        output = io.StringIO()
        writer = csv.writer(output)
        queryset = await datasource.all()

        headers = [field.title for field in datasource.schema.fields.values()]
        writer.writerow(headers)
        for item in queryset:
            row = [
                item.get(key, default="")
                for key in datasource.schema.fields.keys()
            ]
            writer.writerow(row)

        content = output.getvalue()
        headers = {
            "Content-Disposition": f'attachment; filename="{table_id}.csv"'
        }
        return Response(content, headers=headers)

    #  Perform pagination
    datasource = datasource.offset(offset).limit(PAGE_SIZE)
    queryset = await datasource.all()

    # Get pagination and column controls to render on the page
    column_controls = ordering.get_column_controls(
        url=request.url,
        columns=columns,
        selected_column=order_column,
        is_reverse=is_reverse,
    )
    page_controls = pagination.get_page_controls(url=request.url,
                                                 current_page=current_page,
                                                 total_pages=total_pages)

    if request.method == "POST":
        form_values = await request.form()
        validated_data, form_errors = datasource.validate(form_values)
        if not form_errors:
            await datasource.create(values=validated_data)
            return RedirectResponse(url=request.url, status_code=303)
        status_code = 400
    else:
        form_values = None
        form_errors = None
        status_code = 200

    accept = request.headers.get("Accept", "*/*")
    media_type = negotiate(accept, ["application/json", "text/html"])

    view_style = request.query_params.get("view")
    if view_style not in ("json", "table"):
        view_style = "table"

    json_data = None
    if view_style == "json" or media_type == "application/json":
        data = [{
            key: field.serialize(item.get(key))
            for key, field in datasource.schema.fields.items()
        } for item in queryset]
        if media_type == "application/json":
            return JSONResponse(data,
                                headers={"Access-Control-Allow-Origin": "*"})
        json_data = json.dumps(data, indent=4)

    # Render the page
    template = "table.html"
    context = {
        "request": request,
        "schema": datasource.schema,
        "owner": username,
        "table_id": table_id,
        "table_name": datasource.name,
        "table_url": datasource.url,
        "table_has_columns": bool(datasource.schema.fields),
        "table_has_rows": search_term or list(queryset),
        "queryset": queryset,
        "json_data": json_data,
        "view_style": view_style,
        "search_term": search_term,
        "column_controls": column_controls,
        "page_controls": page_controls,
        "form_errors": form_errors,
        "form_values": form_values,
        "can_edit": can_edit,
    }
    return templates.TemplateResponse(template,
                                      context,
                                      status_code=status_code)