åµé ã®æŽå²ããŒã1ããã«ã¡ã¯ thunderargsã¯ãã¢ãããŒã·ã§ã³ã䜿çšããŠå
¥ååŒæ°ãåŠçã§ããã©ã€ãã©ãªã§ããããšãç°¡åã«æãåºããŸãã
ããã«ãåçŽã«ã²ãŒããã¹ããŒããããšãã§ããŸããããã«ããã颿°ã®ãããã®åŒæ°ãä»ã®å Žæãããã«ãããŸãã ããšãã°ããã©ã¹ã³å
ã®ãªã¯ãšã¹ããªããžã§ã¯ãããã ãããŠæåŸã«ã代ããã«
@app.route('/ugly_calc', dont_wrap=True) def ugly_calc(): x, y = int(request.args['x']), int(request.args['y']) op_key = request.args.get('op') if not op_key: op_key = '+' op = OPERATION.get(op_key) return str(op(x, y))
ãã
@app.route('/calc') def calc(x:Arg(int), y:Arg(int), op:Arg(str, default='+')): return str(OPERATION[op](x, y))
å°ãªããšã誰ããèšäºã®å
容ã倧äœçè§£ãããšæããŸãã ããã§èª¬æãããŠããã®ã¯ããããžã§ã¯ãã®å°æ¥ãšãããã€ã«ã¹ããŒã³ãã®å€§ãŸããªé
眮ã«ã€ããŠã®èå¯ã§ãã ãã¡ãããããããçš®é¡ã®ç°ãªãæ©èœã®æåã®ãã©ããã§ãã
ãã®éšåã§
- ãããžã§ã¯ãã®æ§é ã®å€æŽãšãå
ã®æ§é ã®ããã€ãã®é倧ãªãšã©ãŒãèæ
®ããŠãã ãã
- ããªããŒã¿ãŒãã©ã®ããã«æ©èœããçæãããšã©ãŒãã«ã¹ã¿ãã€ãºããæ¹æ³ãèŠãŠã¿ãŸãããã
- ç¹æ®ãªåŒæ°ã®åºæ¬èŠçŽ ïŒIntArgãStrArgãListArgãªã©ïŒãäœæããŸãã
- ãªã¯ãšã¹ãã§åä¿¡ããIDã«ãã£ãŠããŒã¿ããŒã¹ãããªããžã§ã¯ããèªåçã«ãã«ããã¯ã©ã¹ãæºåããŸã
- ã¢ãã«ã¯ã©ã¹ããšã«ãšã³ããªãã€ã³ããçæããŸã
- ãªã¹ããŒãå®è£
ããããã€ãã®åŒæ°ã®ããªããŒã¿ãŒãäœæããæ¹æ³ã確èªããŸã
- åŒæ°ã®æ§é ã«é¢ããæ
å ±ãå®å
šã«ããŒã¿ããŒã¹ã«è»¢éã§ããããšã確èªããŸãããäœããããŸããã
- æåŸã«ããããã®å®éšã®æ çµã¿ã§ã¯æ±ºããŠå®çŸãããªãã£ãå°ããªé¢å¿ã«ã€ããŠèª¬æããŸãã
æ§é ã®å€åããŸãã¯ç§ã蹎ãããã¹ãçç±
ããŠããããžã§ã¯ãã®éåœã«ãããéèŠãªåºæ¥äºã«ã€ããŠç°¡åã«èª¬æããŸãã æåã«ãArmin Ronasher
ãflaskã«
ã¢ãžã¥ãŒã«ãäœæããããšãæšå¥šããæ¹æ³ãæåŸã«èªã¿ãããããããé©åãªçš®é¡ã«ããŸããã ãããè¡ãããã«ãã¡ã€ã³ã©ã€ãã©ãªã®æ©èœïŒãã®libãšã«ãã¯thunderargsãšããååã®ãŸãŸã§ããïŒããFlaskãžã®è¿œå ãšããŠäœ¿çšã§ããæ©èœããå®å
šã«åé¢ããŸããïŒãã®ã¯ã©ããã¹ã¯ããæ³åã®ãšãããflame-thunderargsãšããååã«å
¥ããããšãã§ããŸãïŒã ã¯ããæ¬è³ªçã«ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ãã«ãŒãã«ããåé¢ããã ãã§ããã®ã€ã³ã¿ãŒãã§ã€ã¹ããªããŠãå®è¡å¯èœã§ãã ãããŠãããã¯æåããè¡ãããŠããã¹ãã§ããã åŸããèããŠãåç·šæã«è²»ãããæéã¯ã»ãŒ5æéã§ããã
äžè¬ã«ãæ£ç¢ºã«äœãå€ãã£ãã®ãããããäœãæå³ããã®ããç°¡åã«èª¬æããŸãã
ããã§ãã«ãŒãã«ãšãã©ã¹ã³ãžã®ã€ã³ã¿ãŒãã§ãŒã¹ã®2ã€ã®ã©ã€ãã©ãªãã§ããŸããã
ã¡ã€ã³ã©ã€ãã©ãªã¯ãæ¢ã«è¿°ã¹ãããã«ãå€éšã€ã³ã¿ãŒãã§ã€ã¹ãªãã§äœ¿çšã§ããŸãã ãããŠãã¡ãããç¬èªã®ã€ã³ã¿ãŒãã§ãŒã¹ãäœæããããã«äœ¿çšã§ããŸãã ããšãã°ãä»ã®Webãã¬ãŒã ã¯ãŒã¯ãžã ãŸãã¯argparseããã ãŸãã¯ãžã£ããŒãããã«ã ã¯ããäžè¬çã«ãäœã«å¯ŸããŠãã
å®éããã®æç¹ãããããžã§ã¯ãã¯é»åã«ãªããŸãã
flask-thunderargsãå®å
šãªãã©ã¹ã³ã¢ãžã¥ãŒã«ã«ãªããŸãã
å¯äžã®åé¡ã¯ãã€ã³ã¿ãŒãã§ã€ã¹èªäœãéåžžã«å°ããããšã§ãã å®éããã¹ãŠã
ãã®ãã¡ã€ã«ã«å«ãŸããŠ
ããŸãã 誰ããå¥ã®ã©ã€ãã©ãªã«ç¬èªã®ã€ã³ã¿ãŒãã§ã€ã¹ãäœæããããšã«æ±ºããå Žåã¯ãå®å
šã«éäžã§ããŸãã
ãããŠããšã³ããã€ã³ããåæåããããã»ã¹ã¯ãã¡ããå€ãããŸããã ããã§ãæå°éã®ã¢ããªã±ãŒã·ã§ã³ã¯æ¬¡ã®ããã«ãªããŸãã
from flask import Flask from flask.ext.thunderargs import ThunderargsProxy from thunderargs import Arg app = Flask(__name__) ThunderargsProxy(app) @app.route('/max') def find_max(x: Arg(int, multiple=True)): return str(max(x)) if __name__ == '__main__': app.run()
ãã®ãããªããšã
ééãã
æåŸã®éšåã§ã¯ãç¬èªã®ããªããŒã¿ãŒãäœæããæ¹æ³ããã§ã«çè§£ããŠããŸãã ãããŠããããéåžžã«åçŽã§ããããšã確èªããŸããã æãåºãããŠãã ããïŒ
def less_than_21(x): return x < 21 @app.route('/step5_alt') def step5_1(offset: Arg(int, default=0, validators=[lambda x: x >= 0 and x < len(elements)]), limit: Arg(int, default=20, validators=[less_than_21])): return str(elements[offset:offset+limit])
ã芧ã®ãšãããäœæã«ã¯2ã€ã®ãªãã·ã§ã³ããããŸãã 1ã€ã¯ãã©ã ãã䜿çšããã€ã³ã©ã€ã³ã§ãã 2çªç®ã¯ãã«ãŠã§ã€ãã§ãã æ¬¡ã«ããã«ãŠã§ã€ããªãã·ã§ã³ãæãŸããçç±ã瀺ããŸãã
æåŸã®éšåã®å®éšã粟æ»ãã人ã¯ããã¡ã¯ããªãŒã«ãã£ãŠäœæãããããªããŒã¿ãŒãããªããããã§çè§£å¯èœãªãšã©ãŒãæããããšã«æ°ä»ãã§ãããïŒ
thunderargs.errors.ValidationError: Value of `limit` must be less than 21
ãããããã®äŸã§ã¯ãçè§£äžèœã§ãããã¹ããªãšã©ãŒãçºçããŸãã
thunderargs.errors.ValidationError: Argument limit failed at validator
ããã«å¯ŸåŠããã®ã¯éåžžã«ç°¡åã§ãã ããã«ããšã©ãŒã¯å
ã®ãšã©ãŒãããããã«è¯ããªããŸãã
experiments.custom_error.LimitError: limit must be less than 21 and more than 0. Given: 23
ãã®çµæãåŸãã«ã¯ã次ã®ã³ãŒããå¿
èŠã§ãã
class LimitError(ValidationError): pass
from thunderargs.errors import customize_error from experiments.custom_error import LimitError message = "{arg_name} must be less than 21 and more than 0. Given: {value}" @customize_error(message=message, error_class=LimitError) def limit_validator(x): return x < 21 and x>0 @app.route('/step5_alt2') def step5_2(offset: Arg(int, default=0, validators=[lambda x: x >= 0 and x < len(elements)]), limit: Arg(int, default=20, validators=[limit_validator])): return str(elements[offset:offset+limit])
äžè¬ã«ããšã©ãŒãã«ã¹ã¿ãã€ãºããã«ã¯ãããªããŒã¿ãŒé¢æ°ã§
customize_error
ãã³ã¬ãŒã¿ãŒããã³ã°ãããã ãã§ãã æ¬¡ã®å€æ°ã¯åžžã«ãšã©ãŒããã¹ãã«æž¡ãããŸãã
error_code
衚瀺ãããšã©ãŒçªå·ã ã·ã¹ãã åã®ãã¡ã³ã®ããã®ã·ã¹ãã å
ã®ãããã;arg_name
ã¯ã颿°å®£èšã®åŒæ°ã«å²ãåœãŠãããååã«å¯Ÿå¿ããåŒæ°ã®ååã§ãã ç§ãã¡ã®å Žåãããã¯äŸãã°å¶éã§ãã- value-ããªããŒã¿ãŒãåãåã£ãå€ã Flask-Thunderargsã®å Žåãããã¯ã»ãšãã©ã®å Žåæååã§ããreques.jsonãšreques.filesãé€ãå
šå¡ãåœŒã«æž¡ãããã§ãã
validator_no
ã·ãªã¢ã«çªå·ã é©åã«æ§æãããããªããŒã¿ãŒã«åœ¹ç«ã€ãã©ããã¯éåžžã«çãããã
ããã«ããšã©ãŒã¯ã©ã¹ã察å¿ããååã§ãŽãã¢ããããååä»ããã©ã¡ãŒã¿ãŒãcustomize_errorã«æž¡ãããšãã§ããŸãã ããã¯ãããšãã°ãèšå®ã§æå®ãããããŒã¿ããšã³ããŠãŒã¶ãŒãžã®éç¥ãšããŠè»¢éããå¿
èŠãããå Žåã«äŸ¿å©ã§ãã ãŸããããã¯ããšã©ãŒãžã§ãã¬ãŒã¿ãäœæããŠããå Žåã«ãé©çšãããŸãã äŸãšããŠãvalidfarmã®å€å
žçãªãã¡ã¯ããªãŒãã³ã¬ãŒã¿ãèããŠã¿ãŸãããã
def val_in(x): @customize_error("Value of `{arg_name}` must be in {possible_values}", possible_values=x) def validator(value): return value in x return validator
ãã®äŸã®possible_valuesã¯ãããã°ã©ããŒã«ãã£ãŠãã¡ã¯ããªãŒã«æž¡ããã倿°xããååŸãããã¢ããªã±ãŒã·ã§ã³ã®èµ·åæã«ãååŸãããŸãã
æšå®ããŒãžã§ã³ïŒ 0.4ç¶æ¿å€æ°ã¯ã©ã¹
æããã«ãæœè±¡åã®ã¬ãã«ãäžããããšã¯ãã©ã€ãã©ãªã®ãšã³ããŠãŒã¶ãŒã«ãšã£ãŠæçšã§ãã ãããŠããã®æ¹åãžã®æåã®ã¹ãããã¯å°éã¯ã©ã¹ã§ãã 以äžã«äŸã瀺ããŸãã
class IntArg(Arg): def __init__(self, max_val=None, min_val=None, **kwargs): kwargs['p_type'] = int if not 'validators' in kwargs or kwargs['validators'] is None: kwargs['validators'] = [] if min_val is not None: if not isinstance(min_val, int): raise TypeError("Minimal value must be int") kwargs['validators'].append(val_gt(min_val-1)) if max_val is not None: if not isinstance(max_val, int): raise TypeError("Maximal value must be int") kwargs['validators'].append(val_lt(max_val+1)) if min_val is not None and max_val is not None: if max_val < min_val: raise ValueError("max_val is greater than min_val") super().__init__(**kwargs)
ãããŠããã®ã¯ã©ã¹ã®ã¢ããªã±ãŒã·ã§ã³ã¯æ¬¡ã®ãšããã§ãã
from experiments.inherited_args import IntArg @app.route('/step7') def step7(x: IntArg(default=0, max_val=100, min_val=0)): return str(x)
ãã®ãããªã¯ã©ã¹ã®äž»ãªæ©èœã¯ãå
¥ååŒæ°ã®ããã€ãã®ãã©ã¡ãŒã¿ãŒãæåã§èšè¿°ããå¿
èŠããªãããšã§ãã ããã«ãããã€ãã®ããªããŒã¿ãŒãæåã§èšè¿°ããå¿
èŠã¯ãããŸããã ãŸããã³ãŒãã§ãããã®æå³ãæå®ããããšãå¯èœã«ãªããŸããããã¯ãèªã¿ãããã«ãšã£ãŠéåžžã«éèŠã§ãã
æšå®ããŒãžã§ã³ïŒ 0.4ORMã®ç¶æ¿ã¯ã©ã¹
mongoengineãä»ããŠäœæãããããã¥ã¡ã³ãã¯ã©ã¹ããããšããŸãã
class Note(Document): title = StringField(max_length=40) text = StringField(min_length=3, required=True) created = DateTimeField(default=datetime.now)
ç¹å®ã®ããã¥ã¡ã³ããè¿ãã²ãã¿ãŒãå¿
èŠã§ãã ãã®ã¿ã¹ã¯ã®ããã«ç¬ç«ããã¯ã©ã¹ãäœããŸãããïŒ
class ItemArg(Arg): def __init__(self, collection, **kwargs): kwargs['p_type'] = kwargs.get('p_type') or ObjectId kwargs['expander'] = lambda x: collection.objects.get(pk=x) super().__init__(**kwargs)
圌ãããããšã¯ãå
¥ååŒæ°ã倿Žããããšã ãã§ãã å¿
èŠãªã»ããã«å±éããã ãã§ãã ãããŠããã®ãããªæå°éã®ãªãã·ã§ã³ã§ããããããè¡ãããšãã§ããŸãïŒ
@app.route('/step9/get') def step9_2(note: ItemArg(Note)): return str(note.text)
ããªããããã§ããã
æšå®ããŒãžã§ã³ïŒ ç¬ç«ããã©ã€ãã©ãªã«çœ®ãããšã¯çã«ããªã£ãŠããŸãFlask Getterãçæãã
ã¢ãã«ã«ã²ãã¿ãŒãç¹å¥ãªã¢ã¯ã·ã§ã³ãå®è¡ããªãã¯ã©ã¹ããããšæ³åããŠãã ããã ããŒã¿ããŒã¹ã«ä¿åãããŠããã®ãšåã圢åŒã§ãŠãŒã¶ãŒæ
å ±ãæäŸããã²ãã¿ãŒãäœæããå¿
èŠããããŸãã ãã®å Žåãã²ãã¿ãŒãžã§ãã¬ãŒã¿ãŒã¯æ°ã«ããŸããã ããããã£ãŠã¿ãŸãããïŒ
def make_default_serializable_getlist(cls, name="default_getter_name"): @Endpoint def get(offset: IntArg(min_val=0, default=0), limit: IntArg(min_val=1, max_val=50, default=20)): return list(map(lambda x: x.get_serializable_dict(), cls.objects.skip(offset).limit(limit))) get.__name__ = name return get
ãã®é¢æ°ã¯ãMongoEngineã³ã¬ã¯ã·ã§ã³ã®ã²ãã¿ãŒãäœæããå¿
èŠããããŸãã å¯äžã®è¿œå æ¡ä»¶ã¯ãã³ã¬ã¯ã·ã§ã³ã¯ã©ã¹ã§
get_serializable_dict
ã¡ãœãããå®çŸ©ããå¿
èŠãããããšã§ãã ãããã誰ãããã«é¢ããŠç¹å¥ãªåé¡ãæ±ããããšã¯ãªããšæããŸãã ãããŠãããã¯ãã®ããšã®çšéã®äžã€ã§ãïŒ
getter = make_default_serializable_getlist(Note, name='step11_getter') app.route('/step11_alt3')(json_resp(getter))
json_resp
ã§ã¯
json_resp
ãã«ããŒé¢æ°ã䜿çšãã
json_resp
ããå®éã«ã¯è峿·±ãããšã¯äœããããåã«
flask.jsonify
ã®ã³ã³ãããŒã©ãŒã®å¿çã
flask.jsonify
ã©ããã
flask.jsonify
ïŒå¯èœãªå ŽåïŒã ããã«ããã®äŸã§ã¯ãå€å
žçãªæ§æã䜿çšããã«ãã³ã¬ãŒã¿ãŒã䜿çšããŸããã ç§ã®æèŠã§ã¯ãããã¯æ£åœåãããŸããããã§ãªããã°ãæçšãªã¢ã¯ãã£ããã£ãå®è¡ããªãã©ãããŒãã©ã³ã¹ããŒããäœæããå¿
èŠããã£ãã§ãããã
æšå®ããŒãžã§ã³ïŒ 以åãšåæ§é話èšé²ãªã©
説æããã«ãŒã«ã«é©åãããŠãŒã¶ãŒã®å身äœã®åããèšé²ããŸãããã ãããè¡ãããã«ãã³ãŒã«ããã¯é¢æ°ãåã蟌ãåçŽãªãã³ã¬ãŒã¿ãŒãã¹ããŒããŸãã
def listen_with(listener): def decorator(victim): @wraps(victim) def wrapper(**kwargs): listener(func=victim, **kwargs) return victim(**kwargs) return wrapper return decorator
ã³ãŒã«ããã¯èªäœïŒ
def logger(func, **kwargs): print(func.__name__) print(kwargs)
ãã®ã³ãŒã«ããã¯ã¯ãåä¿¡ãããã¹ãŠã®åŒæ°ãç»é¢ã«è¡šç€ºããã ãã§ãã ããã«äŸ¿å©ãªäŸãèããŠã¿ãŸãããã
def denied_for_john_doe(func, firstname, lastname): if firstname == 'John' and lastname == 'Doe': raise ValueError("Sorry, John, but you are banned") @app.route('/step13') @listen_with(denied_for_john_doe) def step13(firstname: Arg(str, required=True), lastname: Arg(str, required=True)): return "greeting you, {} {}".format(firstname, lastname)
ããã§èŠãããã«ãå€ã®çµã¿åããã䜿çšããå¯èœæ§ã®ãã¹ãããããŸãã äžè¬ã«ãçŽç²ã«åœ¢åŒçã«ã¯ããã®ãããªãã¶ã€ã³ã¯ãã§ã³ããŒã§ã¯ãªãããªã¹ããŒããåé¢ããå¿
èŠããããŸãã ããããä»ã®ãšãããå®éšã®äžç°ãšããŠããã®ãŸãŸã«ããŠãããŸãããã ããã¢ãŒããã¯ãã£çã«æ£ããäŸã次ã«ç€ºããŸãã
def mail_sender(func, email): if func.__name__ == 'step14':
ãŸããäŸã§ã¯ãªãããã®æºåã
æšå®ããŒãžã§ã³ïŒ 0.5ããŒã¿ããŒã¹å
ã®åŒæ°ã®æ§é
ããã§ã¯ããã¶ãŒãã«åãæãããŸãããã 仿¥ãããããããã§ã¯ãå
¥ååŒæ°ã®æ§é ãããŒã¿ããŒã¹ã«ä¿åããŠããŸãã
å®éããã®ãããªã¢ãŒããã¯ãã£ã¯ãããŒã¿ãå®éã«åä¿¡ããã³åŠçããã³ãŒããããŒã¿ã«åæžããŸãã ãããŠãã©ãããã§ããã®ããŒã¿ãååŸã§ããŸãã ããšãã°ãæ§æãã¡ã€ã«ããã ãŸãã¯ããŒã¿ããŒã¹ããã 確ãã«ã2ã€ã®ããŒã¿ãœãŒã¹ã®éããèãããšïŒ å§ããŸãããã
ãŸããçŸåšå®è¡äžã®ããã°ã©ã ã®ãªããžã§ã¯ããšããŒã¿ããŒã¹ããã€ã³ããŒããããããŒã¿ãšã®å¯Ÿå¿è¡šãã³ã³ãã€ã«ããå¿
èŠããããŸãã ãã®äŸã§ã¯ãäžèšã§æ¢ã«èª¬æãã1ã€ã®ã¿ã€ãã®ã¿ã䜿çšããŸãã ãããã£ãŠããããŸã§ã®ãšããã圌ã ããããã«ããŸãã
TYPES = {'IntArg': IntArg}
次ã«ãå®éã«ãšã³ããªãã€ã³ãã®å
¥ååŒæ°ã«é¢ããæ
å ±ãä¿åããã³è¡šç€ºããã¢ãã«ãèšè¿°ããå¿
èŠããããŸãã
class DBArg(Document): name = StringField(max_length=30, min_length=1, required=True) arg_type = StringField(default="IntArg") params = DictField() def get_arg(self): arg = TYPES[self.arg_type](**self.params) arg.db_entity = self return arg
ããã§ã¯ãèŠãŠã®ãšãããåŒæ°ã®ååããã®åãããã³ãã®åã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ããã远å ã®ãã©ã¡ãŒã¿ãŒã瀺ãããŠããŸãã ç§ãã¡ã®å Žåãããã¯IntArgã§ããã䜿çšã§ãããã©ã¡ãŒã¿ãŒã¯max_valãmin_valãrequiredãdefaultãããã³ORMã«ãã£ãŠæ£ããåŠçãããä»ã®ãã¹ãŠã§ãã
get_arg
颿°
get_arg
ãããŒã¿ããŒã¹ã«ä¿åãããæ§æã§Argã€ã³ã¹ã¿ã³ã¹ãååŸããããšãç®çãšããŠããŸãã ä»ãç§ãã¡ã¯éåžžã颿°ã«è¿œå ããæ³šéãä»ããŠåã
ã®åŒæ°ãèšè¿°ããæ§é ã«åããã©ã©ã€ã«ãå¿
èŠã§ãã ã¯ããã¯ãããããã¯ãã¹ãŠç¹å®ã®ã³ã³ã¹ãã©ã¯ãã«ããŒãžãããåŒæ°ããŒãµãŒã«éãããŸãã
class DBStruct(Document): args = ListField(ReferenceField(DBArg)) def get_structure(self): return {x.name: x.get_arg() for x in self.args}
ããã¯ã¯ããã«åçŽã§ãããåå¥ã«èª¬æãã䟡å€ã¯ã»ãšãã©ãããŸããã ããããã
ListField(ReferenceField(DBArg))
ãšã察話ãããŠããªã人ã«ãšã£ãŠã¯ã
ListField(ReferenceField(DBArg))
æ§ç¯ã¯ããã®ãã£ãŒã«ãã®ããŒã¿ããŒã¹ã«DBArgã¯ã©ã¹ã®èŠçŽ ã®ãªã¹ããæ ŒçŽããããšãæå³ãã
ListField(ReferenceField(DBArg))
ããããšãæç¢ºã«ãã䟡å€ããããŸãã
ãŸããäžèšã匷åºã§å
·äœçãªãã®ã«æ§æãããã®ãå¿
èŠã§ãã ãã¹ãŠãçããŠããã¿ã¹ã¯ã«é©çšãããšã ãèšã£ãŠã¿ãŸãããã ãããŠããã®ãããªã¿ã¹ã¯ããããŸãã ããªããšç§ã«ã¹ãã¢ãŸãã¯ãªãŒã¯ã·ã§ã³ããããšä»®å®ããŸãããã æã
ããã¯ãããã®ããã«èµ·ãããŸãã 管çããã«ã®ã¿ã¹ã¯ã¯ããšããããååã®ã«ããŽãªãäœæã§ããå¿
èŠããããŸããååã®ã«ããŽãªã«ã¯ããããåºæã®ãã©ã¡ãŒã¿ããããŸãã ããã§ããã®ã¿ã¹ã¯ãå®è¡ããŸãã
class Category(Document): name = StringField(primary_key=True) label = StringField() parent = ReferenceField('self') arg_structure = ReferenceField(DBStruct) def get_creator(self): @Endpoint @annotate(**self.arg_structure.get_structure()) def creator(**kwargs): return Item(data=kwargs).save() creator.__name__ = "create_" + self.name return creator def get_getter(self): pass
ããã§ã¯ãã«ããŽãªã¢ãã«ã«ã€ããŠèª¬æããŸããã 颿°ãšãšã³ããã€ã³ãã®åœåã«å¿
èŠãªã·ã¹ãã åã衚瀺åïŒããã¯äœãæå³ããªãïŒãããã³èŠªïŒã¯ããç¶æ¿ã®ããã«äºåã«æºåããŸãïŒããããŸãã ããã«ããã®ã«ããŽãªã«äœ¿çšãããããŒã¿æ§é ã瀺ãããŠããŸãã æåŸã«ããã®ã«ããŽãªã®äœæè
颿°ãèªåçã«äœæãã颿°ã説æãããŠããŸãã ããã§ãã£ãã·ã¥ãšä»ã®ã°ããºããã蟌ãã®ã¯ããããšã§ãããä»ã®ãšãããå®éšã®äžç°ãšããŠããããç¡èŠããŸãã
æåŸã«ããšã³ããŠãŒã¶ãŒã補åã«é¢ããæ
å ±ãã¢ããããŒãããããã®ãŠãŒã¶ãŒããŒã¿ãä¿åããããã®ã¢ãã«ãå¿
èŠã§ãã ããã§ã¯ã以åã®ãã¹ãŠã®äŸãšåæ§ã«ãããã¯ç°¡ç¥åããã圢åŒã§è¡šç€ºãããŸãã
class Item(Document): data = DictField() category = ReferenceField(Category)
ç¹å¥ãªèª¬æã¯ãŸã£ããå¿
èŠãªããšæããŸãã
ããã§ã¯ã補åã®æåã®ã«ããŽãªãäœæããŸãããã
>>> weight = DBArg(name="weight", params={'max_val': 500, 'min_val':0, 'required': True}).save() >>> height = DBArg(name="height", params={'max_val': 290}).save() >>> human_argstructure = DBStruct(args=[weight, height]).save() >>> human = Category(name="human", arg_structure=human_argstructure).save()
ã¯ããç§ã¯äººã
ã売ãããšã¯éåžžã«å«ççã§ã¯ãªãããšãç¥ã£ãŠããŸãããããã¯ã¡ããã©ããèµ·ãããŸãã:)
次ã«ãååã®ååãäœæããã©ãããŒãå¿
èŠã§ãã
@app.route('/step15_abstract') def abstract_add_item(category: ItemArg(Category, required=True, p_type=str)): creator = category.get_creator() wrapped_creator = app._arg_taker(creator) return str(wrapped_creator().id)
ä»ã§ã¯éåžžã«ãã§ãã ããã¯ãã¢ãŒããã¯ãã£ã®å¥ã®èª€ãã«ãããã®ã§ãã ãã ããåã®ãã®ããã¯ããã«éèŠã§ã¯ãããŸããã ãŸãã ããã§äœãèµ·ãã£ãŠããã®ãã説æããŸãã
æåã«ãæ¢ã«äžèšã§èª¬æããæ¹æ³ã§ã«ããŽãªã€ã³ã¹ã¿ã³ã¹ãååŸããŸãïŒ
Note
ã¢ãã«ã®äŸãåç
§ïŒã ãããã£ãŠããŠãŒã¶ãŒãååšããªãã«ããŽãªã«è£œåã远å ããããšãããšãDoesNotExistãåãåããŸãã ãã®ã«ããŽãªã®äž»ããŒã¯ã·ã¹ãã åã§ãããèå¥åãšããŠæž¡ãå¿
èŠãããã®ã¯ãŠãŒã¶ãŒã§ãã ç§ãã¡ã®å Žåãããã¯
human
ã§ãã ãããã£ãŠããªã¯ãšã¹ãå
šäœã¯æ¬¡ã®ããã«ãªããŸãã
localhost:5000/step15_abstract?category=human&weight=100&height=200
æ®ãã¯ãåŒã³åºãããã³ã³ã¹ãã©ã¯ã¿ãä»ã®ãã©ã¡ãŒã¿ãååŸããããã®ãã®ã§ãã
app._arg_taker
ãšã³ããã€ã³ãããœãŒã¹ããæ¬ èœããŠããåŒæ°ããååŸãã§ããããã«ãããã³ã¬ãŒã¿ãŒã ç§ãã¡ã®å Žåãããã¯request.argsã§ãããååãšããŠããœãŒã¹ã¯ä»»æã§ãã å®éããã®ãã©ã°ã¡ã³ãã«ã¯ãç§ã®å»ºç¯äžã®ééãããããŸãã è¯ãæ¹æ³ã§ã¯ããã¹ãããããšã³ããã€ã³ãããã®ãããªãã³ã¬ãŒã¿ã§ã©ããããå¿
èŠã¯çããªãã¯ãã§ãã
æšå®ããŒãžã§ã³ïŒ 決ããŠçµéšã§ã¯ãããŸããçµè«ãšå°æ¥
ããŠãããããããã§ä»æ¥ã¯çµãããŸãã ããã§ãé·ããããã¯ã«ã€ããŠæšæž¬ããããšãã§ããŸãã ãŸããæåã®æçš¿ã«åçããŠããããã¹ãŠã®äººã«æè¬ããããšæããŸãã 誰ãåäžã®å»ºèšçãªææ¡ãããŠããªããšããäºå®ã«ãããããããããªãã¯æ¬åœã«é埳çã«ç§ãå©ããŸãã:)
ãããŠãæå³ã𿬲æã«ã€ããŠç°¡åã«èª¬æããŸãã
ä»åŸæ°ãæã®äž»ãªæ¹åæ§ã¯ãã³ãŒãã®ã³ã¡ã³ãããªãã¡ã¯ã¿ãªã³ã°ããã¹ãã«ãã¬ããžã§ãã ã¯ããç§èªèº«ã¯ããã®é åã§ç§ã®ã³ãŒããããããããŠããããšãç¥ã£ãŠããŸãããããåŠå®ããã®ã¯æããªããšã§ãã
ããã«ãä»ã®ãã¬ãŒã ã¯ãŒã¯ã«ãåŽé¢ã®ãããªããã€ãã®ã²ãŒããäœæããããšæããŸãã äžè¬çã«ãç§ã¯èªåã®å³æžé€šã圹ç«ã€å ŽæãèŠã€ããããšæã£ãŠããŸãã ãããŸã§ã®ãšãããç«å·»ãšargparseã®ã¿ãæè¿ãããŠããŸãã
ã©ã€ãã©ãªèªäœã«ã€ããŠã¯ãããã§ã¯ãã£ãŒãããã¯ã«çŠç¹ãåœãŠãããšãéèŠã ãšèããŠããŸãã ãµã³ããŒåŒæ°ã䜿çšããŠå®ãããªã€ã³ã¿ãŒãã§ã€ã¹ãäœæãããšããŸãã æçµã©ã€ãã©ãªã«æ
å ±ãæäŸã§ããã°ããªãããã®json-rpcãäœæã§ããã®ã§ã
OPTIONS
ãªã¯ãšã¹ãã®ã¯ã©ã€ã¢ã³ãã¯ã©ã®ãã©ã¡ãŒã¿ãŒãåãå
¥ããã©ã®ãšã©ãŒããšã³ããã€ã³ãã§çºçããå¯èœæ§ãããããèŠã€ããããšãã§ããã°ã¯ãŒã«ã§ãã
åŸã§ãå¥ã®æçµèšäºãæžããŸãã 圌女ã¯ãã§ã«ãå®ç掻ãã«ãã£ãããšå·çããŠããŸãã äžéšã®ãµãŒãã¹ã®ã³ãŒãã£ã³ã°ããã»ã¹ã®èª¬æããããšæããŸãã ããã§ã¢ã€ãã¢ã¯1ã€ã ãã«ãªãã1ã€ã®è峿·±ããµã€ãïŒæ²ãããã³ãïŒã®ã¿ã°ã·ã¹ãã ã«æ¥ç¶ãããŸãã ããããç§ã¯ä»ã®ææ¡ãèããŠããããã§ãã ãã€ã¯ãããã°ãQïŒAãã©ãŒã©ã ãªã©ã ç§ã¯ããããªãã£ããã®ãããªããšã«ã€ããŠæ°ã«ããŸããã ãã®ã³ãŒãã®äŸã§ã¯ãç§ã®ãããããã®å¯èœãªéãå€ãã®åŽé¢ã衚瀺ã§ããããšãéèŠã§ãã ãšããããããã«ãããå®éã«ãã§ãã¯ããŠãå Žåã«ãã£ãŠã¯ããã€ãã®ãã°ãã¢ãŒããã¯ãã£äžã®æ¬ é¥ãèŠã€ããããšãã§ããŸãã
ãæž
èŽããããšãããããŸããã ãã€ãã®ããã«ãç§ã¯ã©ããªæ¹å€ãåžæã«ãåãã§ããŸãã
ã¡ã€ã³ã«ããã©ã¹ã³ã²ãŒã ïŒèšäºã®ãã¹ãŠã®å®éšã®ã³ãŒãã¯ãã¡ãïŒ