async def not_found(request, exc): """ Return an HTTP 404 page. """ template = "404.html" context = {"request": request} return templates.TemplateResponse(template, context, status_code=404)
async def server_error(request, exc): """ Return an HTTP 500 page. """ template = "500.html" context = {"request": request} return templates.TemplateResponse(template, context, status_code=500)
async def detail(request): username = request.path_params["username"] table_id = request.path_params["table_id"] row_uuid = request.path_params["row_uuid"] can_edit = check_can_edit(request, username) datasource = await load_datasource_or_404(username, table_id) datasource = datasource.filter(uuid=row_uuid) item = await datasource.get() if item is None: raise HTTPException(status_code=404) if request.method == "POST": form_values = await request.form() validated_data, form_errors = datasource.validate(form_values) if not form_errors: await item.update(values=validated_data) return RedirectResponse(url=request.url, status_code=303) status_code = 400 else: form_values = (None if item is None else datasource.schema.make_validator().serialize(item)) 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() } if media_type == "application/json": return JSONResponse(data, headers={"Access-Control-Allow-Origin": "*"}) json_data = json.dumps(data, indent=4) # Render the page template = "detail.html" context = { "request": request, "schema": datasource.schema, "owner": username, "table_name": datasource.name, "table_url": datasource.url, "item": item, "form_values": form_values, "form_errors": form_errors, "can_edit": can_edit, "view_style": view_style, "json_data": json_data, } return templates.TemplateResponse(template, context, status_code=status_code)
async def columns(request): 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) if request.method == "POST": form_values = await request.form() validated_data, form_errors = NewColumnSchema.validate_or_error( form_values) if not form_errors: identity = slugify(validated_data["name"], separator="_", to_lower=True) query = (tables.column.select().where( tables.column.c.table == datasource.table["pk"]).where( tables.column.c.identity == identity)) column = await database.fetch_one(query) if column is not None: form_errors = { "name": "A column with this name already exists." } if not form_errors: position = (1 if not datasource.columns else datasource.columns[-1]["position"] + 1) insert_data = dict(validated_data) insert_data["table"] = datasource.table["pk"] insert_data["created_at"] = datetime.datetime.now() insert_data["identity"] = slugify(insert_data["name"], separator="_", to_lower=True) insert_data["position"] = position query = tables.column.insert() await database.execute(query, values=insert_data) return RedirectResponse(url=request.url, status_code=303) status_code = 400 else: form_values = None form_errors = None status_code = 200 # Render the page template = "columns.html" context = { "request": request, "owner": username, "table_id": table_id, "table_name": datasource.name, "table_url": datasource.url, "columns": datasource.columns, "form_errors": form_errors, "form_values": form_values, "can_edit": can_edit, } return templates.TemplateResponse(template, context, status_code=status_code)
async def dashboard(request): datasources = await load_datasources() rows = [] for datasource in datasources: text = datasource.name url = datasource.url count = await datasource.count() rows.append({ "owner": datasource.username, "text": text, "url": url, "count": count }) template = "dashboard.html" context = { "request": request, "rows": rows, } return templates.TemplateResponse(template, context)
async def profile(request): username = request.path_params["username"] can_edit = check_can_edit(request, username) query = tables.users.select().where(tables.users.c.username == username) profile_user = await database.fetch_one(query) if profile_user is None: raise HTTPException(status_code=404) datasources = await load_datasources_for_user(profile_user) rows = [] for datasource in datasources: text = datasource.name url = datasource.url count = await datasource.count() rows.append({"text": text, "url": url, "count": count}) if request.method == "POST": form_values = await request.form() validated_data, form_errors = NewTableSchema.validate_or_error( form_values) if not form_errors: identity = slugify(validated_data["name"], to_lower=True) query = (tables.table.select().where( tables.table.c.user_id == profile_user["pk"]).where( tables.table.c.identity == identity)) table = await database.fetch_one(query) if table is not None: form_errors = { "name": "A table with this name already exists." } if not form_errors: insert_data = dict(validated_data) insert_data["created_at"] = datetime.datetime.now() insert_data["identity"] = slugify(insert_data["name"], to_lower=True) insert_data["user_id"] = profile_user["pk"] query = tables.table.insert() await database.execute(query, values=insert_data) return RedirectResponse(url=request.url, status_code=303) status_code = 400 else: form_values = None form_errors = None status_code = 200 template = "profile.html" context = { "request": request, "owner": username, "profile_user": profile_user, "rows": rows, "form_values": form_values, "form_errors": form_errors, "can_edit": can_edit, } return templates.TemplateResponse(template, context, status_code=status_code)
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)
async def authorize(request): redirect_url = request.query_params.get("redirect_url", "#") template = "mock_github/authorize.html" context = {"request": request, "redirect_url": redirect_url} return templates.TemplateResponse(template, context)