Express æç¨ 6: 使ç¨è¡¨å
卿¤æç¨ä¸æä»¬ä¼æä½ å¦ä½ä½¿ç¨ Express å¹¶ä¸ç»å Pug æ¥å®ç° HTML 表åï¼å¹¶ä¸å¦ä½ä»æ°æ®åºä¸åå»ºï¼æ´æ°åå é¤ææ¡£ã
| åæï¼ |
宿å颿æçæç¨ï¼å æ¬ Express æç¨ç¬¬ 5 ç« ï¼å±ç¤ºå¾ä¹¦é¦æ°æ® |
|---|---|
| ç®æ ï¼ |
äºè§£å¦ä½ç¼å表åè·åç¨æ·ä¿¡æ¯ï¼å¹¶ä¸å°è¿äºæ°æ®æ´æ°å°æ°æ®åºä¸ã |
æ¦è§
HTML 表åå¨ç½é¡µä¸æ¯ä¸ä¸ªæå¤ä¸ªå段/å°å·¥å ·çéåï¼å®è¢«ç¨æ¥æ¶éç¨æ·çä¿¡æ¯ï¼å¹¶å°ä¿¡æ¯ä¸ä¼ å°æå¡å¨ã表åä½ä¸ºä¸ç§ç¨æ¥æ¶éç¨æ·çæºå¶ï¼é常ççµæ´»ï¼å 为æåç§åéçè¾å ¥æ¡ï¼æ¥æ¥ååç§ç±»åçæ°æ®ââææ¬æ¡ï¼å¤éæ¡ï¼åéæé®ï¼æ¶é´éæ©å¨çã表ååæå¡å¨äº¤äºæ°æ®ä¹ç¸å¯¹å®å ¨ï¼å 为å®ä½¿ç¨ POST 请æ±åéæ°æ®ï¼ä¿æ¤ä¸åè·¨ç«ç¹è¯·æ±ä¼ªé æ»å»ï¼cross-site request forgeryï¼çå¨èã
使¯è¡¨ååæ ·ä¹å¾å¤æï¼å¼åè éè¦ä¸ºè¡¨åç¼å HTMLï¼å¨æå¡å¨ä¸éªè¯ï¼å¹¶ä¸æ£ç¡®å»é¤æå®³çæ°æ®ï¼æµè§å¨ä¸ä¹å¯è½éè¦ï¼ï¼å¯¹äºä»»ä½ä¸åæ³çåæ®µï¼éè¦ä¼ ç»ç¨æ·ç¸åºçé误信æ¯ï¼å½æ°æ®æåæäº¤åï¼å¤çæ°æ®ï¼å¹¶è®¾æ³éç¥ç¨æ·æäº¤æåã
æ¤æç¨å°å±ç¤ºä¸è¿°çæä½ï¼å¦ä½å¨ Express ä¸å®ç°ã卿¤è¿ç¨ä¸ï¼æä»¬å°æ©å± LocalLibrary ç½ç«ï¼ä»¥å è®¸ç¨æ·å建ï¼ç¼è¾åå é¤å¾ä¹¦é¦ä¸ç项ç®ã
夿³¨ï¼æä»¬è¿æ²¡æèèå¦ä½å°ç¹å®è·¯ç±ï¼éå¶ä¸ºç»è¿èº«ä»½éªè¯æææçç¨æ·ï¼å æ¤å¨è¿ä¸ªæ¶é´ç¹ï¼ä»»ä½ç¨æ·é½å¯ä»¥å¯¹æ°æ®åºè¿è¡æ´æ¹ã
HTML 表å
é¦å ç®è¦æ¦è¿°HTML 表åãèèä¸ä¸ªç®åç HTML 表åï¼å ¶ä¸å å«ä¸ä¸ªææ¬å段ï¼ç¨äºè¾å ¥æäºâå¢éâçåç§°ï¼åå ¶ç¸å ³æ ç¾ï¼
![]()
表åå¨ HTML ä¸ï¼å®ä¹ä¸º<form>...</form>æ è®°å
çå
ç´ éåï¼å
å«è³å°ä¸ä¸ªtype="submit"çinputè¾å
¥å
ç´ ã
请注æï¼æéå¸¸å»ºè®®ä½ è¿éä½¿ç¨ input ç submit è䏿¯ buttonï¼è¿ä¼ä½¿ä½ æå°ææ¦ã
<form action="/proxy/developer.mozilla.org/team_name_url/" method="post">
<label for="team_name">Enter name: </label>
<input
id="team_name"
type="text"
name="name_field"
value="Default name for team." />
<input type="submit" value="OK" />
</form>
è½ç¶è¿éï¼æä»¬åªå
å«ä¸ä¸ªï¼ææ¬ï¼å段ï¼ç¨äºè¾å
¥å¢éåç§°ï¼ä½è¡¨åå¯è½å
å«ä»»ææ°éçå
¶ä»è¾å
¥å
ç´ ï¼åå
¶ç¸å
³æ ç¾ãåæ®µç type 屿§ï¼å®ä¹å°æ¾ç¤ºåªç§çªå£å°é¨ä»¶ãè¯¥åæ®µçåç§° name å id ï¼ç¨äºæ è¯ JavaScript/CSS/HTML ä¸çåæ®µï¼è valueå®ä¹åæ®µé¦æ¬¡æ¾ç¤ºæ¶çåå§å¼ãå¹é
å¢éæ ç¾ä½¿ç¨ label æ ç¾ï¼æå®ï¼è¯·åé
ä¸é¢çâè¾å
¥åç§°â "Enter name"ï¼ï¼å
¶ä¸ for åæ®µï¼å
å« input ç¸å
³è¾å
¥ç id å¼ã
å¦å¤ï¼æå¿ è¦è¯´ä¸ä¸ï¼HTML ä¸ form 表åé»è®¤å°±æ¯ä»¥ post æäº¤çã宿¯ get æ¹å¼åå¨éæ´å¤§ãä¼ è¾æ´å®å ¨ã
æäº¤è¾å
¥ï¼submitï¼å°æ¾ç¤ºä¸ºæé®ï¼é»è®¤æ
åµä¸ï¼ - ç¨æ·å¯ä»¥ææ¤æé®ï¼å°å
¶ä»è¾å
¥å
ç´ å
å«çæ°æ®ï¼ä¸ä¼ å°æå¡å¨ï¼å¨æ¬ä¾ä¸ï¼åªæteam_nameï¼ã表å屿§ï¼å®ä¹ç¨äºåéæ°æ®ç HTTP methodæ¹æ³ï¼åæå¡å¨ä¸æ°æ®çç®æ ï¼actionï¼ï¼
action: æäº¤è¡¨åæ¶ï¼è¦åéæ°æ®ä»¥è¿è¡å¤ççèµæº/ URLã妿æªè®¾ç½®ï¼æè®¾ç½®ä¸ºç©ºå符串ï¼ï¼å表åå°æäº¤åå½åé¡µé¢ URLãmethod: ç¨äºåéæ°æ®ç HTTP æ¹æ³ï¼POSTæGETã- å¦ææ°æ®å°å¯¼è´æå¡å¨æ°æ®åºçæ´æ¹ï¼åå§ç»åºè¯¥ä½¿ç¨
POSTæ¹æ³ï¼å ä¸ºè¿æ´å å¯ä»¥æµæè·¨ç«ç¹ä¼ªé è¯·æ±æ»å»ã GETæ¹æ³åªåºç¨äºä¸æ´æ¹ç¨æ·æ°æ®ç表åï¼ä¾å¦ï¼æç´¢è¡¨åï¼ãå½ä½ 叿è½å¤ä¸º URL æ·»å ä¹¦ç¾æå ±äº«æ¶ï¼å»ºè®®ä½¿ç¨æ¤é项ã
- å¦ææ°æ®å°å¯¼è´æå¡å¨æ°æ®åºçæ´æ¹ï¼åå§ç»åºè¯¥ä½¿ç¨
表åå¤çæµç¨
表åå¤ç使ç¨çææ¯ï¼ä¸æä»¬å¦ä¹ è¿ãç¨æ¥æ¾ç¤ºæå ³æ¨¡åçä¿¡æ¯çææææ¯ï¼æ¯ç¸åçï¼è·¯ç±å°æä»¬ç请æ±åéå°æ§å¶å¨å½æ°ï¼è¯¥å½æ°æ§è¡æéç任使°æ®åºæä½ï¼å æ¬ä»æ¨¡åä¸è¯»åæ°æ®ï¼ç¶åçæå¹¶è¿å HTML 页é¢ãä½¿äºæ å徿´å¤æçæ¯ï¼æå¡å¨è¿éè¦è½å¤å¤çç¨æ·æä¾çæ°æ®ï¼å¹¶å¨åºç°ä»»ä½é®é¢æ¶ï¼éæ°æ¾ç¤ºå¸¦æé误信æ¯ç表åã
ä¸é¢æ¾ç¤ºäºå¤ç表å请æ±çæµç¨å¾ï¼ä»å å«è¡¨åç页é¢è¯·æ±å¼å§ï¼ä»¥ç»¿è²æ¾ç¤ºï¼ï¼

å¦ä¸å¾æç¤ºï¼ææå¤çä»£ç æéè¦åçä¸»è¦æ¯ï¼
-
å¨ç¨æ·ç¬¬ä¸æ¬¡è¯·æ±æ¶æ¾ç¤ºé»è®¤è¡¨åã
- 表åå¯è½å å«ç©ºç½å段ï¼ä¾å¦ï¼å¦æä½ æ£å¨å建æ°è®°å½ï¼ï¼æè å¯è½é¢å å¡«å äºåå§å¼ï¼ä¾å¦ï¼å¦æä½ è¦æ´æ¹è®°å½ï¼æè å ·ææç¨çé»è®¤åå§å¼ï¼ã
-
æ¥æ¶ç¨æ·æäº¤çæ°æ®ï¼é常æ¯å¨ HTTP
POST请æ±ä¸ã -
éªè¯å¹¶æ¸ çæ°æ®ã
-
妿任使°æ®æ æï¼è¯·éæ°æ¾ç¤ºè¡¨å - è¿æ¬¡ä½¿ç¨ç¨æ·å¡«åçä»»ä½å¼ï¼åé®é¢å段çéè¯¯æ¶æ¯ã
-
å¦ææææ°æ®é½ææï¼è¯·æ§è¡æéçæä½ï¼ä¾å¦ï¼å°æ°æ®ä¿å卿°æ®åºä¸ï¼åééç¥çµåé®ä»¶ï¼è¿åæç´¢ç»æï¼ä¸ä¼ æä»¶çï¼
-
å®ææææä½åï¼å°ç¨æ·éå®åå°å¦ä¸ä¸ªé¡µé¢ã
è¡¨æ ¼å¤ç代ç ï¼é常使ç¨GETè·¯ç±ï¼ä»¥å®ç°è¡¨åçåå§æ¾ç¤ºï¼ä»¥åPOSTè·¯ç±å°åä¸è·¯å¾ï¼ä»¥å¤çè¡¨åæ°æ®çéªè¯åå¤çãè¿æ¯å°å¨æ¬æç¨ä¸ä½¿ç¨çæ¹æ³ï¼Express æ¬èº«ä¸æä¾è¡¨åå¤çæä½çä»»ä½ç¹å®æ¯æï¼ä½å®å¯ä»¥ä½¿ç¨ä¸é´ä»¶ï¼ä»¥å¤ç表åä¸çPOSTåGETåæ°ï¼å¹¶éªè¯/æ¸
çå®ä»¬çå¼ã
éªè¯åæ¸ ç
å¨å¨å表åä¸çæ°æ®ä¹åï¼å¿ é¡»å¯¹å ¶è¿è¡éªè¯åæ¸ çï¼
- éªè¯æ£æ¥è¾å ¥çå¼ï¼éç¨äºæ¯ä¸ªå段ï¼èå´ï¼æ ¼å¼çï¼ï¼å¹¶ä¸å·²ä¸ºææå¿ å¡«åæ®µæä¾äºå¼ã
- æ¸ çå é¤/æ¿æ¢æ°æ®ä¸çå符ï¼å¯è½ç¨äºå°æ¶æå 容åéå°æå¡å¨ã
卿¬æç¨ä¸ï¼æä»¬å°ä½¿ç¨æµè¡ç express-validator 模åï¼æ¥æ§è¡è¡¨åæ°æ®çéªè¯åæ¸ çã
å®è£
éè¿å¨é¡¹ç®çæ ¹ç®å½ä¸ï¼è¿è¡ä»¥ä¸å½ä»¤æ¥å®è£ 模åã
npm install express-validator --save
ä½¿ç¨ express-validator
夿³¨ï¼Github ä¸çexpress-validatoræåï¼æä¾äº API çè¯å¥½æ¦è¿°ãæä»¬å»ºè®®ä½ é 读该å 容ï¼ä»¥äºè§£å ¶ææåè½ï¼å æ¬å建èªå®ä¹éªè¯ç¨åºï¼ãä¸é¢æä»¬åªä»ç»ä¸ä¸ªå¯¹ LocalLibrary æç¨çåéã
è¦å¨æä»¬çæ§å¶å¨ä¸ä½¿ç¨éªè¯å¨ï¼æä»¬å¿ é¡»ä»'express-validator/check'å'express-validator/filter'模åä¸ï¼å¯¼å ¥æä»¬æ³è¦ä½¿ç¨ç彿°ï¼å¦ä¸æç¤ºï¼
const { body, validationResult } = require("express-validator/check");
const { sanitizeBody } = require("express-validator/filter");
æè®¸å¤å¯ç¨çåè½ï¼å
è®¸ä½ ä¸æ¬¡æ£æ¥åæ¸
ç请æ±åæ°ï¼æ£æï¼æ 头ï¼cookie çæ°æ®ï¼ææææ°æ®ãå¯¹äºæ¬æç¨ï¼æä»¬ä¸»è¦ä½¿ç¨bodyï¼ sanitizeBodyï¼å validationResultï¼å¦ä¸é¢â导å
¥âçï¼ã
åè½å®ä¹å¦ä¸ï¼
-
body(fields[, message]): æå®è¯·æ±æ¬æä¸çä¸ç»å段ï¼POSTåæ°ï¼ä»¥åå¯éçéè¯¯æ¶æ¯ï¼å¦ææµè¯å¤±è´¥ï¼åå¯ä»¥æ¾ç¤ºè¯¥å段ãéªè¯æ å以èè±é¾å½¢å¼è¿æ¥å°body()æ¹æ³ãä¾å¦ï¼ä¸é¢ç第ä¸ä¸ªæ£æ¥æµè¯ï¼ânameâåæ®µä¸ä¸ºç©ºï¼å¦æä¸æ¯ï¼å设置éè¯¯æ¶æ¯âEmpty nameâã第äºä¸ªæµè¯ï¼æ£æ¥ age åæ®µæ¯å¦ä¸ºæææ¥æï¼å¹¶ä½¿ç¨optional()æå® null å空å符串ä¸ä¼éªè¯å¤±è´¥ãjsbody('name', 'Empty name').isLength({ min: 1 }), body('age', 'Invalid age').optional({ checkFalsy: true }).isISO8601(),ä½ è¿å¯ä»¥ç¨èè±é¾å¼è¿æ¥ä¸åçéªè¯å¨ï¼å¹¶æ·»å åé¢éªè¯å¨ä¸ºçæ¶æ¾ç¤ºçæ¶æ¯ã
jsbody('name').isLength({ min: 1 }).trim().withMessage('Name empty.') .isAlpha().withMessage('Name must be alphabet letters.'),夿³¨ï¼
ä½ è¿å¯ä»¥æ·»å å èæ¸ çå¨ï¼å¦
trim()ï¼å¦ä¸æç¤ºã使¯ï¼æ¤å¤åºç¨æ¸ çå¨ï¼ä» éç¨äºéªè¯æ¥éª¤ã妿è¦å¯¹æç»è¾åºè¿è¡æ¶æ¯ï¼åéè¦ä½¿ç¨åç¬çæ¸ ç卿¹æ³ï¼å¦ä¸æç¤ºã -
sanitizeBody(fields): æå®ä¸ä¸ªæ£æè¦æ¸ ççåæ®µãç¶åå°æ¸ çæä½ï¼ä»¥èè±é¾å½¢å¼è¿æ¥å°æ¤æ¹æ³ãä¾å¦ï¼ä¸é¢çescape()æ¸ çæä½ï¼ä¼ä»åç§°åéä¸ï¼å é¤å¯è½å¨ JavaScript è·¨ç«ç¹èæ¬æ»å»ä¸ä½¿ç¨ç HTML å符ãjssanitizeBody('name').trim().escape(), sanitizeBody('date').toDate(), -
validationResult(req): è¿è¡éªè¯ï¼ä»¥validationéªè¯ç»æå¯¹è±¡çå½¢å¼ï¼æä¾é误ãè¿æ¯å¨åç¬çåè°ä¸è°ç¨çï¼å¦ä¸æç¤ºï¼js(req, res, next) => { // Extract the validation errors from a request. const errors = validationResult(req); if (!errors.isEmpty()) { // There are errors. Render form again with sanitized values/errors messages. // Error messages can be returned in an array using `errors.array()`. } else { // Data from form is valid. } };æä»¬ä½¿ç¨éªè¯ç»æç
isEmpty()æ¹æ³ï¼æ¥æ£æ¥æ¯å¦åå¨é误ï¼å¹¶ä½¿ç¨å ¶array()æ¹æ³ï¼æ¥è·åéè¯¯æ¶æ¯éåãæå ³æ´å¤ä¿¡æ¯ï¼è¯·åé éªè¯ç»æ APIã
éªè¯åæ¸ çé¾ï¼æ¯åºè¯¥ä¼ éç» Express è·¯ç±å¤çç¨åºçä¸é´ä»¶ï¼æä»¬éè¿æ§å¶å¨ï¼é´æ¥å°æ§è¡æ¤æä½ï¼ãä¸é´ä»¶è¿è¡æ¶ï¼æ¯ä¸ªéªè¯å¨/æ¸ çç¨åºé½ææå®ç顺åºè¿è¡ã 彿们å®ç°ä¸é¢ç LocalLibrary è¡¨åæ¶ï¼æä»¬å°ä»ç»ä¸äºçå®çä¾åã
表å设计
å¾ä¹¦é¦ä¸çè®¸å¤æ¨¡å齿¯ç¸å ³/ä¾èµç - ä¾å¦ï¼ä¸æ¬ä¹¦éè¦ä¸ä¸ªä½è ï¼ä¹å¯è½æä¸ä¸ªæå¤ä¸ªç§ç±»ãè¿æåºäºä¸ä¸ªé®é¢ï¼å³æä»¬åºè¯¥å¦ä½å¤çç¨æ·å¸æçæ åµï¼
- å¨å ¶ç¸å ³å¯¹è±¡å°ä¸å卿¶ï¼å建对象ï¼ä¾å¦ï¼å°æªå®ä¹ä½è 对象ç书ï¼ã
- å é¤å¦ä¸ä¸ªå¯¹è±¡ä»å¨ä½¿ç¨ç对象ï¼ä¾å¦ï¼å é¤ä»æä¹¦æ¬ä½¿ç¨çç§ç±»ï¼ã
å¨è¿ä¸ªé¡¹ç®ï¼æä»¬å°ç®å声æè¡¨ååªè½ï¼
- 使ç¨å·²åå¨ç对象å建对象ï¼å æ¤ç¨æ·å¨å°è¯å建任ä½
Book对象ä¹åï¼å¿ é¡»åå»ºä»»ä½æéçAuthoråGenreå®ä¾ï¼ã - å¦æå¯¹è±¡æªè¢«å
¶ä»å¯¹è±¡å¼ç¨ï¼åå é¤è¯¥å¯¹è±¡ï¼ä¾å¦ï¼å¨å 餿æå
³èç
BookInstance对象ä¹åï¼ä½ å°æ æ³å é¤è¯¥ä¹¦ï¼ã
让æä»¬ççæ´é«çº§çå 容å§ï¼
æä»¬é常ä¼å¨âåå°âæ¥æ¶ form 表åæäº¤çæ°æ®ãæ¾èæè§ï¼è¿éåºè¯¥æ¯ expressï¼
é¦å æä»¬å¯ä»¥ç¥éï¼ä¹è®¸ä½ ä¼ç¥éï¼åºè¯¥å å¼å ¥ expressï¼
const app=express();
è¿å¾å¥½ã
é£ä¹æ¢ç¶æ¯ post æäº¤ï¼ç»å¤§å®¶æ¨è䏿¬¾ä¸é´ä»¶ï¼body-parserãå®è½è®©ä½ è½»æ¾å°å¤ç body æ°æ®ã
å¦ï¼å¦æä½ æ¶åæä»¶ä¸ä¼ ï¼é£ä¹ä½ å¯è½éè¦âmulterâä¸é´ä»¶ï¼ä½ 大æ¦å¬è¯´è¿âformidableâï¼ä½ multer æ¯å®æ´å¼ºå¤§ï¼
夿³¨ï¼æ´âç¢åºâçå®ç°ï¼å¯è½å è®¸ä½ å¨å建æ°å¯¹è±¡æ¶å建ä¾èµå¯¹è±¡ï¼å¹¶éæ¶å é¤ä»»ä½å¯¹è±¡ï¼ä¾å¦ï¼éè¿å é¤ä¾èµå¯¹è±¡ï¼æä»æ°æ®åºä¸ï¼å é¤å¯¹å·²å é¤å¯¹è±¡çå¼ç¨ï¼ ã
è·¯ç±
为äºå®ç°æä»¬ç表åå¤ç代ç ï¼æä»¬éè¦ä¸¤ä¸ªå ·æç¸å URL 模å¼çè·¯ç±ã
第ä¸ä¸ªï¼GETï¼è·¯ç±ï¼ç¨äºæ¾ç¤ºç¨äºåå»ºå¯¹è±¡çæ°ç©ºè¡¨åã第äºä¸ªè·¯ç±ï¼POSTï¼ï¼ç¨äºéªè¯ç¨æ·è¾å
¥çæ°æ®ï¼ç¶åä¿åä¿¡æ¯ï¼å¹¶éå®åå°è¯¦ç»ä¿¡æ¯é¡µé¢ï¼å¦ææ°æ®ææï¼ï¼æéæ°æ¾ç¤ºæé误ç表åï¼å¦ææ°æ®æ æï¼ã
æä»¬å·²ç»å¨ /routes/catalog.jsï¼å¨ä¹åçæç¨ä¸ï¼ä¸ºæä»¬æææ¨¡åçå建页é¢ï¼å建äºè·¯å¾ãä¾å¦ï¼ç§ç±»è·¯ç±å¦ä¸æç¤ºï¼
// GET request for creating a Genre. NOTE This must come before route that displays Genre (uses id).
router.get("/genre/create", genre_controller.genre_create_get);
// POST request for creating Genre.
router.post("/genre/create", genre_controller.genre_create_post);
Express 表ååæä»¶
以ä¸åæä»¶ï¼å°å¸¦æä»¬å®æå示ä¾åºç¨ç¨åºæ·»å æé表åçè¿ç¨ãå¨è¿å ¥ä¸ä¸ä¸ªæä»¶ä¹åï¼ä½ éè¦ä¾æ¬¡é è¯»å¹¶è§£å³æ¯ä¸ªé®é¢ã
- å建ç§ç±»è¡¨å â å®ä¹æä»¬ç页é¢ä»¥å建
Genreç§ç±»å¯¹è±¡ã - å建ä½è 表å â å®ä¹ç¨äºå建ä½è 对象ç页é¢ã
- å建书æ¬è¡¨å â å®ä¹é¡µé¢/表å以å建书æ¬å¯¹è±¡ã
- å建书æ¬å®ä¾è¡¨å â å®ä¹é¡µé¢/表å以å建书æ¬å®ä¾å¯¹è±¡ã
- å é¤ä½è 表å â å®ä¹è¦å é¤ä½è 对象ç页é¢ã
- æ´æ°ä¹¦æ¬è¡¨å â å®ä¹é¡µé¢ä»¥æ´æ°ä¹¦æ¬å¯¹è±¡ã
ææèªæ
å®ç°Book, BookInstance, å Genre模åçå é¤é¡µé¢ï¼ä»¥ä¸æä»¬çä½è
å é¤é¡µé¢ç¸åçæ¹å¼ï¼å°å®ä»¬ä¸å
³èç详ç»ä¿¡æ¯é¡µé¢ï¼é¾æ¥èµ·æ¥ã页é¢åºéµå¾ªç¸åçè®¾è®¡æ¹æ³ï¼
- å¦æææ¥èªå ¶ä»å¯¹è±¡çã对äºå¯¹è±¡çå¼ç¨ï¼ååºæ¾ç¤ºæ³¨éï¼ååºè¿äºå¯¹è±¡ï¼å¹¶è¯´æå¨å é¤ååºç对象ä¹åï¼æ æ³å 餿¤è®°å½ã
- å¦ææ²¡æå¯¹è¯¥å¯¹è±¡çå ¶ä»å¼ç¨ï¼åè§å¾åºæç¤ºå é¤å®ãå¦æç¨æ·æä¸âå é¤âæé®ï¼ååºå é¤è¯¥è®°å½ã
ä¸äºæç¤ºï¼
- å é¤ç§ç±»
Genreå°±åå é¤ä½èAuthor䏿 ·ï¼å ä¸ºä¸¤ä¸ªå¯¹è±¡é½æ¯Bookçä¾èµé¡¹ï¼å æ¤å¨è¿ä¸¤ç§æ åµä¸ï¼åªæå¨å é¤ç¸å ³ä¹¦æ¬æ¶ï¼æè½å é¤å¯¹è±¡ï¼ã - å é¤ä¹¦æ¬
Bookä¹å¾ç¸ä¼¼ï¼ä½ä½ éè¦æ£æ¥æ¯å¦æ²¡æå ³èç书æ¬å®ä¾BookInstancesã - å é¤ä¹¦æ¬å®ä¾
BookInstanceæ¯æç®åçï¼å 为没æä¾èµå¯¹è±¡ãå¨è¿ç§æ åµä¸ï¼ä½ åªéæ¾å°ç¸å ³è®°å½å¹¶å°å ¶å é¤å³å¯ã
å®ç°BookInstance, Author, å Genre模åçæ´æ°é¡µé¢ï¼ä»¥ä¸æä»¬çä¹¦æ¬æ´æ°é¡µé¢ç¸åçæ¹å¼ï¼å°å®ä»¬ä¸å
³èç详ç»ä¿¡æ¯é¡µé¢ï¼é¾æ¥èµ·æ¥ã
ä¸äºæç¤ºï¼
- æä»¬åå宿½çå¾ä¹¦æ´æ°é¡µé¢æ¯æé¾çï¼ç¸åçæ¨¡å¼å¯ç¨äºå ¶ä»å¯¹è±¡çæ´æ°é¡µé¢ã
- ä½è æ»äº¡æ¥æååºçæ¥æåæ®µä»¥å书æ¬å®ä¾ due_date åæ®µï¼æ¯è¾å ¥å°è¡¨å䏿¥æè¾å ¥å段çéè¯¯æ ¼å¼ï¼å®éè¦âYYYY-MM-DDâå½¢å¼çæ°æ®ï¼ãè§£å³æ¤é®é¢çæç®åæ¹æ³ï¼æ¯ä¸ºé彿 ¼å¼åçæ¥æï¼å®ä¹æ°çèæå±æ§ï¼ç¶åå¨å ³èçè§å¾æ¨¡æ¿ä¸ï¼ä½¿ç¨æ¤å段ã
- å¦æä½ éå°å°é¾ï¼æ¤å¤ç¤ºä¾ä¸çæ´æ°é¡µé¢æä¸äºç¤ºä¾ã
æ»ç»
Express, node, ä¸ NPM ä¸é¢çç¬¬ä¸æ¹å¥ä»¶ï¼æä¾ä½ éè¦çæ¯æ ·ä¸è¥¿ï¼å¯ç¨äºæ°å¢è¡¨åå°ä½ çç½ç«ä¸ã卿¬æä¸ï¼ä½ å¦å°äºå¦ä½ä½¿ç¨ Pug, how to create forms using Pug, validate and sanitize input using express-validator, and add, delete, and modify records in the database.
ä½ ç°å¨åºè¯¥äºè§£å¦ä½æ°å¢åºæ¬è¡¨åï¼ä»¥å表åå¤çç å°ä½ ç node ç½ç«ï¼
åè§
- express-validatorï¼npm ææ¡£ï¼ã