Не нужно определять пользовательскую функцию, вместо этого мы можем просто суммировать все элементы группы, вычесть текущее значение и делить на число элементов на группу минус 1
.
df %>% group_by(grouping) %>%
mutate(special_mean = (sum(value) - value)/(n()-1))
# grouping value special_mean
# (chr) (int) (dbl)
#1 A 1 8.5
#2 A 6 6.0
#3 A 11 3.5
#4 B 2 9.5
#5 B 7 7.0
Хорошо, я не думаю, что официальный фрагмент, упомянутый galuszkak, должен использоваться везде, мы должны рассмотреть случай, когда некоторая ошибка может быть вызвана во время обработчика, такого как функция hello_world
. Независимо от того, является ли ответ правильным или неправильным, мы должны обратить внимание на заголовок Access-Control-Allow-Origin
. Итак, все очень просто, как показано ниже:
@blueprint.after_request # blueprint can also be app~~
def after_request(response):
header = response.headers
header['Access-Control-Allow-Origin'] = '*'
return response
Это все ~~
Я только что столкнулся с той же проблемой и пришел к выводу, что другие ответы немного сложнее, чем они должны быть, поэтому вот мой подход для тех, кто не хочет полагаться на большее количество библиотек или декораторов:
Запрос CORS фактически состоит из двух HTTP-запросов. Запрос предварительной проверки, а затем фактический запрос, который выполняется только в случае успешной предварительной проверки.
Перед фактическим междоменным запросом POST
браузер отправит запрос OPTIONS
. Этот ответ не должен возвращать никакого тела, а только некоторые обнадеживающие заголовки, сообщающие браузеру, что можно делать этот междоменный запрос и что он не является частью какой-либо атаки межсайтового скриптинга.
Я написал функцию Python для построения этого ответа, используя функцию make_response
из модуля flask
.
def _build_cors_prelight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add("Access-Control-Allow-Headers", "*")
response.headers.add("Access-Control-Allow-Methods", "*")
return response
Этот ответ является символом подстановки, который работает для всех запросов. Если вы хотите получить дополнительную безопасность, обеспечиваемую CORS, вы должны предоставить белый список источников, заголовков и методов.
Этот ответ убедит ваш браузер (Chrome) идти вперед и выполнить фактический запрос.
При обслуживании фактического запроса вы должны добавить один заголовок CORS - в противном случае браузер не вернет ответ на вызывающий код JavaScript. Вместо этого запрос потерпит неудачу на стороне клиента. Пример с jsonify
response = jsonify({"order_id": 123, "status": "shipped"}
response.headers.add("Access-Control-Allow-Origin", "*")
return response
Я также написал функцию для этого.
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
позволяя вам вернуть однострочник.
from flask import Flask, request, jsonify, make_response
from models import OrderModel
flask_app = Flask(__name__)
@flask_app.route("/api/orders", methods=["POST", "OPTIONS"])
def api_create_order():
if request.method == "OPTIONS": # CORS preflight
return _build_cors_prelight_response()
elif request.method == "POST": # The actual request following the preflight
order = OrderModel.create(...) # Whatever.
return _corsify_actual_response(jsonify(order.to_dict()))
else
raise RuntimeError("Wierd - don't know how to handle method {}".format(request.method))
def _build_cors_prelight_response():
response = make_response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add('Access-Control-Allow-Headers', "*")
response.headers.add('Access-Control-Allow-Methods', "*")
return response
def _corsify_actual_response(response):
response.headers.add("Access-Control-Allow-Origin", "*")
return response
Вот что сработало для меня, когда я развернулся в Heroku.
http://flask-cors.readthedocs.org/en/latest/
Установите колбу, запустив - pip install -U flask-cors
from flask import Flask
from flask_cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
@app.route("/")
@cross_origin()
def helloWorld():
return "Hello, cross-origin-world!"
Попробуйте следующие декораторы:
@app.route('/email/',methods=['POST', 'OPTIONS']) #Added 'Options'
@crossdomain(origin='*') #Added
def hello_world():
name=request.form['name']
email=request.form['email']
phone=request.form['phone']
description=request.form['description']
mandrill.send_email(
from_email=email,
from_name=name,
to=[{'email': app.config['QOLD_SUPPORT_EMAIL']}],
text="Phone="+phone+"\n\n"+description
)
return '200 OK'
if __name__ == '__main__':
app.run()
Этот декоратор будет создан следующим образом:
from datetime import timedelta
from flask import make_response, request, current_app
from functools import update_wrapper
def crossdomain(origin=None, methods=None, headers=None,
max_age=21600, attach_to_all=True,
automatic_options=True):
if methods is not None:
methods = ', '.join(sorted(x.upper() for x in methods))
if headers is not None and not isinstance(headers, basestring):
headers = ', '.join(x.upper() for x in headers)
if not isinstance(origin, basestring):
origin = ', '.join(origin)
if isinstance(max_age, timedelta):
max_age = max_age.total_seconds()
def get_methods():
if methods is not None:
return methods
options_resp = current_app.make_default_options_response()
return options_resp.headers['allow']
def decorator(f):
def wrapped_function(*args, **kwargs):
if automatic_options and request.method == 'OPTIONS':
resp = current_app.make_default_options_response()
else:
resp = make_response(f(*args, **kwargs))
if not attach_to_all and request.method != 'OPTIONS':
return resp
h = resp.headers
h['Access-Control-Allow-Origin'] = origin
h['Access-Control-Allow-Methods'] = get_methods()
h['Access-Control-Max-Age'] = str(max_age)
if headers is not None:
h['Access-Control-Allow-Headers'] = headers
return resp
f.provide_automatic_options = False
return update_wrapper(wrapped_function, f)
return decorator
Вы также можете проверить этот пакет Flask-CORS
Если вы хотите включить CORS для всех маршрутов, просто установите расширение flask_cors (pip3 install -U flask_cors
) и оберните app
следующим образом: CORS(app)
.
Этого достаточно, чтобы сделать это (я проверил это с помощью POST
запроса на загрузку изображения, и это сработало для меня):
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # This will enable CORS for all routes
Важное примечание: если в вашем приложении есть ошибка Например, если вы попытаетесь напечатать несуществующую переменную, вы получите сообщение об ошибке CORS, которое на самом деле не имеет ничего общего с CORS.
Мое решение - обертка вокруг app.route:
def corsapp_route(path, origin=('127.0.0.1',), **options):
"""
Flask app alias with cors
:return:
"""
def inner(func):
def wrapper(*args, **kwargs):
if request.method == 'OPTIONS':
response = make_response()
response.headers.add("Access-Control-Allow-Origin", ', '.join(origin))
response.headers.add('Access-Control-Allow-Headers', ', '.join(origin))
response.headers.add('Access-Control-Allow-Methods', ', '.join(origin))
return response
else:
result = func(*args, **kwargs)
if 'Access-Control-Allow-Origin' not in result.headers:
result.headers.add("Access-Control-Allow-Origin", ', '.join(origin))
return result
wrapper.__name__ = func.__name__
if 'methods' in options:
if 'OPTIONS' in options['methods']:
return app.route(path, **options)(wrapper)
else:
options['methods'].append('OPTIONS')
return app.route(path, **options)(wrapper)
return wrapper
return inner
@corsapp_route('/', methods=['POST'], origin=['*'])
def hello_world():
...