Mësimi i thellë praktik i bazuar në ueb dhe siguria me shembull

Daisyfotoja e profilit

Nga Daisy

Mësim dhe siguri e thellë praktike e bazuar në internet me shembull Botim i tretë Charlotte Harper 3 korrik 2024 Parathënie: Konsideratat e sigurisë në ndërtimin e softuerit për Ueb janë një pjesë e rëndësishme e planit dhe ekzekutimit të çdo zhvilluesi të internetit ndërsa inxhinieroni një prototip që është i besueshëm, i qëndrueshëm dhe i dobishëm për qëllime praktike. DOM (shënimi i objektit të dokumentit), me zbatimin e tij të HTML, JavaScript, dhe CSS, si dhe softuer backend që zbatojnë Python, C/C ++, Java dhe Bash, u japin zhvilluesve të uebit lirinë dhe fuqinë për të krijuar një larmi të gjerë projektesh që shprehin krijimtaria, siguroni lehtësi të përdorimit dhe funksionalitetit, portretizoni përulësinë dhe karakter Vrasni kohën ose bëni diçka të bërë në internet, zakonisht në një pajisje smartphone me ekran me prekje. Shumica e njerëzve as nuk do të dinin se ku të fillojnë kur duan të ndërtojnë një faqe në internet nga e para,Ata do të priren të fillojnë në faqen e internetit të një personi tjetër dhe të ndërtonin diçka të kufizuar në funksionalitet, besueshmëri, lehtësi përdorimi dhe veçanërisht krijimtarinë kur ata mund të kishin të gjitha mjetet më të fundit të fuqishme në dispozicion të tyre në mënyrë që të ndërtojnë diçka të dobishme pa humbur kohën e shtypjes së kohës, dhe Sidomos humbja e parave duke paguar abonime të shtrenjta për softuer pak njerëz donin të përdorin gjithsesi duke pasur parasysh kufizimet e tij në lehtësinë e përdorimit dhe fleksibilitetit. Nëse keni disa minuta për të lexuar përmes këtij libri dhe të mësoni se çfarë dua t'ju mësoj, ose edhe të flisni me mua personalisht për qëllimet tuaja dhe të merrni disa udhëzime në drejtimin e duhur, dhe janë të motivuar të mësojnë të kodojnë dhe të shkruajnë softuerin tuaj , Merrni këtë libër në shtëpi dhe lini mënjanë ca kohë për të mësuar të ndërtoni aplikacionin tjetër me ndikim, të fuqishëm, të thjeshtë dhe të rëndësishëm në internet, një faqe në internet që është gjithçka për ju dhe bën pikërisht atë që dëshironi dhe plotëson nevojat e audiencës tuaj. Për mua: Unë jam një zhvillues i softuerit me një të gjerëAnge e përvojës në C/C ++, Java, Python, HTML, CSS dhe JavaScript. Unë ndërtoj faqet e internetit që njerëzit duan të përdorin, duan të vizitojnë, dhe madje të jem i varur nga përdorimi i vetëm për të mësuar, rikrijuar dhe vrarë kohën, dhe më e rëndësishmja, unë shes softuer. Nëse keni pasur një ide se si keni dashur që një faqe në internet të shikonte dhe të funksiononte, ju ishit të gatshëm të më mbështesnit, në mënyrë që të mund të përmbushja nevojat e mia ndërsa unë takoj tuajin, dhe ju jeni të gatshëm të mbuloni kostot e drejtimit të një faqe në internet vetë, Unë do t'ju ndërtoja YouTube, tiktok, Twitter, Google, apo edhe një aplikacion sigurie të teknologjisë së lartë vetëm që mund të përdorni. Në vend që të përpiqem t'ju shes kohën time, unë jam duke u përpjekur të blej tuajin: Unë dua t'ju flas për të ndërtuar një aplikacion (uebfaqe) vetë me informacionin që tashmë ekziston, dhe t'ju mësoj atë që ju nevojitet për të qenë një zhvillues i pavarur i softuerit, Sipërmarrësi, duke udhëhequr një karrierë të suksesshme në çfarëdo fushe që dëshironi. Dhe më lejoni të jem i qartë, arsimi që ju jap do të jetë joformal. Ju mund të shkoni në shkollë dhe të mësoni të gjitha këto me njëEdukimi RMal, ose edhe lexoni këtë libër në shkollë, plotësoni detyrat tuaja dhe hiqni shumë nga edukimi juaj, por unë nuk do t'ju vë zyrtarisht në vendin e nxehtë dhe t'ju kërkoj të plotësoni detyrat. Unë nuk jam profesori juaj, ju mund të mendoni për mua si një mik i cili dëshiron t'ju udhëzojë drejt një karriere të drejtuar nga suksesi juaj personal. Dhe unë nuk jam duke ju shitur as sukses, do t'ju duhet ta blini me kohën tuaj. Mësimi për të koduar ka një kurbë të pjerrët të të mësuarit dhe nuk ishte kurrë e lehtë, apo edhe supozohej të ishte. Ju duhet të punoni sa më shumë që të keni mundësi dhe të vazhdoni të provoni dhe të dështoni dhe të provoni përsëri edhe kur jeni të irrituar në mënyrë që të mësoni dhe ndërtoni vetë aplikacione. Kjo është në natyrën e vetë kodit. Kodi drejtohet nga një përpilues që është krijuar për t'i dhënë mesazheve të gabimit të programuesit, dhe këto do t'ju mësojnë se si të kodoni, edhe nëse thjesht po kopjoni gabimin në motorin tuaj të kërkimit dhe duke lexuar shembujt e njerëzve të tjerë. Dhe unë duhet të them, ju nuk keni nevojë të jeni jashtëzakonisht të pasur, të zgjuar, të suksesshëm,En me detaje të orientuara ose të organizuara për të ndërtuar një aplikacion. Kompjuteri kujdeset për atë organizatë për ju. Thjesht duhet të vazhdoni përmes provës dhe gabimit, të mbani fokusin dhe të punoni shumë në atë që bëni, dhe do të keni një karrierë shumë të suksesshme në tërësinë e asaj që bëni. Kush jam: Unë e kuptoj që pjesa e fundit kishte të bënte më shumë me të mësuarit dhe të marrësh një rrugë nga ky libër. Kush jam unë saktësisht? Kjo është një pyetje e ndërlikuar. Unë jam i paqartë për këtë vetë, pasi vuaj nga kushtet mjekësore që mund ta bëjnë të vështirë për mua madje të kodoj ose të shkruaj këtë libër herë pas here, ndërsa paraqes sfida me shoqërizimin dhe çështjet e identitetit që e bëjnë jetën time më të vështirë kur bëhet fjalë për prezantimin e vetvetes . Me pak fjalë, nëse po e lexoni këtë libër, ju e sollët në shtëpi sepse e keni përshkuar atë dhe keni menduar se ishte e dobishme, ose edhe nëse thjesht lexoni këtë larg, për ju, unë jam një individ me mendje që dëshiron të shohë që të keni sukses gjithçka që bëni ju. Unë jam një inxhinier vetë, një softuerZhvilluesi, dhe një student, dhe unë po shkruaj këtë libër për studentët e tjerë që duan ta bëjnë jetën e tyre më të lehtë duke pasur një manual të softuerit për të cilin u duhen më lehtë jetën e tyre duke dhënë shembuj për të kopjuar atë që përshtatet së bashku si një enigmë e madhe në një punë , i dobishëm, i madh, funksional, koheziv dhe aplikacioni tërheqës që mund të nxisë suksesin pa marrë parasysh linjën e biznesit. Kryesisht, kjo është ajo që unë bëj: Unë ndërtoj aplikacione për të ndihmuar veten dhe njerëzit e tjerë të kenë sukses. Unë jam gjithashtu një autor, megjithëse ky është botimi im i parë që kam ndërmend të përfundoj në mënyrë që ta vendos portofolin tim së bashku në një dokument të dobishëm, dhe unë jam një artist gjithashtu. Unë do ta pranoj këtë për ju, unë jam një lloj personi i çuditshëm. Unë nuk jam perfekt, unë kam drejtuar ins me ligjin madje duke më çuar të largohem nga kolegjet dhe universitetet dhe të largohem nga shtetet në mënyrë që të përpiqem të bëj një emër për veten time me më shumë sukses. Unë jam një grua nga lindja, vesh grim, bëj fotografi nga vetja, vesh fustane dhe veshje të tjera të grave, dhe qëndroj i vetëdijshëm për veten time si njëmashkull nga natyra. Unë kam pasur probleme me njerëz të tjerë në të kaluarën që çojnë në luftë me shkrimin dhe ndërtimin e uebfaqeve, dhe kërkoj falje që nuk kam qenë në gjendje ta marr këtë libër në duart tuaja më shpejt: ju duhej kjo. Ju do të dëshironi të lexoni dhe të shkruani kod që duket si i imi dhe funksionon si i imi dhe bën të njëjtën gjë, por edhe më mirë, sepse nëse mund të përballoni të blini këtë libër në vend që të krijoni tastierën tuaj si unë vetëm për të krijuar një libër vetë duke kërkuar para Për të, ju keni burimet që ju nevojiten për të qenë të suksesshëm në jetën tuaj. Unë kisha të gjitha llojet e çështjeve me rritjen e familjes, kushtet shëndetësore, mjekët, mediat dhe ligjin, dhe kodi im pasqyron thellësisht luftën që është feminizmi dhe natyra femërore në një botë të ndarë dhe të irrituar. Sidoqoftë, ky libër është diçka për të cilën më intereson thellësisht, fëmija im, portofoli im dhe jetesa ime, kështu që unë vlerësoj konsiderimin tuaj kur ju merrni tekstin në shtëpi dhe me kujdes pore mbi të në mënyrë që të mësoni nga unë. Ju lutem mbani në mend se nuk jam perfekt,Libri do të ketë gabime, rishikime dhe botime të reja, dhe do t'ju duhet të mendoni me trurin tuaj logjik sa më mirë që të keni mundësi në mënyrë që të keni një përvojë të suksesshme me shkrimin tim. Gjithashtu, kuptoni që dua të them mirë për ju edhe kur përballeni me sfida kur shkruani. Mendoni për këtë si kjo: Kur thjesht mund të merrni me qira një sistem kompjuterik për të bërë gjithçka që mund të imagjinoni në hapësirën dixhitale, të ruani të gjitha informacionet që hasni, #$%! YZE dhe ta organizoni, dhe të kuptoni, ju do Në mënyrë të pashmangshme hasni vështirësi me informacionin që ju jeni duke gëlltitur dhe madje duke botuar. Unë po ju them këtë sepse hasem në të njëjtat vështirësi. Përdorni këtë libër në rrezikun tuaj, punoni me komunitetin tuaj dhe komunitetet në dispozicion për ju për të ndërtuar softuer brenda një ambienti të sigurt dhe mos i merrni gjërat personalisht kur dështoni ose madje keni sukses në një mënyrë të gabuar: Kështu e kam marrë këtë larg , dhe pse unë mund t'ju sjell këtë tekst dhe t'ju ndihmoj të keni sukses pa u zhvendosur në një shteg çmendurie që largohetUnë e shkatërrova, copëtuar dhe skuqur ndërsa unë hasem me problemet e zakonshme që të gjithë bëjnë në një shkallë globale falë shkallës paralele globale të rrjetit në të cilin do të punojmë, Interneti. Ju mund të mos jeni shumë të njohur me atë që unë jam me vetëm disa fjalë, por ju inkurajoj të lexoni më tej, do të më njihni ndërsa vazhdoni të më lexoni dhe të më kuptoni ndërsa ndërtoni projektet tuaja për të përfunduar punën tuaj. Nuk do të ketë detyra shtëpie me këtë libër, për sa kohë që profesorët ose mësuesit tuaj nuk ju caktojnë ndonjë, por unë ju inkurajoj shumë që të ndërtoni një portofol të projekteve vetë ndërsa lexoni së bashku, si dhe një projekt gur themeli që tregon se si mundeni Aplikoni atë që keni mësuar. Projekti im Capstone është baza për shumicën e asaj që do të lexoni në këtë libër, pasi përfshin kodin nga projektet e mia të mëparshme, kodin që kam krijuar dhe mësuar të shkruaj metodikisht me dorë, dhe një gamë të gjerë idesh dhe këshillash që më kanë ndihmuar të ke...
Mësimi i thellë praktik i bazuar në ueb dhe siguria me shembull

Mësim dhe siguri e thellë praktike e bazuar në internet me shembull Botim i tretë Charlotte Harper 3 korrik 2024 Parathënie: Konsideratat e sigurisë në ndërtimin e softuerit për Ueb janë një pjesë e rëndësishme e planit dhe ekzekutimit të çdo zhvilluesi të internetit ndërsa inxhinieroni një prototip që është i besueshëm, i qëndrueshëm dhe i dobishëm për qëllime praktike. DOM (shënimi i objektit të dokumentit), me zbatimin e tij të HTML, JavaScript, dhe CSS, si dhe softuer backend që zbatojnë Python, C/C ++, Java dhe Bash, u japin zhvilluesve të uebit lirinë dhe fuqinë për të krijuar një larmi të gjerë projektesh që shprehin krijimtaria, siguroni lehtësi të përdorimit dhe funksionalitetit, portretizoni përulësinë dhe karakter Vrasni kohën ose bëni diçka të bërë në internet, zakonisht në një pajisje smartphone me ekran me prekje. Shumica e njerëzve as nuk do të dinin se ku të fillojnë kur duan të ndërtojnë një faqe në internet ngaScratch, ata do të priren të fillojnë në faqen e internetit të një personi tjetër dhe të ndërtojnë diçka të kufizuar në funksionalitet, besueshmëri, lehtësi përdorimi dhe veçanërisht krijimtarinë kur ata mund të kishin të gjitha mjetet më të fundit të fuqishme në dispozicion të tyre në mënyrë që të ndërtojnë diçka të dobishme pa humbur butona të shtypjes së kohës , dhe veçanërisht duke humbur para duke paguar abonimet e shtrenjta për softuer pak njerëz donin të përdorin gjithsesi duke pasur parasysh kufizimet e tij në lehtësinë e përdorimit dhe fleksibilitetit. Nëse keni disa minuta për të lexuar përmes këtij libri dhe të mësoni se çfarë dua t'ju mësoj, ose edhe të flisni me mua personalisht për qëllimet tuaja dhe të merrni disa udhëzime në drejtimin e duhur, dhe janë të motivuar të mësojnë të kodojnë dhe të shkruajnë softuerin tuaj , Merrni këtë libër në shtëpi dhe lini mënjanë ca kohë për të mësuar të ndërtoni aplikacionin tjetër me ndikim, të fuqishëm, të efektshëm dhe të rëndësishëm në internet, një faqe në internet që është gjithçka për ju dhe bën pikërisht atë që dëshironi dhe plotëson nevojat e audiencës tuaj. Për mua: Unë jam një zhvillues i softuerit meGama e përvojës në C/C ++, Java, Python, HTML, CSS dhe JavaScript. Unë ndërtoj faqet e internetit që njerëzit duan të përdorin, duan të vizitojnë, dhe madje të jem i varur nga përdorimi i vetëm për të mësuar, rikrijuar dhe vrarë kohën, dhe më e rëndësishmja, unë shes softuer. Nëse keni pasur një ide se si keni dashur që një faqe në internet të shikonte dhe të funksiononte, ju ishit të gatshëm të më mbështesnit, në mënyrë që të mund të përmbushja nevojat e mia ndërsa unë takoj tuajin, dhe ju jeni të gatshëm të mbuloni kostot e drejtimit të një faqe në internet vetë, Unë do t'ju ndërtoja YouTube, tiktok, Twitter, Google, apo edhe një aplikacion sigurie të teknologjisë së lartë vetëm që mund të përdorni. Në vend që të përpiqem t'ju shes kohën time, unë jam duke u përpjekur të blej tuajin: Unë dua t'ju flas për të ndërtuar një aplikacion (uebfaqe) vetë me informacionin që ekziston tashmë, dhe t'ju mësoj atë që ju nevojitet për të qenë një zhvillues i pavarur i softuerit, Sipërmarrësi, duke udhëhequr një karrierë të suksesshme në çfarëdo fushe që dëshironi. Dhe më lejoni të jem i qartë, arsimi që ju jap do të jetë joformal. Ju mund të shkoni në shkollë dhe të mësoni të gjitha këto me njëEdukimi zyrtar, apo edhe lexoni këtë libër në shkollë, plotësoni detyrat tuaja dhe hiqni shumë nga edukimi juaj, por unë nuk do t'ju vë zyrtarisht në vendin e nxehtë dhe t'ju kërkoj të plotësoni detyrat. Unë nuk jam profesori juaj, ju mund të mendoni për mua si një mik i cili dëshiron t'ju udhëzojë drejt një karriere të drejtuar nga suksesi juaj personal. Dhe unë nuk jam duke ju shitur as sukses, do t'ju duhet ta blini me kohën tuaj. Mësimi për të koduar ka një kurbë të pjerrët të të mësuarit dhe nuk ishte kurrë e lehtë, apo edhe supozohej të ishte. Ju duhet të punoni sa më shumë që të keni mundësi dhe të vazhdoni të provoni dhe të dështoni dhe të provoni përsëri edhe kur jeni të irrituar në mënyrë që të mësoni dhe ndërtoni vetë aplikacione. Kjo është në natyrën e vetë kodit. Kodi drejtohet nga një përpilues që është krijuar për t'i dhënë mesazheve të gabimit të programuesit, dhe këto do t'ju mësojnë se si të kodoni, edhe nëse thjesht po kopjoni gabimin në motorin tuaj të kërkimit dhe duke lexuar shembujt e njerëzve të tjerë. Dhe unë duhet të them, ju nuk keni nevojë të jeni jashtëzakonisht të pasur, të zgjuar,E rreptë, apo edhe e orientuar në detaje ose e organizuar për të ndërtuar një aplikacion. Kompjuteri kujdeset për atë organizatë për ju. Thjesht duhet të vazhdoni përmes provës dhe gabimit, të mbani fokusin dhe të punoni shumë në atë që bëni, dhe do të keni një karrierë shumë të suksesshme në tërësinë e asaj që bëni. Kush jam: Unë e kuptoj që pjesa e fundit kishte të bënte më shumë me të mësuarit dhe të marrësh një rrugë nga ky libër. Kush jam unë saktësisht? Kjo është një pyetje e ndërlikuar. Unë jam i paqartë për këtë vetë, pasi vuaj nga kushtet mjekësore që mund ta bëjnë të vështirë për mua madje të kodoj ose të shkruaj këtë libër herë pas here, ndërsa paraqes sfida me shoqërizimin dhe çështjet e identitetit që e bëjnë jetën time më të vështirë kur bëhet fjalë për prezantimin e vetvetes . Me pak fjalë, nëse po e lexoni këtë libër, ju e sollët në shtëpi sepse e keni përshkuar atë dhe keni menduar se ishte e dobishme, ose edhe nëse thjesht lexoni këtë larg, për ju unë jam një individ me mendje që dëshiron të shohë që të keni sukses gjithçka që bëni ju. Unë jam një inxhinier vetë,Zhvilluesi, dhe një student, dhe unë po shkruaj këtë libër për studentët e tjerë që duan ta bëjnë jetën e tyre më të lehtë duke pasur një manual të softverit për të cilin u duhen më lehtë jetën e tyre duke dhënë shembuj për të kopjuar që përshtaten së bashku si një enigmë e madhe në një punë , i dobishëm, i madh, funksional, koheziv dhe aplikacioni tërheqës që mund të nxisë suksesin pa marrë parasysh linjën e biznesit. Kryesisht, kjo është ajo që unë bëj: Unë ndërtoj aplikacione për të ndihmuar veten dhe njerëzit e tjerë të kenë sukses. Unë jam gjithashtu një autor, megjithëse ky është botimi im i parë që kam ndërmend të përfundoj në mënyrë që ta vendos portofolin tim së bashku në një dokument të dobishëm, dhe unë jam një artist gjithashtu. Unë do ta pranoj këtë për ju, unë jam një lloj personi i çuditshëm. Unë nuk jam perfekt, unë kam drejtuar ins me ligjin madje duke më çuar të largohem nga kolegjet dhe universitetet dhe të largohem nga shtetet në mënyrë që të përpiqem të bëj një emër për veten time me më shumë sukses. Unë jam një grua nga lindja, vesh grim, bëj fotografi nga vetja, vesh fustane dhe veshje të tjera të grave, dhe qëndroj i vetëdijshëm për veten time si njëfemër nga natyra. Unë kam pasur probleme me njerëz të tjerë në të kaluarën që çojnë në luftë me shkrimin dhe ndërtimin e uebfaqeve, dhe kërkoj falje që nuk kam qenë në gjendje ta marr këtë libër në duart tuaja më shpejt: ju duhej kjo. Ju do të dëshironi të lexoni dhe të shkruani kod që duket si i imi dhe funksionon si i imi dhe bën të njëjtën gjë, por edhe më mirë, sepse nëse mund të përballoni të blini këtë libër në vend që të krijoni tastierën tuaj si unë vetëm për të krijuar një libër vetë duke kërkuar para Për të, ju keni burimet që ju nevojiten për të qenë të suksesshëm në jetën tuaj. Unë kisha të gjitha llojet e çështjeve me rritjen e familjes, kushtet shëndetësore, mjekët, mediat dhe ligjin, dhe kodi im pasqyron thellësisht luftën që është feminizmi dhe natyra femërore në një botë të ndarë dhe të irrituar. Sidoqoftë, ky libër është diçka për të cilën më intereson thellësisht, fëmija im, portofoli im dhe jetesa ime, kështu që unë vlerësoj konsideratën tuaj kur ju merrni tekstin në shtëpi dhe me kujdes pore mbi të në mënyrë që të mësoni nga unë. Ju lutem mbani në mend se nuk jamECT, ky libër do të ketë gabime, rishikime dhe botime të reja, dhe do t'ju duhet të mendoni me trurin tuaj logjik sa më mirë që të keni mundësi në mënyrë që të keni një përvojë të suksesshme me shkrimin tim. Gjithashtu, kuptoni që dua të them mirë për ju edhe kur përballeni me sfida kur shkruani. Mendoni për këtë si kjo: Kur thjesht mund të merrni me qira një sistem kompjuterik për të bërë gjithçka që mund të imagjinoni në hapësirën dixhitale, të ruani të gjitha informacionet që hasni, #$%! YZE dhe ta organizoni, dhe të kuptoni, ju do Në mënyrë të pashmangshme hasni vështirësi me informacionin që ju jeni duke gëlltitur dhe madje duke botuar. Unë po ju them këtë sepse hasem në të njëjtat vështirësi. Përdorni këtë libër në rrezikun tuaj, punoni me komunitetin tuaj dhe komunitetet në dispozicion për ju për të ndërtuar softuer brenda një ambienti të sigurt dhe mos i merrni gjërat personalisht kur dështoni ose madje keni sukses në një mënyrë të gabuar: Kështu e kam marrë këtë larg , dhe pse unë mund t'ju sjell këtë tekst dhe t'ju ndihmoj të keni sukses pa u zhvendosur në një shteg çmendurieAves me shkatërruar, shqyer dhe të copëtuar ndërsa unë hasem me problemet e zakonshme që të gjithë bëjnë në një shkallë globale falë shkallës globale paraleliste të rrjetit në të cilin do të punojmë, Interneti. Ju mund të mos jeni shumë të njohur me atë që unë jam me vetëm disa fjalë, por ju inkurajoj të lexoni më tej, do të më njihni ndërsa vazhdoni të më lexoni dhe të më kuptoni ndërsa ndërtoni projektet tuaja për të përfunduar punën tuaj. Nuk do të ketë detyra shtëpie me këtë libër, për sa kohë që profesorët ose mësuesit tuaj nuk ju caktojnë ndonjë, por unë ju inkurajoj shumë që të ndërtoni një portofol të projekteve vetë ndërsa lexoni së bashku, si dhe një projekt gur themeli që tregon se si mundeni Aplikoni atë që keni mësuar. Projekti im Capstone është baza për shumicën e asaj që do të lexoni në këtë libër, pasi përfshin kodin nga projektet e mia të mëparshme, kodin që kam krijuar dhe mësuar të shkruaj metodikisht me dorë, dhe një gamë të gjerë idesh dhe këshillash që më kanë ndihmuar të ketë sukses në pikën ku unë mund të rrotulloj një aplikacion të thjeshtë qëE paraqitur plotësisht dhe duket dhe sillet si një aplikacion popullor që mund ta shihni mikun ose familjen tuaj duke përdorur, në internet, të reklamuar për ju, ose në lajme. Çfarë është ky libër: Ky libër është një tutorial me shembull. Ju mund të gjeni kodin këtu, udhëzime se si të mësoni të kodoni, informacionin mbi kodin e korrigjimit dhe rregullimin e gabimeve, hapat e zgjidhjes së problemeve, udhëzimet se si të bëni kopje rezervë dhe të ruani kodin tuaj, të ri-vendosni nëse dikush prish kodin tuaj, siguroni kodin tuaj, vendosni Kodi juaj, ndërtoni faqet e internetit interaktive që janë argëtuese, angazhuese dhe Addictive, dhe ju do të merrni një kuptim se kush jam, pse kjo është e rëndësishme, dhe si ta portretizoni veten, aplikacionin tuaj dhe imazhin e kompanisë, si dhe softuerin Ju ndërtoni në dritën më të mirë absolute për të qenë më tërheqës që të jetë e mundur për përdoruesit tuaj fundorë, vizitorët e faqes suaj të internetit. Në këtë libër, unë do të demonstroj një numër shembujsh të hartimit të softuerit me fokus në internet si një platformë, si dhe siguri. Ne do të fillojmë përvojën e të mësuarit duke ndërtuar një themeloreOject duke përdorur guaskën UNIX, me karakteristika rezervë dhe skriptimi. Pastaj, ne do të shqyrtojmë një uebfaqe themelore të blogut, do të azhurnojmë blogun tonë me veçoritë e fotografive dhe videove, si dhe t'i përdorim këto karakteristika për të përdorur zgjidhje të sigurisë duke përdorur softuer falas, dhe të sigurojmë serverin tonë duke përdorur një modul të vërtetimit të prizave (PAM). Ne pastaj do të rishikojmë trajtimin dhe përpunimin e skedarëve, duke eksploruar redaktimin e videove, dhurimin e zërit, skanimin e barkodit dhe njohjen e karakterit optik, midis koncepteve të tjera. Gjatë rrugës ne do të shqyrtojmë API -të të cilat do të na ndihmojnë ta bëjmë softuerin tonë më të dobishëm dhe të sigurt, me mundësi falas dhe të paguara. Gjatë rrugës, ne do të eksplorojmë mjetet e sigurisë fizike dhe mjetet militante siç janë armët e zjarrit dhe prodhimi dhe prodhimi i municioneve, përfshirë dizajnin e fuçisë dhe përsëritësit, modelimin e frëngjisë dhe dronit, dhe drejtorët e tjerë, ne do të integrojmë me softuerin tonë në rrjetin ekzistues për të mbrojtur softuerin tonë tonë dhe të demonstrojnë vetëmbrojtje dhe banimi. Ne do të bëjmë pushime gjatë rrugës për të ndërtuar lojëra, 2D dhe 3DPërfundimi i motorëve, dhe punoni me harduer të ngulitur në rast studimi shembuj të softuerit themelor të dhënies dimensionale dhe një masazhues elektronik vibrues të hedhur përkatësisht në gome silikoni. Gjatë rrugës, ne gjithashtu do të përdorim zgjidhje të mësimit të makinerive tashmë të disponueshme në mënyrë që të sigurojmë më mirë softuerin tonë. Ne gjithashtu do të përdorim mjete të aksioneve të disponueshme për uebin në mënyrë që të thjeshtojmë dhe sigurojmë procesin. Ky libër është një udhëzues për suksesin tuaj në ndërtimin e një aplikacioni në internet dhe integrimin e tij me një rrjet profesional të kompjuterit dhe sistemeve mekanike të ngulitura, dhe në përgjithësi një udhëzues për ndërtimin e softuerit dhe pajisjeve të ngulitura pa njohuri në sfond ose përvojë të mëparshme. Çfarë nuk është ky libër: Nëse me të vërtetë dëshironi të keni një faqe në internet, thjesht mund të krijoni një dyqan të thjeshtë dhe të shisni atë që ju nevojitet, të postoni një blog, të postoni foto ose video, ose ndryshe pa shkruar kurrë një linjë të vetme kodesh. Ky libër nuk është ai. Ky libër do t'ju mësojë se si të ndërtoni softuer që është më i dobishëm, plotësishti veçuar, funksional dhe i sigurt se çdo softuer që mund të gjesh tashmë, sepse vendos softuerin e fundit që është akoma prototipe, mund të jetë i shtrenjtë për të kandiduar në një shkallë të kompanive të moshuara që operojnë në, dhe nuk i bën thirrje prapa, kompanive të ndërlikuara të ngritura Bëni para për njerëzit që nuk po bëjnë vërtet asgjë. Nëse e ndiqni këtë libër nga afër, do të dëshironi të shkruani kod, kodin hulumtues, të ndërtoni aplikacionet tuaja dhe do të fitoni para nga ato që bëni. Unë do të fitoj para nga ky libër, edhe në fazat e hershme, sepse përmban informacione që njerëzit kanë nevojë dhe duan të lexojnë, dhe tashmë po blejnë kur blejnë ose përdorin aplikacionet e mia. Ky libër nuk do të ndërtojë një aplikacion për ju, por do t'ju drejtojë në drejtimin e duhur dhe do t'ju mbajë me mjetet që ju nevojiten dhe aftësitë dhe këshillat që do të lehtësojnë suksesin tuaj në ndërtimin e softuerit për në internet, me çdo rresht të Kodi që do t'ju duhet të shkruani si një shembull, të gatshëm për t'u bashkuar në softuer ju dhe mbështetësit tuaj, mysafirë, klientelë,Rends, familja, vizitorët, kontraktorët dhe njerëzit e Internetit duan të përdorin dhe mbështesin. Çfarë do të mësoni: Ky libër do t'ju mësojë se si të ndërtoni dhe shisni softuer, me të vërtetë funksionale, softuer të dobishëm, regjistrimin e mediave, karakteristika të sigurisë si njohja e fytyrës, skanimi i barkodit të zonës së lexueshme të makinerisë, API -të në internet për të vërtetuar, regjistruar dhe dhënë video dhe foto, dhe shkëmbimi i mesazheve si Bluetooth dhe Komunikimi afër fushës (NFC). Ky libër do t'ju mësojë se si të përdorni një kompjuter në rrjet, duke u përqëndruar në Debian Linux, si të ndërtoni kodin bash për të bërë instalimin dhe kopjimin e softuerit tuaj një fllad të qetë, të automatizuar, si të ndërtoni kodin Python si një backend për të shërbyer mesazhe dinamike, stil Gjërat bukur duke përdorur stilet CSS me bootstrap, aktivizoni hyrjet e përdoruesve dhe ndërveprimin përmes pajisjeve të rrjetit, ndërtoni media interaktive dhe rrjet me uebfaqe të tjera për të ofruar veçori të sigurisë si mesazhe me tekst për verifikim ose tjetër Qëllimet, skanimi i ID -së, Moderimi i Imazhit dhe Video, të dhënaRansactions për të mbajtur softuerin tuaj të sigurt, përpunimin e pagesave, tregtimin e cryptocurrency, detyra asinkron dhe më shumë. Do të mësoni se si të ndërtoni pajisjet tuaja Bluetooth, me bateri, karikues, mikrokontrollues, qarqe, motorë dhe sensorë, duke përdorur bashkuesin, telin dhe 3D të shtypura, si dhe materiale të hedhura. Unë do të demonstroj parimet e dizajnit 3D të aplikuar në prodhimin dhe mjetet shtesë dhe bërjen e vdes, kështu që ju jeni në gjendje të prodhoni pajisjet tuaja të ngulitura, harduerike me bateri të integruara, karikues, qarqe elektronike dhe rezultate funksionale. dhe rrjetoni ato me Bluetooth dhe në internet. Në mënyrë të veçantë, ne do të shqyrtojmë dy studime të rasteve, një masazhues vibrues dhe një armë zjarri të bërë në shtëpi, të dy të programuar në OpenSCAD, i cili është i disponueshëm si një ndërfaqe grafike ose mjeti i linjës së komandës dhe mund të integrohet në një ueb për rezultate më të shpejta. Ju do të mësoni se si të ndërtoni dhe vendosni një faqe në internet nga toka pa përvojë paraprake, ta bëni atë funksional, të sigurt, të bukur, të dobishëm dhe më së shumtiMortshmërisht praktike. Ju do të mësoni se si të përdorni mësimin e makinerisë dhe vizionin e kompjuterit për ta bërë një faqe të sigurt dhe më praktike, të regjistroni video dhe audio nga faqja juaj e internetit, të dhuroni zërin tuaj, të bëni muzikë dhe të moduloni audio për të krijuar mostra të dobishme dhe si të shkelni zhurmën nga zhurma nga Duke përdorur faqet e internetit të tjera për të ndërtuar rrjetin më të mirë të mundshëm të faqeve të internetit që mund të lidheni direkt me tuajat në mënyrë që të ndani të gjitha informacionet e dobishme që duhet të ofroni, dhe madje edhe më e rëndësishmja t'i sillni njerëzit në softuerin dhe biznesin tuaj. Ky libër do të përqendrohet më së shumti në media, sigurinë dhe mësimin e makinerive, të cilat janë tre komponentët kryesorë që do t'ju ndihmojnë të ndërtoni softuer të dobishëm për Ueb duke angazhuar përdoruesit e duhur dhe duke shkëputur ato të gabuara në një mënyrë që është realiste, praktike, Duart dhe angazhimi ndërsa gjithashtu automatik, dhe i guximshëm. Ky libër mëson UNIX, konkretisht Debian (Ubuntu), Bash Shell, Python, HTML, CSS, JavaScript, dhe një numër paketash të dobishme softuerësh përn Likojnë kërkesa, si dhe softuer të dobishëm Bash si Git dhe FFMPEG. Unë gjithashtu do t'ju mësoj se si të tregtoni automatikisht cryptocurrency, dhe të merrni pagesa në cryptocurrency ose nga kartat e rregullta të debitit, ndërsa madje paguani vizitorët tuaj një pjesë të të ardhurave tuaja nëse vendosni ta bëni këtë. Unë do t'ju mësoj se si të fitoni para nga faqja juaj e internetit edhe përmes reklamave, si të përgatisni aplikacionin tuaj për motorët e kërkimit dhe ta bëni atë të shpejtë, të renditur në renditjen e parë për atë që klientët tuaj do të kërkojnë për t'ju gjetur, dhe duke u renditur në sa më shumë të zakonshëm kërkime sa të jetë e mundur. Unë do t'ju mësoj se si ta shisni softuerin tuaj, ta reklamoni atë, t'i tërheq klientët që kërkojnë shërbimet tuaja dhe të bëni një emër për veten tuaj në internet përmes rrugëve që ekzistojnë tashmë, janë të lira dhe të punojnë mirë. Unë do t'ju mësoj se si të ruani të dhënat tuaja në kompjuterët cloud që punojnë për ju dhe të ruani të dhënat tuaja me çmim të lirë, si të planifikoni dhe të ndërtoni një faqe në internet që bën atë që dëshirojnë përdoruesit tuaj dhe atë që dëshironi, dhe si t'i mbani përdoruesit tuaj të angazhuar ngaduke përfshirë faqen tuaj një trokitje e lehtë në telefonat e tyre me njoftime, email, mesazhe me tekst, thirrje telefonike dhe më shumë rrugë për t'i rikthyer përdoruesit tuaj në faqen tuaj të internetit në dispozicionin tuaj pas klikimit të një butoni të siguruar vetëm për ju. Ky libër do të përqendrohet në prakticitetin e botimit dhe shpërndarjes së mediave në sasi të mëdha, nga teksti në foto në video deri tek audio, duke bërë një përshtypje të mirë për përdoruesit fundorë (klientelën tuaj), dhe duke shitur veten në çfarëdo mënyre që bëni në mënyrë që të krijoni Një faqe në internet, një aplikacion që është përfaqësues i jush dhe ju vetëm, dhe ju bën, softveri juaj dhe kompania juaj duken mirë në mënyrën më të mirë të mundshme. Ju gjithashtu do të mësoni disa këshilla dhe truket nga unë, nga këshilla për kodim, kotësi praktike si përbërja dhe fotografia, modelimi dhe aktrimi, dhe më shumë, të cilat do të jenë të rëndësishme për të portretizuar veten dhe kompaninë tuaj në dritën më të mirë të mundshme duke përdorur të gjitha mjetet në dispozicion për ju ndërsa shpërndani sa më shumë përmbajtje sa ju nevojitet në një ekuilibër të shëndetshëm të platformave për të sjellë tuajine të realizohet pa më përpjekje, punë ose para sesa është e nevojshme. Ky libër quhet "mësim dhe siguri e thellë praktike e bazuar në internet me shembull" për një arsye: ai merret me mësimin të kodojë, posaçërisht për në internet, posaçërisht me fokus në sigurinë, nga një këndvështrim praktik, me shembuj të kodit të punës që shërben qëllimet praktike të përshkruara në tekst. Komponenti i të mësuarit i këtij teksti përfshin gjithashtu mësimin e makinerisë, kodin që unë do t'ju tregoj se si të ekzekutoni në internet që do të trajtojë vizionin e kompjuterit, njohjen e fytyrës, modifikimin e imazhit dhe videos, përmirësimin e figurës, përmirësimin e rezolucionit, captioning imazhi dhe detyra të tjera si si Metrikat e parashikimit të buruara nga imazhet, të tilla si natyra e figurës si një imazh autentik, i transferuar nga kompjuteri, ose një kopje optike (një foto e një imazhi, ose foto e shtypur). Mësimi i makinerisë është shumë i rëndësishëm kur bëhet fjalë për sigurinë në internet dhe sigurinë e softuerit, sepse mund të preformojë detyrat që ishin ndryshe të pamundura. Kompjuteri juajRegjistrohuni me një kodkalim, por mund të jetë më e sigurt ta përdorni nëse ju fut me fytyrën tuaj. Ju mund ta bëni një kompjuter server këtë të sigurt, një kompjuter që normalisht do t'ju kërkonte një emër përdoruesi dhe kodkalimi dhe të regjistroheni, mbase me një shenjë konfirmimi për çdo hyrje të re ose adresë të re IP, por nëse po ndërtoni në shkallë të gjerë, të lehtë Përdorni, softuer thelbësisht të sigurt dhe të fuqishëm, kjo mund të jetë e mjaftueshme. Lidhja e softuerit tuaj shumë ngushtë me programin e dikujt tjetër, si një shërbim me email ose shërbim me mesazhe me tekst, nuk është e mjaftueshme për ta bërë softuerin tuaj të sigurt, ose të kujtdo (çdo sit që përdorni). Kushdo që ndërton softuer që është i sigurt në mënyrë të përsosur ka një kuptim të asaj që nënkupton kjo. Softueri është në thelb i pasigurt sepse pajisjet dhe llogaritë që ne i përdorim për të hyrë në atë nuk janë gjithmonë në dispozicionin tonë, ato mund të jenë në duart e kujtdo që ka qëllim të keq për softuerin dhe për këtë arsye mund të paraqesë rrezik për vetë softuerin. Ky është diçka në fokusin e këtij libri. Një kompjuter i rrjetuar është si parazgjedhurSiguruar me një shenjë të gjatë të çelësit, të thirrur dhe SSH ose Secure Shell Key, dhe përndryshe sigurohet më së miri me një server në internet, sepse serveri në internet siguron qasjen e hapur, si dhe gjendjen e mjeteve të sigurisë së artit që funksionojnë në vetë serverin. Serveri në internet ka qasje në shfletuesin në internet të përdoruesit, i cili është ndoshta pjesa më e fuqishme e pajisjes së përdoruesit, sepse është vendi ku përdoruesi mund të hyjë në softuer në rrjet. Kjo mjete e mjeteve mund të japë tekst, faqet e internetit që shihni, dhe gjithashtu mund të regjistrojë imazhe, audio dhe video (si një foto e një fytyre ose një ID të shtetit), mund të lexojë dhe të shkruajë në pajisjet e radios Bluetooth, dhe mund të lexojë dhe të shkruajë në afërsi të fushës. Etiketat e transponderit, kartat e lira të çelësave, fobs, afishe, unaza dhe madje edhe implantet e çipave me numra serialë unikë që mund të lexohen dhe shkruhen me të dhënat e krijuara dhe të vërtetuara nga një server në internet i lidhur me faqen në internet. Duke përdorur të gjitha mjetet në dispozicionin tuaj, me këtë libër do të pajisni veten me njohuri për të ndërtuar një uebfaqe të sigurt, dhe në përgjithësi aSistemi kompjuterik me rrjet i rrjetuar që funksionon për ju, bën ofertat tuaja, dhe duket dhe ndjehet mirë. Ku te filloj: Ju jeni të mirëpritur të kaloni në pjesën me të cilën filloj këtë libër, ose ndonjë seksion, në kodin e saktë që ju nevojitet, veçanërisht nëse keni përvojë me kodimin para ose ndonjë prej mjeteve të lartpërmendura që do të përshkruaj në detaje në këtë libër si si dhe dokumentimin e rasteve të përdorimit dhe shembuj praktikë të tyre. Nëse nuk keni përvojë në kodin e të shkruarit, ju rekomandoj shumë të lexoni të gjithë këtë libër, dhe veçanërisht ju rekomandoni të lexoni pjesët e mëparshme, për t'u siguruar që ky libër është i duhuri për ju. Nëse ky libër nuk është i duhuri për ju, konsideroni t'i dhuroni një shoku ose të afërmi që mund të jetë i interesuar të mësojë vetë në zhvillimin e uebit, dhe madje konsideroni të huazoni atë përsëri dhe të mësoni prej tyre për të mbushur boshllëqet ku unë ju dështova si një mësuesi, ose mësuesit e tjerë bënë para meje. Filloni atje ku dëshironi, çdo pjesë e këtij libri do të jetë e dobishme nëse keni ndërmend të ndërtoni një të dobishëmPP, dhe konsideroni se aplikacionet më të mira janë ndërtuar me përdoruesin përfundimtar në mendje: Njihni klientin tuaj. Tani më njihni mua, ju e dini këtë libër dhe jeni gati të filloni. Për të filluar, kapni një kompjuter (madje edhe laptopi më i lirë nga një dyqan kuti, Amazon, ose një desktop i vjetër funksionon, dhe vendoseni atë në një mënyrë që funksionon për ju. Si ta lexoni këtë libër: Teksti i theksuar, tregon se teksti i përket një komande të shpejtë, ku do të shkruani kodin që drejtoni. Shpejtësia e komandës është shumë e përqendruar në tastierë dhe kërkon pak ose pa klikim, duke shpejtuar rrjedhën tuaj të punës dhe duke i bërë gjërat më të lehta për ju. Fillimi: Le të zhyten. Ne do të fillojmë me ndërtimin e kodit në një makinë lokale dhe të fillojmë pa ndërtuar një faqe në internet të lidhur në internet. Kjo është më e sigurt për të filluar, nuk kushton asgjë dhe është e lehtë për ju. Në varësi të sistemit tuaj operativ, hyrja në një guaskë bash do të jetë pak më ndryshe. Për Mac OS, unë rekomandoj të instaloni një makinë virtuale në këtë pikë, pasi do të merrni më shumë pajtueshmërinë me tëMakinë virtuale. Ofrues të ndryshëm si Virtualbox dhe Paralells mund të drejtojnë një makinë virtuale për ju, megjithëse është gjithashtu e mundur të instaloni Ubuntu direkt në makinë, nëse preferoni të përdorni një mjedis vendas i cili rekomandohet në mënyrë që të krijoni një përvojë të shpejtë, të efektshme. Nëse jeni duke përdorur Linux ose Windows, të cilat unë rekomandoj, duhet të jetë mjaft e lehtë për të krijuar një projekt. Hapni terminalin tuaj, rregulloni madhësinë siç e shihni të arsyeshme dhe filloni të ndiqni hapin 2. Nëse jeni duke përdorur Windows, ju lutemi ndiqni hapin 1. Hapi 1: - Vetëm përdoruesit e Windows Në Windows, hapni komandën e shpejtë si administrator dhe lloj WSL - Instaloni Hapi 2: - Vazhdoni këtu, ose kaloni Hapi 1 këtu nëse nuk po përdorni Windows Në një terminal të hapur, (në varësi të sistemit tuaj, të quajtur Ubuntu në Windows, terminal në Mac ose Linux, ose një emër të ngjashëm), filloni duke krijuar një projekt. Ne e bëjmë këtë me komandën mkdir, e cila krijon një direktori. Nëse keni nevojë të krijoni një drejtori për të ruajtur projektin tuaj, i cili rekomandohet, përdornikomanda cd për të ndryshuar në drejtori dhe dhe CD/PATH/TO/DREJTORIA - Rruga është dosjet (skedarët) që i paraprijnë drejtorinë tuaj të destinacionit, rruga juaj e paracaktuar është ~ ose/shtëpia/emri i përdoruesit (ku emri i përdoruesit është emri juaj i përdoruesit). Për të ndryshuar në drejtorinë e paracaktuar, shkruani CD ose CD Shembull Mkdir - Zëvendësoni "Shembullin" me emrin e Drejtorisë Tani ju keni një direktori pune për projektin tuaj. Duke qenë pasi është kaq e rëndësishme që kjo direktori të ruhet në rast se ju duhet të kaloni në një makinë të ndryshme ose të vendosni kodin që shkruani, në mënyrë që të jetë gati për në internet, ne do të ndërtojmë një skenar për të mbështetur drejtorinë tuaj në hapat e ardhshëm. Por ndërtimi i një skenari kërkon pak kod, dhe kodi duhet të automatizohet për të qenë sa më i dobishëm. Pra, le të ndërtojmë një skenar për të ndërtuar së pari skriptet. Le të fillojmë duke krijuar skenarin dhe duke e bërë atë të ekzekutueshëm. Ne do të përdorim sudo, chmod dhe prekje për këtë, dhe do ta quajmë skenarin


sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
Tani ne kemi krijuar skenarin, e kemi bërë të ekzekutueshëm dhe jemi të gatshëm ta redaktojmë atë. Nano është një redaktues teksti që do t'ju lejojë të redaktoni tekstin pa klikuar, i cili është shumë më i lehtë sesa të përdorni një ndërfaqe grafike të përdoruesit. Për të modifikuar një skedar me Nano, përdorni Nano dhe më pas rrugën për në skedar. Për të bërë një skenar që bën një skenar, është mjaft i ngjashëm me bërjen e skenarit tonë në radhë të parë. Ne do të përdorim të njëjtin kod si më lart, duke zëvendësuar emrin e skenarit, "accript" me një parametër argumenti, 1 $. Kjo na lejon të thërrasim skenarin duke shtypur thjesht sudo accript Newscript, në atë pikë ne mund të krijojmë çdo skenar të ri duke zëvendësuar "Newscript" me emrin e skenarit tuaj. Kodi në Nano duhet të duket si:

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
Dhe për të mbyllur Nano, ne mund të mbajmë poshtë butonin e kontrollit dhe të shtypim X, atëherë Y për të treguar se po e ruajmë skedarin dhe do të godasim kthimin. Tani në vend që të shtypim këto tre komanda për të modifikuar një skenar, ne do të jemi në gjendje të shkruajmë accript Sudo Accript për të modifikuar përsëri skenarin. Kjo funksionon! Dhe çdo skenar i ri mund të drejtohet lehtë duke e thirrur atë në guaskë. Le të ruajmë punën tonë tani: Le të shkruajmë një skenar rezervë për të ruajtur skenarin tonë të ri dhe pastaj ta kthejmë atë në drejtorinë tonë të projektit, duke mbështetur gjithashtu skenarin rezervë.

sudo ascript backup
Tani, në Nano:

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
Ku/shteg/drejt/drejtoria është rruga drejt projektit që keni krijuar me mkdir. Më vonë do të mësojmë se si të kopjojmë shtigjet e përsëritura si kjo me një lak dhe një listë, e cila është më pak kod, por tani për tani le ta mbajmë atë të thjeshtë dhe të kemi disa rreshta. Për të ekzekutuar këtë skenar dhe kopjuar kodin tuaj, ruani skedarin në Nano me kontroll+x, y dhe kthehuni, dhe shkruani më poshtë në guaskën tuaj

backup
Nëse ju kërkohet fare për një fjalëkalim ndërsa lexoni këtë libër dhe ndiqni së bashku në guaskë, ju lutemi shkruani saktë fjalëkalimin e përdoruesit tuaj, do të keni tre përpjekje para se të duhet të ri-drejtoni komandën. Ju mund të përdorni shigjetat lart dhe poshtë për të ribërë komandat dhe t'i modifikoni ato, nëse duhet të drejtoni ndonjë gjë dy herë. Shtypni të thjeshtë lart dhe poshtë me ndërprerje për të zgjedhur një komandë, përpara se të redaktoni komandën me të djathtën, shigjetat e majta dhe të fshini tastin, si dhe tastierën, dhe ta ekzekutoni atë me kthim. Urime! Ju keni arritur të krijoni një skenar të mrekullueshëm rezervë që mbështet dy skriptete të rëndësishme të guaskës në drejtorinë tuaj të punës. Ne mund të lëvizim gjërat më vonë pasi projekti bëhet më i madh, por kjo funksionon tani për tani. Le të vazhdojmë të mbështesim në re, ne do të përdorim GitHub për këtë (megjithëse ka shumë zgjidhje të tjera GIT për kopje rezervë, ato janë të gjitha për të njëjtën softuer ndërsa i bëni ato në një server, ndërsaGjithashtu duke ju mundësuar të shkarkoni kopje të tëra të softverit tuaj pas një fjalëkalimi ose çelësi. Është e dobishme për të kursyer softuerin tuaj, veçanërisht kur ne migrojmë në instancat e siguruara Linux që ndonjëherë prishen kur një linjë e vetme e kodit dështon, duke ju lënë të kyçur ndërsa kodi juaj mund të mos jetë i mbështetur nëse nuk merrni një shans për ta mbështetur atë lart automatikisht, të cilin do t'i mbulojmë. Nëse nuk jeni duke përdorur tashmë një makinë virtuale Ubuntu në këtë pikë, unë rekomandoj duke përdorur një makinë virtuale Ubuntu në këtë pikë sepse kjo do ta bëjë jetën tuaj më të lehtë kur instaloni të gjitha paketat e nevojshme në mënyrë që të ndërtoni një uebfaqe pune dhe të paraformësoni mësimin e thellë Operacionet në kompjuterin tuaj. Ne do ta transferojmë kodin në një server në internet në të ardhmen e afërt, por ne duam të sigurohemi që ka të paktën disa shtresa të sigurisë pas serverit tonë në internet që janë rezistent ndaj phishing, dhe të përdorim një numër të paketave Linux për të bërë kjo Nëse ende doni të përdorni Mac OS, ju jeni të mirëpritur të kërkoni dhe instaloniPaketat e nevojshme në internet, por mund të mos ketë alternativa për çdo paketë që do të mbulojë ky libër ose seri. Le të shtojmë disa komanda për të kryer punën tonë me skenarin rezervë duke ekzekutuar komandën sudo accript

# …
git add –all
git commit -m “backup”
git push -u origin master
Edhe një herë, kontrolloni x për të kursyer. Tani duhet të bëjmë një konfigurim një herë për këtë projekt. Për shkak se së shpejti do të jetë një projekt GIT, ne nuk kemi nevojë të shkruajmë çdo komandë sa herë që vendosemi nga një depo GIT, por do të marrim varjen e kësaj kur të shkruajmë skriptet tona të vendosjes. Për të filluar, le të sigurohemi që jemi në drejtorinë e duhur dhe inicializojmë depo git dhe gjenerojmë çelësa SSH.

cd /path/to/directory
git init
git branch -m master
ssh-keygen
Pasi të shkruajmë SSH-Keygen, çelësi i ri duhet të ruhet në dosjen Home nën një dosje të quajtur .ssh. Quhet id_rsa.pub. Le ta gjejmë këtë çelës dhe ta kopjojmë. Për ta parë,

cd ~
cat .ssh/id_rsa.pub
Kopjoni tekstin që kthehet nga komanda e fundit dhe krijoni një llogari me ofruesin tuaj GIT (në mënyrë ideale GitHub), përpara se të shtoni çelësin SSH në llogarinë tuaj. Pasi të keni një llogari, klikoni në menunë e sipërme të djathtë dhe shkruani cilësimet, përpara se të shtoni tastin tuaj SSH në çelësat SSH dhe GPG nën qasje në menunë. Zgjidhni Shto një çelës SSH dhe shtoni tuajin duke e ngjitur atë dhe duke i dhënë asaj një titull, përpara se të kurseni dhe të ktheheni në GitHub për të krijuar një depo të re. Kjo është e ngjashme për ofruesit e tjerë të GIT, do t'ju duhet të lexoni dokumentacionin e tyre. Në konfigurimin e ri të depove, jepni depo tuaj një emër përshkrues dhe vendosni nëse doni ta publikoni, dhe sigurohuni që të mos konfiguroni ende skedarë për përfshirje. Pasi të krijohet depoja, kopjoni klonin me URL SSH dhe ngjitni atë në komandën e mëposhtme.

git remote add git://… (your remote URL)
Tani mund të zhvendoseni përsëri në depo tuaj me CD, do të jeni të njohur me këtë. Provoni skenarin tuaj rezervë tani me kopje rezervë E mrekullueshme! Tani ne me të vërtetë mund të marrim kodim. Le të instalojmë Django tani që kemi një kuptim të mirë në Bash dhe Git. Django do të na lejojë automatikisht të kopjojmë softuerin tonë, Bash mund ta bëjë këtë gjithashtu, por Django duhet të ketë një zbatim më të thjeshtë më të sigurt (ai mund të çaktivizohet dhe konfigurohet më lehtë). Për të instaluar softuer në Ubuntu, ne do të përdorim komandën sudo apt-get. Së pari, le të azhurnojmë dhe azhurnojmë softuerin që kemi pasur tashmë. Kjo mund të bëhet me azhurnim sudo apt-get dhe azhurnim sudo apt-get -y. Tjetra, le të instalojmë Python dhe mjedisin tonë virtual, shtëpia e kodit tonë, me komandën e mëposhtme: sudo apt-get instaloni python-is-python3 python3-venv Kjo është gjithçka që ju nevojitet për të shkuar me Django për sa i përket instalimeve të softuerit në shembullin Ubuntu. Për Windows dhe Linux kjo duhet të jetë mjaft e drejtpërdrejtë, por për Mac mund të dëshironi të instaloni një makinë virtuale dheLinux mbi të duke përdorur një mjedis virtual falas ose të paguar si VirtualBox ose Paralells Desktop dhe rikrijoni hapat e mësipërm në mënyrë që të vendosni një mjedis Ubuntu. Ubuntu është kritik në këtë rast sepse është softveri që faqet e internetit funksionojnë dhe u mundëson atyre të presin faqet e internetit me të gjithë softuerin e lartpërmendur. Le të gërmojmë në Django. Në drejtorinë tonë përsëri, me

python -m venv venv # Krijon mjedisin virtual ku ruhet kodi
source venv/bin/activate # Aktivizon mjedisin virtual
pip install Django
django-admin startproject mysite . # Aty ku Mysite është projekti që po filloj në drejtorinë time aktuale.
Django sapo po na fillon, sepse Django po pret serverin në internet dhe po bën gjithçka që na nevojitet për të marrë një uebfaqe themelore lokale dhe duke ekzekutuar. Tani që kemi instaluar Django, le të redaktojmë pak cilësimet për ta bërë atë të funksionojë se si na duhet. Së pari, le të krijojmë një aplikacion të ri

python manage.py startapp feed
Do të vini re që aplikacioni i parë quhet Feed. Aplikacioni duhet të quhet gjithçka që ju pëlqen, dhe ne do të krijojmë aplikacione të reja, por emri i secilës aplikacion duhet të jetë i qëndrueshëm sa herë që aplikacioni referohet në kod. Për të shtuar një aplikacion të ri, ne gjithmonë do të modifikojmë cilësimet.py në drejtorinë tjetër që aplikacioni i krijuar, i quajtur në StartProject, këtu e tutje. Duke përdorur nano,

nano app/settings.py
Në cilësimet, gjeni të instaluar_apps dhe ndajeni [] në 3 rreshta. Duke përdorur katër hapësira në vijën e qendrës boshe, shtoni 'ushqim' ose emrin e aplikacionit tuaj. Kjo pjesë e cilësimeve.py duhet të duket si:

INSTALLED_APPS = [
    'feed',
]
Para se të harrojmë, le të provojmë që Django po punon. Duke përdorur komandën Python Manage.py Runserver 0.0.0.0:8000, ne mund të ekzekutojmë serverin dhe pastaj të lundrojmë në një shfletues në internet në kompjuterin që drejton kodin në http: // localhost: 8000 dhe të shohim një faqe në internet (funksionon!) Lërini serverin me kontrollin C, njësoj si çdo komandë tjetër. Tani, le të gërmojmë në shkrimin e disa kodeve të Python. Django ka tre përbërës kryesorë, të gjithë ata drejtohen me kod tërësisht. Komponentët quhen model, pamje dhe shabllon, dhe secila është në një nivel më të lartë dhe më të ulët përkatësisht përpara se faqja në internet t'i dorëzohet përdoruesit. Modeli është kodi që ruan informacionin në bazën e të dhënave për rikthimin, zgjidhjen dhe interpretimin. Pamja vendos se si modeli është dhënë, manipuluar dhe modifikuar, pothuajse çdo pamje do të përdorë një model direkt. Modeli është kodi HTML me disa kambana dhe bilbila shtesë të quajtura Gjuha e Modelit. Modeli jepet nga pamja ku është e mbushur me kod python dheKonteksti siç janë modelet dhe informacioni (tela dhe numra të plotë të përdorimit) nga pamja. Django ka edhe përbërës të tjerë, duke përfshirë por jo të kufizuar në: Cilësimet, të cilat konfigurojnë aplikacionin ndërsa diskutuam. URL, të cilat janë modele që përdoruesi ndjek për të fituar qasje në pjesë specifike të aplikacionit në internet. Format, të cilat përcaktojnë se si informacioni që i dërgohet serverit trajtohet dhe jepet në bazën e të dhënave, si dhe përdoruesit. Këto janë themelet e informacionit për përpunimin në anën e serverit, dhe mund të pranojnë çdo lloj informacioni dyqanet e kompjuterave, veçanërisht vargjet e tekstit, numrat dhe Booleans të vërtetë/false (zakonisht kutitë e kontrollit). Shabllone, të cilat janë kodi html dhe gjuha e shablloneve dhe ura hendekun midis Python dhe HTML, që do të thotë se informacioni i Python mund të shërbehet si kod HTML që çdokush mund të qase për një larmi qëllimesh në një pajisje të largët që joeed të jetë afër serverit. Skedarët statikë, të cilat zakonisht janë JavaScript dhe janë bibliotekat të cilat serveri i shërben dhe janë të lidhura me shabllonin. Skedarët e mediave, të cilat serveri i shërben ose janë pritur nga jashtë, ose thjesht janë shkruar në server para se të përpunohen dhe postohen në një server tjetër (një kovë) për pritjen. Middleware, i cili është pjesë e kodit që drejtohen në të njëjtën kohë me çdo pamje dhe konsiderohen "të përfshira" në pamje. Procesorët e kontekstit, të cilët përpunojnë kontekstin e secilës pamje dhe përdoren për të shtuar një kontekst shtesë. Testet, të cilat vërtetojnë që përdoruesi ose kërkesa të kalojnë kërkesa të caktuara përpara se të jepet pamja. Konsumatorët, të cilët diktojnë se si trajtojnë faqet e internetit dhe i përgjigjen komunikimit. Admin, i cili përdoret për të regjistruar modele në mënyrë që ato të manipulohen në detaje brenda faqes së administratorit Django, ku baza e të dhënave mund të administrohet përmes një ndërfaqe grafike. Selino, e cila përcakton detyrat asinkrone pjesë të kodit Django mund të fillojnëNning para se të vazhdoni menjëherë në detyrën tjetër ose linjën e kodit. Django mund të ketë shumë përbërës të tjerë, për të cilët do t'i diskutojmë në detaje këtu. Ka shumë mënyra për ta bërë Django më funksionale, duke shtuar uebfaqe, të cilat janë të shpejta, kanale komunikimi të efektshme, selino, të cilat ekzekutojnë detyra asinkrone, dhe një mori pjesësh të tjera të softuerit për shtrirjen e django, veçanërisht në funksionet e shikimit, ku shumica e Kodi është ekzekutuar. Funksionet e shikimit janë thelbësore sepse ato zakonisht deklarojnë çdo pjesë të kodit që është specifik për një model specifik të URL -së, ose një seksion të serverit. Së pari, le të eksplorojmë funksionet e shikimit. Funksionet e shikimit fillojnë me importet që tregojnë kodin që do të përdoren në pamje, dhe përcaktohen duke përdorur përkufizime të rregullta të funksionit ose klasa. Pamjet më të thjeshta përcaktohen nga përkufizimi i funksionit DEF, dhe kthimi i një httPresponse me një shabllon themelor. Le të fillojmë duke përcaktuar një pamje themelore për të kthyer tekstin "Përshëndetje Bota". Mos harroni se sa herë që shtoniFter një deklaratë si def, nëse, ndërsa, për, etj, do t'ju duhet të shtoni 4 hapësira për secilën nga përkufizimet paraprake që dëshironi të aplikoni në funksionin tuaj. Ne do të futemi në atë që secila prej këtyre do të thotë së shpejti. Nga drejtoria e faqes sonë, modifikoni skedarin Feed/Views.py duke përdorur Nano dhe shtoni rreshtat e mëposhtëm në fund të

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
HttPresponse i Django përgjigjet me një varg teksti, i treguar me hapjen dhe mbylljen '. Sa herë që kaloni informacione në një funksion ose klasë, si kërkesë ose një varg, do t'ju duhet të përdorni kllapa (, hapje dhe mbyllje). Kjo nuk është gjithçka që na duhet për të parë mendimin tonë akoma. Sigurisht, ne nuk i kemi thënë serverit ku pamja është saktësisht, ne ende duhet të përcaktojmë një shteg me të cilin duhet të japë pamja. Le të fillojmë duke përcaktuar një rrugë themelore në APP/urls.py, dhe ne do të futemi në grupe shteg më vonë. Në APP/urls.py, shtoni një rresht pas deklaratave të importit pas fillimit të importimit të pamjes që sapo krijuam.

from feed import views as feed_views
Tani, le të përcaktojmë modelin e pamjes. Modelet e shikimit kanë tre komponentë, përbërësin e rrugës, i cili i tregon serverit ku pamja ekziston brenda serverit (shtegu i URL -së që përdoruesi i shtyp në shiritin e navigimit për të hyrë në faqen e internetit), përbërësi i shikimit ku është specifikuar pamja, dhe a Emri miqësor për pamjen, kështu që është e lehtë për të tërhequr modelin e tij kur punoni me një shabllon, veçanërisht kështu që emri mund të ndryshohet dhe azhurnohet nëse është e nevojshme për të bërë hapësirë ​​për një pamje tjetër ose për të marrë një emër më logjik. Ka kuptim të bësh gjëra në këtë mënyrë dhe të jetë fleksibël, sepse baza e kodit tuaj do të jetë një mjedis gjithnjë në ndryshim që ka nevojë për fleksibilitet dhe improvizim në mënyrë që të jetë i vlefshëm dhe i lehtë për t'u punuar me të. Ja se si do të duket pikëpamja juaj, mund ta shtoni këtë në urlpatterns = [Seksioni i App/URLS.py. Modeli i pamjes përcaktohet me tre përbërësit e përshkruar më lart, dhe një funksion të quajtur shteg. Modelet tuaja të URL -së janë një listë, prandaj sigurohuni që gjithmonë t'i jepni fund secilit artikull në tome presje, sepse kjo ndan secilën prej tyre. Do artikull gjithashtu duhet të shkojë në një linjë të re, edhe një herë me katër hapësira para tij, ashtu si aplikacioni në Settings.py. Ne do të përcaktojmë përbërësin e parë të pamjes me një funksion boshe, në mënyrë që të krijojmë një pamje që funksionon në drejtorinë rrënjësore të serverit në internet. URL -të e tua tani duhet të duken

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
Kjo është baza për krijimin e një faqe në internet me Django që është plotësisht statike. Në mënyrë që të bëjmë një uebfaqe më dinamike ku mund të fillojmë informacionin e caching, si imazhe, video, audio dhe më shumë, do të duhet të përdorim modele, të cilat do t'i eksplorojmë tjetër. Tani për tani, le të kontrollojmë kodin tonë dhe të ekzekutojmë serverin. Për të kontrolluar kodin për gabime, ekzekutoni:

python manage.py check
Nëse ka ndonjë mesazh gabimi, duhet të rishikoni me kujdes ndryshimet që keni bërë në aplikacionin tuaj dhe të shihni nëse ka ndonjë gjë që duhet të fiksohet, si një hapësirë ​​e jashtëligjshme ose që i mungon, një karakter shtesë, një varg i pakontrolluar, ndonjë shtypje, ndonjë aksidentalisht Karakteri i fshirë, ose ndonjë gjë tjetër. Duke lexuar mesazhin e gabimit (nëse keni një të tillë), duhet të jeni në gjendje të shihni rrugën për në një skedar që keni krijuar ose redaktuar së bashku me një numër të linjës, kështu që shikoni në atë skedar dhe rresht dhe të shihni nëse mund të rregulloni ndonjë gjë që është atje . Nëse e keni rregulluar çështjen, ekzekutoni përsëri komandën e mësipërme. Kur softveri juaj është i gatshëm për të kandiduar dhe po punon, ju do të shihni daljen "Kontrolli i sistemit nuk ka identifikuar asnjë problem". Tani ju jeni gati të shkoni. Ekzekutoni serverin me:

python manage.py runserver 0.0.0.0:8000
Tani hapni një shfletues në internet dhe lundroni në http: // localhost: 8000. Ju duhet të shihni tekstin e kthyer në kllapa dhe citate të funksionit HTTPRESPONSE sipas mendimit tuaj. Ky është vetëm një shembull themelor, por nëse e keni bërë këtë larg, ju i kuptoni bazat se si funksionojnë Linux, Bash, Python dhe Django. Le të gërmojmë më thellë në disa modelim të bazës së të dhënave dhe të eksplorojmë fuqinë e një klase Python në ruajtjen e informacionit. Pastaj, ne do të fillojmë të marrim një kontroll në HTML dhe CSS para se ta bëjmë faqen tonë të paraqitur plotësisht, fleksibël dhe të sigurt duke përdorur JavaScript dhe Machine Learning. Klasat ruhen në modele.py të aplikacionit tuaj. Duke përdorur nano, modifikoni aplikacionin/modelet.py dhe shtoni një klasë të re. Një klasë përcaktohet me përkufizimin e klasës dhe i kalohet një super klasës nga e cila trashëgon, në këtë rast modele.model. Emri i klasës vjen pas përcaktimit të klasës, dhe pasi të përdoret përkufizimi i klasës A: (zorra e trashë), përpara se atributet dhe përkufizimet e funksionit të lidhura me klasën të tregohen më poshtë. Klasa jonëKa nevojë për një ID që mund të përdorim për ta tërhequr atë dhe për ta mbajtur atë unik, dhe gjithashtu ka nevojë për një fushë teksti për të ruajtur disa informacione. Më vonë, ne mund të shtojmë një afat kohor, skedarë, booleans (përkufizime të vërteta ose të rreme që mund të ndihmojnë kodin tonë të marrin vendime se çfarë të bëjmë me modelin, dhe mund të përdoren për ta zgjidhur atë), një shembull për të lidhur modelin me një përdorues të regjistruar në server, dhe më shumë. Le ta shpaketojmë kodin

from django.db import models # Importi që përdoret për të përcaktuar klasën tonë dhe atributet e tij

class Post(models.Model): # Përkufizimi i vetë klasës sonë
    id = models.AutoField(primary_key=True) # ID e modelit tonë, një çelës i gjeneruar automatikisht që do të na lejojë të kërkojmë modelin, ta mbajmë atë unik dhe është i dobishëm kur duhet të bashkëveprojmë me modelin pasi të jetë krijuar.
    text = models.TextField(default='') # Atributi dyqanet tona të klasës, në këtë rast, disa tekst, duke mos paguar një varg bosh.
Mbyllni dhe ruajeni skedarin ashtu siç kemi bërë më parë për të përfunduar. Ka shumë fusha dhe opsione të tjera që do t'i eksplorojmë kur të azhurnojmë këtë klasë ndërsa aplikacioni ynë evoluon, por kjo është nevojat themelore të krijimit të një aplikacioni për të postuar ndonjë tekst. Sidoqoftë, ky model nuk do të funksionojë vetëm. Siç përshkruhet më parë, do të na duhet një pamje me porosi dhe model i url për ta bërë këtë model të funksionojë, dhe do të na duhet gjithashtu një formë së bashku me një shabllon. Le të shqyrtojmë së pari formularin. Për të përcaktuar një formë, modifikoni aplikacionin/format.py me Nano dhe shtoni rreshtat e mëposhtëm. Do të na duhen dy importe, klasa jonë e formave, si dhe modeli që kemi krijuar (Feed.models.post), një përkufizim i klasës i ngjashëm me modelin, dhe një fushë së bashku me një nënklasë të quajtur meta që do të përcaktojë modelin formën ndërvepron me Forma gjithashtu mund të ketë një funksion fillestar që e vendos atë bazuar në informacionin në kërkesë, model ose ndryshe, ne do ta eksplorojmë këtë më vonë. Format e modelit janë kaq të dobishme sepse ato mund të krijojnë një model ose gjithashtu të modifikojnë një model,Kështu që ne do t'i përdorim ato për të dy. Le ta përcaktojmë një në forma.py

from django import forms
from feed.models import Post

class PostForm(forms.ModelForm):
    text = forms.CharField(widget=forms.Textarea)
    class Meta:
        model = Post
        fields = ('text',)
Kjo është bazat e asaj që duket një formë dhe model. Kjo formë modeli mund të përdoret për të çastuar ose modifikuar një postim, duke ndryshuar tekstin që përmban. Ne do të shohim integrimin e kësaj forme në një pamje tjetër. Së pari, le të bëjmë migrimet dhe të migrojmë bazën e të dhënave në mënyrë që kodi ynë të mund të bashkëveprojë me modelin kur të funksionojë. Për ta bërë këtë, ekzekutoni komandat e mëposhtme:

python manage.py makemigrations
python manage.py migrate
Kjo do të marrë një minutë për të ekzekutuar, por pasi të ndodhë, do t'ju lejojë të hyni në modelin në pamje, ndërmjetës, ose kudo tjetër në softuer. Le të vazhdojmë duke bërë një pamje ku mund të shohim modelin tonë. Redaktoni burimin/pamjet.py dhe shtoni kodin e mëposhtëm, siç u përmend. Ju nuk do të duhet të shtoni asgjë pas shenjës #, ai kod është komente që përdoren për të treguar informacione rreth kodit. Ne do të fillojmë duke importuar modelin tonë në pamje, dhe duke e shtuar atë në një kontekst ku ne mund ta bëjmë atë në një shabllon si një listë për shfaqje. Tjetra, ne do të shtojmë një shabllon ku mund të japim formularin dhe modelin me një buton për të krijuar një objekt të ri bazuar në modelin dhe ta postojmë në server. Kjo tingëllon e ndërlikuar, kështu që le ta bëjmë atë hap pas hapi. Para se të përfundojmë pamjen, le të krijojmë një shabllon që thjesht e bën modelin dhe të sigurohemi që mund ta shohim atë duke krijuar një postim të ri në guaskë. Ja se si duhet të duket ajo pamje:

from feed.models import Post
from django.shortcuts import render, redirect
from django.urls import reverse

def feed(request):
    posts = Post.objects.all() # Pyetni të gjitha postimet në bazën e të dhënave deri më tani
    return render(request, 'feed/feed.html', {
        'posts': posts,
    })
E gjitha kjo duket mjaft e thjeshtë derisa të arrijmë në fund. Render, vlera e kthyer nga funksioni në vend se në një përgjigje HTTP si shembulli i mëparshëm, gjithmonë merr një kërkesë si inputi i parë i saj, pranon një kontekst (në këtë rast postimet në bazën e të dhënave), i cili tani mund të jepet në shabllon , dhe kthen modelin e përcaktuar në funksion. Modeli do të jetë një dokument HTML me pak gjuhë të quajtur Jinja2, e cila bën informacione Python në HTML. Për të filluar krijimin e shablloneve, bëni dy drejtori në ushqim.

mkdir feed/templates
mkdir feed/templates/feed
Tjetra, modifikoni një shabllon në drejtorinë e mësipërme, ushqeni/shabllonet/ushqeni dhe shtoni kodin për këtë shembull. Le të shohim modelin për këtë shembull.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Ky është një model shumë i thjeshtë. Përcakton hapjen dhe mbylljen e etiketave HTML, një etiketë të llojit të dokumentit, një etiketë trupi me një titull legjendash, një etiketë pushimi e cila shton një linjë të vogël në të gjithë ekranin, dhe një për lak që i jep secilit postim në listën e postimeve si një paragraf në shablloni. Kjo është gjithçka që duhet për të dhënë postime, por ende nuk ka asnjë në bazën e të dhënave. Le të krijojmë disa me guaskën. Ne mund ta ekzekutojmë guaskën me menaxhimin.py

python manage.py shell
Tani, le të importojmë modelin tonë të postimit

from feed.models import Post
Tjetra, ne do të krijojmë një postim të thjeshtë me një varg dhe do të dalim nga guaska. Vargu mund të jetë gjithçka, për sa kohë që është teksti i vlefshëm.

Post.objects.create(text='hello world')
exit()
Së fundmi, do të duhet të shtojmë një model URL në ushqimin tonë. Për shkak se aplikacioni ynë i ushqimit do të përdorë URL të shumta dhe ne duam t'i mbajmë madhësitë e skedarëve të vegjël, le të krijojmë një URL.py lokale në aplikacionin tonë Feed që duket si kjo:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.feed, name='feed'),
]
Ne gjithashtu do të duhet të modifikojmë URLS.py në aplikacionin bazë, çfarëdo që vendosëm ta quajmë, kjo ishte drejtoria e parë që krijuam. Redaktoni App/App.py dhe shtoni sa vijon në modelet e URL -së

from django.urls import include # në krye

urlpatterns = [
    # ... Kodi i mëparshëm këtu
    path('feed/', include(('feed.urls'), namespace='feed')),
]
Tani, kur ne ekzekutojmë serverin me Python Manage.py Runserver, ne do të shohim faqen që kemi krijuar sepse kemi modelin, pamjen dhe modelin, si dhe modelin e URL -së, së bashku me artikujt në bazën e të dhënave. Tjetra, le të zbatojmë formën që krijuam dhe të fillojmë të krijojmë postimet tona. Por para se të shkruajmë shumë kod, le të bëjmë një kopje rezervë duke përdorur skenarin që kemi shkruar më herët, kopje rezervë. Drejtoni këtë skenar në guaskë, prisni disa momente, dhe i gjithë kodi do të mbështetet në depo tonë git.

backup
Zbatimi i formularit është relativisht i thjeshtë. Ne do të importojmë formën tonë, do të shtojmë një mbajtës të kërkesës për postim në pamje dhe do ta ruajmë postimin në bazën e të dhënave përpara se të ridrejtojmë në të njëjtën pamje. Ne mund të përdorim funksionin e ridrejtimit që kemi importuar tashmë, dhe një funksion tjetër i quajtur Reverse për të marrë URL për modelin e shikimit. Ne do ta kërkojmë këtë me vargun 'Feed: Feed' sepse hapësira e emrave të modelit të përfshirë është ushqimi, dhe pamja quhet edhe Feed.

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # Pyetni të gjitha postimet në bazën e të dhënave deri më tani
    if request.method == 'POST': # Trajtoni kërkesën për postim
        form = PostForm(request.POST) # Krijoni një shembull të formularit dhe ruajeni të dhënat në të
        if form.is_valid(): # Vlerësoni formularin
            form.save() # Ruani objektin e ri
        return redirect(reverse('feed:feed')) # Ridrejtohuni në të njëjtën URL me një kërkesë GET
    return render(request, 'feed/feed.html', {
        'form': PostForm(), # Sigurohuni që ta kaloni formularin në kontekst në mënyrë që të mund ta japim atë.
        'posts': posts,
    })
Tani, do të duhet të azhurnojmë modelin për të dhënë llogari për formën e re. Ne mund ta bëjmë këtë duke përdorur
Tag në HTML dhe duke e dhënë formularin në modelin HTML me një buton dorëzimi. Do të na duhet gjithashtu një shenjë CSRF, një shenjë e cila parandalon që faqet e jashtme të postojnë në formular pa ngarkuar më parë një faqe.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<form method=”POST”>
{% csrf_token %}
{{ form }}
<button type=”submit”>New Post</button>
</form>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Le ta zbërthejmë këtë. Ekziston një klasë e re e formës, një shenjë, vetë forma dhe një buton dorëzimi. Shumë e thjeshtë, por kur e hedhim një vështrim në të, mund të dëshirojmë ta bëjmë atë të duket më mirë. Ajo funksionon, ne mund të postojmë postime të reja me formularin dhe ato tani ruhen në bazën e të dhënave. Ka disa gjëra që po ndodhin këtu. Ne përdorim etiketat HTML për të deklaruar se dokumenti është një dokument HTML, ne përdorim një etiketë shablloni ({ %… %}) për të dhënë shenjën për formën, dhe një tjetër, {{…}} për të dhënë formën. Ne gjithashtu kemi një lak për të dhënë tekstin duke përdorur etiketa bllok dhe një etiketë shablloni. Etiketat e bllokut janë me të vërtetë të rëndësishme sepse ne mund të përcaktojmë se si pjesët e shabllonit jepen me to, dhe etiketat e shablloneve janë baza e mënyrës se si i vendosim variablat në kodin tonë. Tani duhet ta bëjmë aplikacionin tonë të duket më mirë, sepse tani për tani duket vërtet themelore. Ne mund ta bëjmë këtë duke përdorur CSS, ose inline, ose në klasa të lidhura me secilin objekt në dokument. CSS është vërtet e bukur sepse tregon gjithçka në faqe se si duhet të duket,Dhe mund ta bëjë atë të duket vërtet mirë. Ka disa biblioteka që mund ta bëjnë këtë, por personaliteti im personal është bootstrap. Bootstrap mund të shkarkohet nga faqja e tyre e internetit,GetBootstrap.com/. Pasi të jeni atje, shtypni butonin për të lexuar dokumentet e instalimit dhe kopjoni kodin nga seksioni i përfshirë përmes CDN. Ju do të keni nevojë për këtë kod në krye të dokumentit tuaj HTML, në një etiketë të quajtur Head. Gjithashtu, le të shkojmë përpara dhe të krijojmë një shabllon bazë, kështu që ne nuk kemi nevojë t'i rikrijojmë këto lidhje në secilin shabllon. Bëni një direktori të re të quajtur Modelet me shabllone Mkdir, dhe pastaj modifikoni shabllone/bazë.html. Duhet të duket kështu:
 
<!doctype HTML>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
 
Sigurohuni që të kopjoni CSS dhe JavaScript, skedarët .css dhe .js, sepse do të na duhet JavaScript për ta bërë faqen tonë më funksionale në të ardhmen. Tani, le të kthehemi në guaskën e bashit dhe të drejtojmë një komandë të shpejtë. Mos harroni, nëse ndonjëherë keni nevojë për të hyrë në mjedisin virtual, lloji i burimit VENV/bin/aktivizoni. Kjo do t'ju lejojë të instaloni Paketat Python në vend në një mënyrë që lejon Django të hyjë në to. Për të dhënë format tona të krijuara nga klasa Django Bootstrap, ne do të përdorim një paketë Python të quajtur Crispy Forms. Ne mund ta shkarkojmë këtë me komandën e mëposhtme

pip install django-crispy-forms
Pasi të instalohet kjo, shtojeni në cilësimet.py

INSTALLED_APPS = [
    # … Kodi i mëparshëm këtu
    'crispy_forms',
]
Tani, përsëri në modelin tonë të ushqimit, ne mund të heqim disa gjëra. Le të heqim fillimin dhe fundin e dokumentit dhe ta zëvendësojmë atë me trashëgimi nga modeli ynë bazë, duke përdorur shtrirjet dhe përcaktimin e bllokut. Gjithashtu, ne do të shtojmë një import të filtrit të modelit me ngarkesë dhe një filtër shablloni në formë. Së fundmi, le të shtojmë një klasë bootstrap në butonin në formë për ta bërë atë të duket më shumë si një buton. Kjo duhet të duket kështu:
 
{% extends 'base.html' %}
{% block body %}
{% load crispy_forms_tags %}
<form method=”POST”>
{% csrf_token %}
{{ form|crispy }}
<button type=”submit” class=”btn btn-outline-primary”>New Post</button>
</form>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
{% endblock %}
 
E bukur! Kjo është mjaft kod tashmë. Tjetra, ne duhet ta provojmë atë dhe të sigurohemi që mund të shohim se gjithçka duket bukur, dhe gjithashtu të jetë i sigurt se gjithçka po funksionon siç duhet. Drejtoni serverin sipas udhëzimeve të mëparshme dhe sigurohuni që faqja të duket dhe të funksionojë mirë. Punë e shkëlqyeshme! Ju jeni gati të kaloni në hapin tjetër, në të cilin ne do të shtojmë funksionalitetin e hyrjes së përdoruesit duke përdorur URL, forma, pamje dhe shabllone të ngjashme. Modeli bazë është i rëndësishëm, dhe ne do të vazhdojmë ta modifikojmë atë dhe të bëjmë ndryshime sipas nevojës, por tani le të përqëndrohemi në bërjen e faqes sonë më të sigurt, duke u mundësuar përdoruesve të regjistrohen me një emër përdoruesi dhe kodifikimi, dhe përfundimisht edhe informacione më të rëndësishme që Do t'ju ndihmojë të mbani aplikacionin tuaj të sigurt dhe llogarinë tuaj të arritshme vetëm nga ju. Për ta bërë këtë, ne do të duhet të përdorim modelin e përdoruesit të integruar në Django. Modeli i përdoruesit është një model i bazës së të dhënave, si postimi ynë, që mund të jepet për të regjistruar një përdorues në faqen e internetit. Në të ardhmen, para se të vendosim faqen në internet, ne do ta bëjmëZgjatni këtë model me modele të tjera që i atribuohen asaj dhe ndërtoni masa shtesë të sigurisë për hyrjen që janë rezistente ndaj phishing. Ne do të fillojmë duke përdorur disa forma të ndërtuara në hyrje që ofron Django. Së pari, le të krijojmë një aplikacion të ri që do të përdorim për të dhënë shabllonet dhe pamjet për faqen themelore të hyrjes. Ne gjithashtu do të krijojmë aplikacione të tjera për të përfaqësuar sfidat e vazhdueshme të hyrjes në mënyrë që të sigurojmë aplikacionin, duke përfshirë një pincode, njohjen e fytyrës, komunikimin në terren të afërt, pajisjet e jashtme, vërtetimin e shumë faktorëve dhe njohjen e gjurmëve të gishtërinjve. Ne tashmë kemi biseduar për fillimin e një aplikacioni. Nga drejtoria jonë, brenda mjedisit virtual, kaloni menaxhimin.py këto

python manage.py startapp users
Tani, duhet të kemi një direktori për aplikacionin e ri. Le të fillojmë duke krijuar një pamje në atë direktori që korrespondon me hyrjen e përdoruesit. Django ka ndërtuar pamje për hyrjet e përdoruesve, por këto nuk do të jenë të përshtatshme për ne sepse ne kemi nevojë për një pamje me porosi, e cila preferohet të bëhet me një përkufizim. Në këtë pamje, ne do të fillojmë duke kontrolluar për një kërkesë për postim, kaloni kërkesën.POST në një formim login të importuar nga Django, të vërtetoni llogarinë e përdoruesit dhe të regjistroheni në përdoruesin përpara se t'i ridrejtojmë ato në aplikacionin tonë Feed. Në Përdoruesit/Views.py, shtoni kodin e mëposhtëm

from django.shortcuts import render, redirect
from django.urls import reverse
from django.contrib.auth.forms import AuthenticationForm, SetPasswordForm
from django.contrib.auth import authenticate, logout
from django.contrib.auth import login as auth_login
from django.contrib import messages

def login(request):
    if request.method == “POST”:
        username = request.POST['username'] # Merrni emrin e përdoruesit dhe fjalëkalimin nga kërkesa për postim
        password = request.POST['password'] # Vërtetoni përdoruesin
        user = authenticate(username=username, password=password)
        if user:
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
            messages.success(request, 'Your password was accepted. Please continue')
            return redirect(reverse('feed:feed'))
        else: messages.warning(request, 'Username or password incorrect. Please try again')
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Kjo është gjithçka që ju nevojitet për një pamje themelore të hyrjes. Tani, le të krijojmë një formë për pamjen duke zgjatur modelin bazë. Ne do të fillojmë duke krijuar një direktori të re për shabllonet në dosjen e përdoruesve.

mkdir users/templates
mkdir users/templates/users
Tani, ne duhet të jemi në gjendje të modifikojmë përdoruesit/shabllonet/përdoruesit/login.html. Ndërsa jemi në të, ne do të krijojmë një shabllon për të lejuar përdoruesin të regjistrohet gjithashtu.

nano users/templates/users/login.html
Tani, në shabllon,
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST">
    {% csrf_token %}
    <fieldset class="form-group">
        <legend class="border-bottom mb-4 break">Log In</legend>
        {{ form|crispy }}
    </fieldset>
    <div class="form-group">
        <button class="btn btn-outline-info" type="submit">Login</button>
    </div>
</form>
{% endblock %}
 
Kjo është bazat e një shablloni të hyrjes. Reallyshtë me të vërtetë ashtu si modeli tjetër në strukturë, por duket pak më ndryshe kur është dhënë. Ne mund ta kopjojmë këtë kod për të ndërtuar një model tjetër shumë të ngjashëm të quajtur Register.html, ku do të ndryshojmë formulimin dhe do të përdorim një formë të re që ndërtojmë. Le ta bëjmë modelin së pari. Redaktoni përdoruesit/shabllonet/përdoruesit/regjistri.html dhe shtoni kodin e mëposhtëm:
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST">
    {% csrf_token %}
    <fieldset class="form-group">
        <legend class="border-bottom mb-4 break">Create an account</legend>
        {{ form|crispy }}
    </fieldset>
    <div class="form-group">
        <button class="btn btn-outline-info" type="submit">Register</button>
    </div>
</form>
{% endblock %}
 
Tani, le të ndërtojmë një formë për regjistrimin tonë të përdoruesit dhe të rrethojmë përsëri në pamje para se të azhurnojmë hyrjet e përdoruesve tanë me një model. Ne do ta bëjmë këtë formë themelore për të filluar, por të përfshijmë më shumë detaje dhe veçori të sigurisë siç janë marrëveshjet dhe CAPTCHA në të ardhmen. Redaktoni format me përdoruesit e nano/forms.py dhe shtoni kodin e mëposhtëm.

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']
Pra, ne kemi një formë tjetër këtu, e cila funksionon mjaft thjesht. Shtë një formë e regjistrit të përdoruesit me një emër përdoruesi, email dhe fjalëkalim, si dhe një fushë të konfirmuar fjalëkalimi. Vini re se kjo formë nuk zgjat format e rregullta. Klasa e formës, është një formë modeli që do të thotë se ka një meta. Një fushë përcaktohet njësoj, dhe meta e klasës përcakton modelin forma korrespondon me pjesën tjetër të informacionit që do të shkruhet në formular. Shumica e kësaj ekziston tashmë në Django të ndërtuar në UserCreationForm, kështu që ne do ta përdorim atë si bazë për klasën (kaluar në kllapa). Tjetra, ne do të shqyrtojmë pamjen për të regjistruar një përdorues, tani që kemi një formë dhe një shabllon. Ky është një modeForm, ashtu si ai në pamjen e re të postimit. Redaktoni përdoruesit/pamjet.py dhe shtoni kodin e mëposhtëm:

# … Shuma
from .forms import UserRegisterForm

def register(request):
    if request.method == “POST”:
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Kjo është gjithçka që na duhet për të regjistruar një përdorues, por duhet të kemi më shumë informacion. Ne duam të dimë kohën kur përdoruesi i regjistruar, në cilën orë ata ishin të fundit në sit, disa informacione rreth tyre, si një biografi, zona kohore, etj. Gjithashtu, do të duhet të azhurnojmë modelin tonë të ushqimit, të postojmë, për të dhënë llogari për përdoruesin Modeloni dhe atribuoni postime për secilin përdorues. Për ta bërë këtë, ne do të azhurnojmë modelet.py në të dy aplikacionet. Le të fillojmë duke redaktuar modelin e ushqimit. Duhet të duket kështu tani:

from django.db import models # … Shuma
from django.contrib.auth.models import User

class Post(models.Model):
    id = models.AutoField(primary_key=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name='posts') # Shto në këtë linjë
    text = models.TextField(default='')
Kushtojini vëmendje rreshtit të dytë që iu shtua skedarit. Ky është një çelës i huaj, i cili do t'i atribuojë secilit postim një përdoruesi të vetëm për postim, kështu që ne mund të sigurohemi që t'i ruajmë postimet në bazë të përdoruesit për përdorues dhe asnjë postim nuk mund të bëhet pa ia atribuar një përdoruesi. Ne e përcaktojmë këtë çelës të huaj me klasën që përfaqëson, një argument i fshirjes për të siguruar që postimet janë fshirë me përdoruesit, argumentet e pavlefshme dhe të zbrazëta për t'u siguruar që mund ta heqim përdoruesin nëse është e nevojshme, dhe të akomodojmë për mungesën e një përdoruesi në postime që ne tashmë ne tashmë krijuar, dhe një emër të lidhur, të cilin mund ta përdorim për t'iu referuar objekteve të postimit që krijon përdoruesi. Ky emër i lidhur, ndryshe nga Post.Author, autori i postimit, na jep përdorues që postoi vetë postimin. Tani ne mund t'i marrim postimet një përdorues të bërë duke ekzekutuar user.posts.all (), ose autor.posts.all (). Tani, le t'i bëjmë hyrjet tona më elastike. Ne tashmë mund ta bëjmë faqen tonë shumë më pak të prekshme nga phishing thjesht duke vlerësuar kufizimin e numrit të herë që do të lejojmë një hyrje nësit, kjo është mjaft e lehtë. Le të fillojmë të ruajmë disa informacione për secilin përdorues më parë ndërsa vazhdojmë të zhvillojmë aplikacionin tonë. Redaktimi i përdoruesve/modeleve.py, shtoni sa vijon

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name='profile')
    account_created = models.DateTimeField(default=timezone.now)
    last_seen = models.DateTimeField(default=timezone.now)
    can_login = models.DateTimeField(default=timezone.now)
    preferred_name = models.CharField(max_length=20,default='', null=True, blank=True)
    bio = models.TextField(blank=True, default='')
Vini re se ky model është mjaft i ngjashëm me modelin POST. Ne kemi një import shtesë, zona kohore, e cila do të na lejojë të vendosim parazgjedhje në fushat e DateTime, dhe ne gjithashtu kemi një karakter të karakterit dhe tekstit si postimi. Përdorimi i të gjitha këtyre kohërave, na ndihmon të sigurojmë faqen dhe të kuptojmë përdorimin e tij, dhe fushat e tekstit na lejoni të japim informacione për secilin përdorues, ose autor, në faqen e internetit. OneToOneField duhet të jetë konsiderata e vetme e vogël, ai sillet saktësisht i njëjtë me një Foreginkey por me vetëm një për modelin pasues. Në këtë mënyrë, përdoruesi ka vetëm një profil, ndërsa ata mund të kenë shumë postime. Tani, le të përmirësojmë hyrjen tonë dhe të regjistrojmë pikëpamjet për të dhënë llogari për profilin. Së pari, modifikoni përdoruesit/Views.py dhe përqendrohuni në pamjen e regjistrit:

# … Shuma
from .forms import UserRegisterForm

def register(request):
    if request.method == “POST”:
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            Profile.objects.create(user=user) # Sigurohuni që të shtoni këtë linjë, për të krijuar një profil për përdoruesin
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Kjo thjesht krijon një profil për përdoruesin, pa plotësuar asnjë prej informacionit. Tani, ne duam të sigurohemi që llogaria e përdoruesit nuk mund të regjistrohet shumë shpesh, ose të paktën fjalëkalimet nuk mund të provohen shumë shpesh, kështu që le të azhurnojmë pamjen e hyrjes.

# … Shuma
from .models import Profile
from django.utils import timezone
import datetime

def login(request):
    if request.method == “POST”:
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user and user.profile.can_login < timezone.now(): # Vini re se ne tani kontrollojmë nëse përdoruesi mund të regjistrohet
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
            messages.success(request, 'Your password was accepted. Please continue.')
            return redirect(reverse('feed:feed'))
        else: # Nëse hyrja nuk ishte e suksesshme,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Kjo është pjesa ku ne azhurnojmë profilin e përdoruesve
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Kështu që ata nuk mund të regjistrohen përsëri për disa sekonda
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Ky është themelor themelor i sigurisë. Sigurohuni që faqja të mos jetë e prekshme nga dikush thjesht duke provuar çdo kombinim të mundshëm të fjalëkalimit, apo edhe disa prej tyre në të njëjtën kohë. Kjo nuk do të jetë zhgënjyese për përdoruesin e zakonshëm që njeh kodin e tyre të kalimit dhe thjesht duhet të futet në disa pajisje, por do të mbajë robotë të shumtë phishing jashtë aplikacionit. Vini re se kemi shtuar një deklaratë IF me një ndryshore, can_login, që duhet të jetë një kohë në të kaluarën, dhe ta azhurnojmë atë me çdo hyrje të pasuksesshme duke përdorur të njëjtin emër përdoruesi. Në këtë mënyrë, një përdorues me qëllim të keq nuk do të jetë në gjendje të marrë me mend një fjalëkalim kudo afër sa më shpejt. Numri i sekondave në DateTime.Timedelta () mund të azhurnohet gjithashtu, dhe faqja e internetit do të jetë më elastike por pak më pak e përdorshme me më shumë sekonda. Unë rekomandoj 15 të filloj me. Mos harroni, ne ndërtuam një skenar rezervë për të shpëtuar punën tonë, kështu që le të shkojmë përpara dhe të rezervojmë atë që kemi deri më tani për t'u siguruar që kemi gjithçka të ruajtur. Drejtoni komandën:

sudo backup
Edhe një herë, kjo do të kursejë punën tuaj deri më tani. Unë rekomandoj të ekzekutoni kopje rezervë të shpeshta për të kursyer punën tuaj, dhe madje mund të dëshironi të drejtoni një punë rezervë automatikisht. Ju mund ta bëni këtë duke përdorur një mjet Unix të quajtur Cron. Për të aktivizuar këtë mjet, ekzekutoni komandën e mëposhtme dhe shkruani fjalëkalimin tuaj:

sudo crontab -e
Nëse nuk e keni zgjedhur tashmë opsionin 1 për Nano, redaktorin e tekstit me të cilin tashmë duhet të jeni të njohur dhe të lëvizni në fund të skedarit duke përdorur çelësat e shigjetave. Shtoni rreshtin vijues:

0 * * * * sudo backup
Cron përdor minutën e formatit, orën, ditën e muajit, muajin, ditën e javës, ku një * ose një numër përfaqëson kur të drejtoni komandën. Duke përdorur një 0 për minutë dhe * për pjesën tjetër të opsioneve, ne mund të ekzekutojmë një komandë në minutën e parë të çdo ore në fillim të minutës. Kjo na lejon të kopjojmë kodin automatikisht. Të gjitha punët e Cron kur ekzekutohen me sudo funksionojnë si rrënjë, kështu që ne nuk do të kemi nevojë të shkruajmë një fjalëkalim çdo orë. Për ta bërë më të lehtë kopjimin e kodit tonë pa përdorur një fjalëkalim, le të çaktivizojmë fjalëkalimin për komandën tonë rezervë. Ne do ta bëjmë këtë duke ekzekutuar komandën e mëposhtme dhe duke futur një fjalëkalim:

sudo visudo
Tani, le të lëvizim në fund të skedarit dhe të shtojmë një rresht tjetër:

ALL ALL=NOPASSWD: /bin/backup
Kjo na lejon të ekzekutojmë komandën "rezervë" si çdo përdorues, pa një fjalëkalim. Formati për këtë është i lehtë, thjesht prefiks linjën me "të gjithë = nopasswd:/bin/" dhe përfundoni me komandën, për shembull/kosh/rezervë, i cili ekziston në/usr/bin/. Tani, le të fillojmë të punojmë me email. Emaili është me të vërtetë i rëndësishëm për faqet e internetit, sepse është një mënyrë për të mbajtur një faqe në internet më të sigurt, verifikoni që përdoruesit janë njerëz të vërtetë, dhe madje edhe produkte ose shërbime të tregut për klientët. Shumë njerëz që frekuentojnë internetin kontrollojnë emailin e tyre çdo ditë, dhe marrin të gjitha llojet e postës elektronike të marketingut në lidhje me produktet dhe shërbimet për të cilat interesohen. Ka disa mundësi kur bëhet fjalë për të mundësuar email në një uebfaqe django, dhe ju jeni të mirëpritur të zgjidhni Kushdo që funksionon më mirë për ju. Së pari, ju mund të paguani për një shërbim me email që do t'ju lejojë të dërgoni email nga domain juaj dhe kërkon kod minimal. Ka shumë shërbime që e ofrojnë këtë, të tilla si Google Workspace, SendInBlue, Mailgun, dhe më shumë. Përndryshe, ju jeni mirë duke ndërtuarShërbimi juaj i postës elektronike brenda serverit tuaj nga e para. Unë rekomandoj këtë mundësi, edhe pse është më shumë kod dhe mund të kërkojë pritje të veçantë. Ju nuk do të jeni në gjendje të filloni një server me postë nga kompjuteri juaj në shtëpi ka shumë të ngjarë, kështu që le të shkojmë përpara dhe të shqyrtojmë konfigurimin dhe kodin për të dërguar email para se të fillojmë një server në cloud dhe të krijojmë serverin tonë të postës brenda. Së pari, modifikoni cilësimet.py me sa vijon

nano app/settings.py
Ku aplikacioni është emri i aplikacionit që keni krijuar me StartApp. Shtoni rreshtat e mëposhtëm:

SITE_NAME = 'Django App'

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = username@server.com'
EMAIL_HOST_USER = 'username'
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
Sigurohuni që t'i ndryshoni këto kur të jeni gati për të vendosur aplikacionin tuaj, ne do ta rishikojmë këtë më vonë. Vendosja e postës elektronike duhet të jetë emaili nga i cili dëshironi të dërgoni, dhe fjalëkalimi (email_host_password) duhet të vendoset në fjalëkalimin që gjeneroni për serverin. Unë ngarkoj fjalëkalimin nga një skedar konfigurimi për ta mbajtur atë jashtë kodit duke përdorur logjikën e mëposhtme, mbi këto rreshta në cilësime.py:

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Pastaj, unë kam vendosur një skedar JSON me konfigurimin në /etc/config.json duke përdorur Nano si më poshtë. Për të modifikuar skedarin:

sudo nano /etc/config.json
Shtoni rreshtat e mëposhtëm:

{
	“EMAIL_HOST_PASSWORD”: “<some password here>”
}
Ne do të vazhdojmë të modifikojmë skedarin e konfigurimit dhe të shtojmë të gjitha fjalëkalimet dhe çelësat që do të përdorim në aplikacion. Tani për tani, le të shqyrtojmë shpejt se si të dërgojmë email duke përdorur Python. Së pari, le të krijojmë një shabllon për një email verifikimi që mund t'u dërgojmë përdoruesve tanë, dhe ta vendosim atë në drejtorinë e modeleve të përdoruesit. Ky shabllon do të shkruhet në HTML.

nano users/templates/users/verification_email.html
 
<h1>Django App - Verify Your Email</h1>
<p>Dear {{ user.username }},</p>
<p>To verify your email, please <a href="{{ base_url }}{% url 'users:activate' uidb64=uid token=token %}">click here</a>.</p>

<p>Alternatively, you can paste the following link in your browser's address bar:</p>
<p>{{ base_url }}{% url 'users:activate' uidb64=uid token=token %}</p>

<p>The link will expire in 30 minutes.</p>
<p>If you have not requested a verification email you can simply ignore this email.</p>
<p>See you there,</p>
<p>Daisy</p>
 
Kjo email është mjaft e thjeshtë. Ajo merr një kontekst të një përdoruesi, URL -në bazë për sitin dhe një ID të përdoruesit dhe shenjën të cilat përdoren për të verifikuar emailin e përdoruesit. Sigurohuni që të përcaktoni URL -në bazë në cilësimet.py para se të shkruajmë disa kod python për të dhënë shabllonin. Shkoni përpara dhe shtoni rreshtat e mëposhtëm në App/Settings.py, afër fillimit.

SITE_NAME = 'Django App'
PROTOCOL = 'https'
DOMAIN = 'example.com'

BASE_URL = PROTOCOL + '://' + DOMAIN
Përfundimisht, kur faqja juaj është e gatshme për Internet dhe ju e vendosni atë, ju do të dëshironi të përcaktoni domenin tuaj si emrin e domain që blini për të përfaqësuar faqen. Ky është emri që ju do të shkruani në Navbar për të hyrë në faqen tuaj. Tani për tani, ju mund të lini domain bosh ose të përdorni një mbajtës të vendit. Ju gjithashtu do të dëshironi të ndryshoni emrin e faqes në një emër që dëshironi t'i jepni faqes tuaj, për zgjedhjen tuaj. Para se të dërgojmë email, le të krijojmë një gjenerator të shenjave, në mënyrë që të kemi një shenjë të aktivizimit të llogarisë që nuk skadon kurrë. Ne mund ta bëjmë këtë duke ndërtuar dhe importuar një shenjë të aktivizimit të llogarisë që duket si më poshtë. Redakto skedarin:

nano users/tokens.py
Shtoni kodin e mëposhtëm:

from django.contrib.auth.tokens import PasswordResetTokenGenerator
import six
class TokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        return (
            six.text_type(user.pk) + six.text_type(timestamp)
        )
account_activation_token = TokenGenerator()
unsubscribe_token = TokenGenerator()
Ky gjenerator themelor i shenjave gjeneron një shenjë që ne mund ta dërgojmë përdoruesin në një URL dhe përdoruesi mund të përdorë për të verifikuar emailin e tyre dhe për të aktivizuar llogarinë e tyre. Tjetra, le të shohim se si të dërgojmë një email. Duke përdorur Nano, modifikoni përdoruesit/email.py.

nano users/email.py
Dërgimi i Verifikimit Email HTML do të duket kështu:

from django.contrib.auth import get_user_model
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes
from django.core.mail import EmailMultiAlternatives
from django.shortcuts import render
from .tokens import account_activation_token
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.template import Template, Context
from django.conf import settings
import traceback

def send_verification_email(user):
    User = get_user_model()
    mail_subject = '[{}] Activate your account.'.format(settings.SITE_NAME)
    html_message = render_to_string('users/verification_email.html', {
        'user': user,
        'domain': settings.DOMAIN,
        'protocol': 'https',
        'uid': urlsafe_base64_encode(force_bytes(user.pk)),
        'token': account_activation_token.make_token(user),
    })
    send_html_email(user, mail_subject, html_message)
Kjo është mjaft e thjeshtë. Ne importojmë funksionet që na duhen për të dërguar emailin, e japim emailin me shabllone, dhe cilësimet tona, dhe pastaj e përcaktojmë emailin me emrin e shabllonit dhe i dërgojmë përdoruesit duke përdorur një funksion. Do të vini re që ne nuk e kemi përcaktuar funksionin për të dërguar postën, Send_HTML_EMAIL, megjithatë, kështu që le ta shkruajmë këtë më poshtë kodin që ne i kemi shtuar tashmë përdoruesve/email.py.py

def send_html_email(user, mail_subject, html_message):
    to_email = user.email
    username = user.username
    if to_email == '':
        return None
    unsub_link = settings.BASE_URL + user.profile.create_unsubscribe_link()
    html_message = html_message + "<p><a href=\"" + unsub_link +  "\" + title=\"Unsubscribe from " + settings.SITE_NAME + " emails\">Unsubscribe</a></p></body></html>"
    msg = EmailMultiAlternatives(mail_subject, strip_tags(html_message), settings.DEFAULT_FROM_EMAIL, [to_email], headers={'List-Unsubscribe' : '<' + unsub_link + '>'},)
    msg.attach_alternative(html_message, "text/html")
    profile = user.profile
    try:
        msg.send(fail_silently=False)
        if not profile.email_valid:
            profile.email_valid=True
            profile.save()
    except:
        profile.email_valid=False
        profile.save()
Kjo është pak më komplekse, dhe ne nuk jemi të gatshëm ta ekzekutojmë të gjithë këtë kod akoma. Vini re se ne po përcaktojmë një Unsub_Link, lidhja që përdoruesi mund të përdorë për të çabonuar nga postat elektronike. Kjo është e rëndësishme, sepse përdoruesit do të duhet të jenë në gjendje të heqin dorë nga postat tona elektronike, përveç nëse duan t'i shohin ato, në çdo kohë. Ne gjithashtu shtojmë një alternative të tekstit për mesazhin tonë, i cili është mesazhi HTML i zhveshur nga etiketat HTML. Së fundmi, ne kontrollojmë nëse emaili i dërguar, dhe nëse nuk ka, ne shënojmë në profilin e përdoruesit që emaili i tyre nuk është i vlefshëm. Le të kthehemi te modelet e përdoruesit, në mënyrë që të mund ta bëjmë të gjithë punën. Ne duhet të përcaktojmë një funksion për të gjeneruar një lidhje për të çabonuar, dhe për të përcaktuar një fushë Boolean për të shënuar se emaili i përdoruesit nuk është i vlefshëm. Së pari, shtoni importet e mëposhtme në krye të përdoruesve/modeleve.py

nano users/models.py

# …
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse
Tjetra, le të shtojmë funksione në modelin e përdoruesit për të bërë shenjën dhe për të kontrolluar shenjën e përdorur për të aktivizuar emailin, si dhe fushën për të ruajtur nëse përdoruesi po merr me sukses postën e tyre. Në përdoruesit/modelet.py përsëri, shtoni kodin e mëposhtëm në fund të modelit (kodi i theksuar)

# …
    email_valid = models.BooleanField(default=True)
    
    def make_token(self):
        return TimestampSigner().sign(self.user.username)

    def check_token(self, token):
        try:
            key = '%s:%s' % (self.user.username, token)
            TimestampSigner().unsign(key, max_age=60 * 60 * 24 * 30) # E vlefshme për 30 ditë
        except (BadSignature, SignatureExpired):
            return False
        return True

    def create_unsubscribe_link(self):
        username, token = self.make_token().split(":", 1)
        return reverse('users:unsubscribe', kwargs={'username': username, 'token': token,})
Kjo është mjaft e thjeshtë, ne përdorim një TimestampSigner, i cili është një mjet themelor i kriptografisë, për të krijuar një shenjë e cila do të skadojë pas një kohe të caktuar, dhe ne gjithashtu përdorim një funksion tjetër për të kontrolluar nëse është i vlefshëm. Ne i përdorim këto shenja dy herë, një herë për të verifikuar emailin, dhe një herë për një lidhje të çabonimit. Tani që i kemi këto, e fundit e punës që do të duhet të bëjmë është në pikëpamjet. Brenda përdoruesve/Views.py, le të shtojmë pamje për të verifikuar adresën e postës elektronike dhe për të çabonuar.

nano users/views.py
Së pari, shtoni importet e mëposhtme. Unë hodha në disa shtesë, kështu që ne nuk do të duhet të importojmë më shumë artikuj përsëri më vonë.

from django.contrib.auth import logout
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.models import User
from django.utils.encoding import force_str
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
import json
import requests
import datetime, traceback
from django.contrib import messages
from .models import Profile
from django.utils import timezone
from django.views.decorators.cache import never_cache
from .email import send_verification_email # Sigurohuni që të importoni funksionin e dërgimit të postës elektronike të verifikimit
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.utils.decorators import method_decorator
from django.http import HttpResponseRedirect
from django.conf import settings
from django.utils import timezone
import datetime
import pytz
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_decode
from .tokens import account_activation_token
Ju tashmë mund të keni disa nga këto importe, por nuk dëmton t'i përsërisni ato. Ju do të duhet të importoni funksionin e dërgimit të postës elektronike të verifikimit, si dhe llogari_activation_token nga përdoruesit.tokens, midis importeve të tjera. Tani, në fund të skedarit, shtoni kodin e mëposhtëm:

def unsubscribe(request, username, token):
    user = get_object_or_404(User, username=username)
    if((request.user.is_authenticated and request.user == user) or user.profile.check_token(token)):
        # çabonohuni
        profile = user.profile
        profile.subscribed = False
        profile.save()
        return render(request, 'users/unsubscribe.html')
    # Përndryshe ridrejtoni në faqen e hyrjes
    messages.warning(request,f'Your unsubscribe link has expired. Please log in to unsubscribe.')
    next_url = reverse('users:unsubscribe', kwargs={'username': username, 'token': token,})
    return HttpResponseRedirect('%s?next=%s' % (reverse('login'), next_url))

def activate(request, uidb64, token):
    try:
        uid = force_str(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except(TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None
    ip = get_client_ip(request)
    if user is not None and account_activation_token.check_token(user, token):
        user.profile.email_verified = True
        user.profile.save()
        user.save()
# SendWelComeMail (Kërkesa, Përdoruesi)
        messages.success(request, f'Thanks for confirming your email! You can now log into your account, and a welcome email has been sent to you.')
        return redirect(user.profile.create_face_url())
    else:
        messages.success(request, f'Your activation link has expired. Please request a new activation link.')
        return redirect('verify:verify')

def resend_activation(request):
    if request.method == 'POST':
        form = ResendActivationEmailForm(request.POST)
        email = request.POST['email']
        try:
            user = User.objects.get(email=email)
            send_verification_email(user)
            messages.success(request,'Your verification email sent. Please click the link in your email to verify your account.')
            return redirect(reverse('verify:verify'))
        except:
            messages.warning(request,f'Your email is not correct. Please try again.')
    else:
        form = ResendActivationEmailForm()
    return render(request,'users/resend_activation.html',{'form': form, 'title': 'Resend Activation', 'small': True})
Ky është shumë kod. Le ta zbërthejmë. Funksioni i parë, i pastër dhe i thjeshtë, e përshkruan përdoruesin nga lista e postave. Funksioni i dytë aktivizon emailin e tyre, dhe ju do të vini re se shtova një funksion të komentuar, SendWelComeMail. Jeni të mirëpritur të përdorni një shabllon emaili dhe përkufizimin e funksionit për të dërguar një email të mirëseardhur, unë thjesht nuk e kam akoma. Funksioni i fundit në të cilin hodha është i rëndësishëm, sepse postat elektronike të aktivizimit skadojnë. Prandaj, do të na duhet të rivendosim emailin e aktivizimit disa nga koha. Ne mund të përdorim një formë themelore për këtë, dhe të thërrasim funksionin për të dërguar emailin e verifikimit. Para se ta bëjmë këtë, le të sigurohemi që po dërgohet në radhë të parë, duke shtuar një telefonatë funksioni në pamjen e regjistrit. Shtoni këtë linjë pak para ridrejtimit në pamjen e regjistrit, regjistri def, në përdoruesit/pamjet.py.

nano users/views.py

# … (Pas) Regjistri (Kërkesa) DEF::
            send_verification_email(user)
# … (Para) Ridrejtimi (
Ju nuk keni nevojë të shtoni rreshtat e parë dhe të fundit në atë copë kodi, thjesht sigurohuni që pamja e regjistrit të dërgojë emailin e verifikimit tek përdoruesi. Duhet të duket kështu:

# … Shuma
from .forms import UserRegisterForm

def register(request):
    if request.method == “POST”:
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            send_verification_email(user) # Sigurohuni që të shtoni këtë linjë!
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Tani, do të duhet të shtojmë një formë për të rivendosur emailin e aktivizimit. Në përdoruesit/format.py, shtoni formularin e mëposhtëm:

# … (Shumat)
class ResendActivationEmailForm(forms.Form):
    email = forms.EmailField(required=True)
Do të na duhet gjithashtu një shabllon që korrespondon me këtë formular të aktivizimit të emailit. Le ta shtojmë këtë shabllon. Redaktoni skedarin:

nano users/templates/users/resend_activation.html
Tjetra, shtoni kodin e mëposhtëm në skedar.

{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Resend activation email</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-secondary" type="submit">Resend activation email</button>
            </div>
        </form>
{% endblock %}
Whew, kjo është shumë! Tani, kur vendosim kodin në serverin tonë, ne do të jemi në gjendje të dërgojmë email HTML dhe të aktivizojmë llogaritë e përdoruesit me një klikim në email. Ne gjithashtu mund të dëshirojmë të dërgojmë një email të thjeshtë të mirëseardhjes, kështu që le të shohim se si ta bëjmë atë. Kthehu në përdoruesit/email.py, shtoni kodin e mëposhtëm:

def sendwelcomeemail(user):
    User = get_user_model()
    html = open('{}/users/welcome_email.html'.format(settings.BASE_DIR)).read()
    subject = 'Welcome to ' + settings.SITE_NAME + ', {{ username }}!'
    template = Template(html)
    subjtemplate = Template(subject)
    context = Context({'username': user.username, 'base_url': settings.BASE_URL, 'model_name': 'Daisy Holton, 'site_name': settings.SITE_NAME})
    renderedtemplate = template.render(context)
    subjcontext = Context({'username': user.username})
    subjrenderedtemplate = subjtemplate.render(subjcontext)
    send_html_email(user, subjrenderedtemplate, renderedtemplate)
Gjithashtu, do të na duhet një shabllon për të dhënë të gjitha këto informacione. Në faqen time të internetit, shablloni duket si më poshtë, por ju jeni të mirëpritur ta formatoni atë megjithatë ju pëlqen.
 
<html>
<body>
<h3>Welcome to {{ site_name }}</h3>
<p>Hello {{ username }},</p>
<p>We are happy to see you here! Thank you for joining {{ site_name }} and being a part of the fun. To get started, here are a few things you can do after you verify your identity.</p>
<ol>
    <li><a href="{{ base_url }}/" title="Use the app">Use the app</a>. This is the main page of {{ site_name }}</li>
    <li><a href="{{ base_url }}/feed/profile/Clementine/" title="See my profile">Visit my private {{ site_name }} profile</a>. This is a page for anyone wanting to get to know me.</li>
    <li><a href="{{ base_url }}/feed/profiles/" title="See all profiles currently on the site">More profiles</a>. You can find these people on the site, and see their content.</li>
    <li><a href="{{ base_url }}/feed/all/" title="See everything on {{ site_name }}">See all posts here</a>. This is the private front page of {{ site_name }}.</li>
</ol>
<p>There is even more on the site, so feel free to visit and see what you find. You can share the site with any of the social buttons on each page. I hope you enjoy your time with {{ site_name }}! Thanks for being here.</p>
<p>With much love,</p>
<p>{{ model_name }}</p>
<a href="{{ base_url }}" title="{{ site_name }}">{{ base_url }}</a>
 
Vini re se ne nuk kemi etiketa përmbyllëse të trupit ose HTML, sepse i shtojmë këto kur shtojmë lidhjen HTML Unsubscrib. Këto janë të rëndësishme, por ne nuk duam t'i përcaktojmë ato dy herë. Pra, çfarë është tjetër? Ne kemi bërë një rrugë të gjatë. Në të vërtetë, ne duhet të jemi të gatshëm për të vendosur faqen në një server. Ne mund të shtojmë dekoratorin @Login_Required dhe t'i bëjmë të sigurt pikëpamjet tona, të marrim regjistrime të përdoruesit, të dërgojmë email në përputhje dhe informacione për cache, që është baza e asaj që duhet të bëjë një faqe në internet për të qëndruar e rëndësishme. Ne do të shtojmë disa karakteristika më të dobishme, dhe pastaj do të ndërtojmë një bazë për vendosjen e kodit tonë në një server të largët, vendosjen e një serveri me postë, konfigurimin e domenit dhe filtrat për ta bërë faqen tonë të sigurt dhe të përshtatshme. Do të na duhet gjithashtu një pamje e rivendosjes së fjalëkalimit, kështu që le ta shtojmë atë me të vërtetë të shpejtë. Pamja e rivendosjes së fjalëkalimit të Django është thyer në disa funksione, por ne do të shohim se si të shkruajmë pamjen tonë, modelin e postës elektronike, format dhe modelet e URL -së. Ja se si duket pamja, në përdoruesit/pamjet.py

# ... shuma
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.forms import SetPasswordForm
from django.utils.http import urlsafe_base64_decode

def password_reset(request, uidb64, token):
    user = get_object_or_404(User, id=urlsafe_base64_decode(uidb64))
    if request.method == 'POST':
        form = SetPasswordForm(user, request.POST)
        if form.is_valid() and default_token_generator.check_token(user, token):
            form.save()
            messages.success(request, 'Your password has been reset.')
        elif not form.is_valid():
            messages.warning(request, 'Your passwords do not match, or do not meet the requirements. Please try again.')
            return redirect(request.path)
        else:
            messages.warning(request, 'Your password reset link has expired. Please create a new one.')
        return redirect(reverse('users:login'))
    return render(request, 'users/password_reset_confirm.html', {
        'title': 'Reset your Password',
        'form': SetPasswordForm(user)
Kjo formë është ndërtuar në Django, por do të na duhet një shabllon për të konfirmuar rivendosjen e fjalëkalimit, përdoruesit/shabllonet/përdoruesit/fjalëkalimin_reset_confirm.html
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Reset Password</button>
            </div>
        </form>
{% endblock content %}
 
Ne gjithashtu kemi një shabllon për të dërguar një email për rivendosjen e fjalëkalimit, me një formë të thjeshtë, në përdoruesit/shabllonet/përdoruesit/fjalëkalimin_reset.html
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Request Password Reset</button>
            </div>
        </form>
{% endblock content %}
 
Modeli për vetë emailin është i thjeshtë, është një skedar themelor HTML që bën një lidhje për të rivendosur fjalëkalimin, në përdoruesit/shabllonet/përdoruesit/fjalëkalimin_reset_email.html. Django do të interpretojë automatikisht këtë skedar.
 
<h1>Uglek - Reset Your Password</h1>
<p>Hello,</p>
<p>To reset your password, please <a href="https:/uglek.com{% url 'password_reset_confirm' uidb64=uid token=token %}">click here</a>.</p>
<p>Alternatively, you can paste the following link into your browser:</p>
<p>https://uglek.com{% url 'password_reset_confirm' uidb64=uid token=token %}</p>
<p>If you have not requested a password reset you can simply ignore this email.</p>
<p>Thanks for joining us,</p>
<p>Daisy</p>
 
Do të na duhen edhe dy shabllone të tjera. E para është të konfirmoni që emaili është dërguar. Pamjet për këto janë tashmë në Django, kështu që ne vetëm duhet t'i adresojmë ato në URLS.py. Ky shabllon është i vendosur në përdoruesit/shabllonet/përdoruesit/fjalëkalimin_reset_done.html
 
{% extends 'base.html' %}
{% block content %}
  <div class="media-body">
    <div class="alert alert-info">
        An email has been sent with instructions to reset your password.
    </div>
  </div>
{% endblock content %}
 
Dhe së fundi, për të konfirmuar që rivendosja e fjalëkalimit është e plotë, përdoruesit/shabllonet/përdoruesit/fjalëkalimin_reset_complete.html
 
{% extends 'base.html' %}
{% block content %}
 <div class="media-body">
    <div class="alert alert-info">
        Your password has been set.
    </div>
    <a href="{% url 'users:login' %}">Sign In Here</a>
  </div>
{% endblock content %}
 
Tani, ne kemi nevojë për modele URL për këto pamje. Në përdoruesit/urls.py, shtoni modelet e mëposhtme të URL -së:

urlpatterns = [
    # ... URL -të e mëparshme këtu
    path('password-reset/',
         auth_views.PasswordResetView.as_view(
             template_name='users/password_reset.html',
             html_email_template_name='users/password_reset_html_email.html'
         ),
         name='password_reset'),
    path('password-reset/done/',
         auth_views.PasswordResetDoneView.as_view(
             template_name='users/password_reset_done.html'
         ),
         name='password_reset_done'),
    path('password-reset-confirm/<uidb64>/<token>/',
         auth_views.PasswordResetConfirmView.as_view(
             template_name='users/password_reset_confirm.html'
         ),
         name='password_reset_confirm'),
    path('password-reset-complete/',
         auth_views.PasswordResetCompleteView.as_view(
             template_name='users/password_reset_complete.html'
         ),
         name='password_reset_complete'),
]
Katër shabllone, kjo është shumë! Por tani ne mund të jemi të sigurt që të jemi në gjendje të rivendosim fjalëkalimin e përdoruesit sa herë që na nevojitet, të gjithë nga shfletuesi i uebit. E kuptoj që kjo është shumë kod. Nëse ju duket pak mbi kokën tuaj, kjo është në rregull. Ju do të përmirësoheni, mirëkuptimi juaj do të përmirësohet, dhe do të bëheni shumë më kompetent me kodin shumë shpejt. Nëse jeni plotësisht të humbur, unë rekomandoj të ktheheni në këtë softuer më vonë pasi të keni punuar në një kurs të vetë-ritmit të mësoni të kodoni kursin në internet. Këto zakonisht janë të lira për të filluar, dhe do t'ju udhëzojnë nëpër gjithçka që ju nevojitet për të qenë i suksesshëm kur të ktheheni në këtë projekt. Nëse ndjeheni sikur jeni gati për të vazhduar, lexoni më tej, ne do të mbulojmë vendosjen e kodit tuaj në një server të largët dhe vendosjen e një serveri me postë, si dhe automatizimin e vendosjes tuaj duke përdorur Bash, në mënyrë që të krijoni gjithmonë një projekt të ri me Disa komanda të thjeshta. Gjëja e fundit që duhet të bëjmë para se të vendosemi në një server të largët është ta bëjmë faqen tonë pak më të sigurt. DoVini re se pamja e hyrjes merr vetëm një emër përdoruesi dhe fjalëkalim, dhe nuk ka vërtetim shumë faktorësh ose një kod kohor. Ky është një rregullim i lehtë, dhe me të njëjtin kod, ne mund ta bëjmë faqen tonë të dërgojë mesazhe me tekst dhe madje të jetë i përgjegjshëm ndaj mesazheve me tekst të dërguara në server. Për të filluar, ne do të kthehemi në modelet e përdoruesit dhe do të shtojmë një nënshkrues Timestamp që do të përfaqësojë çdo hyrje. Ne gjithashtu do të shtojmë një identifikues unik, rrotullues në modelin e përdoruesit që do të përdoret për të shtuar siguri shtesë në hyrjen tonë. Redaktimi i modeleve të përdoruesve, përdoruesve/modeleve.py, shtoni sa vijon

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
# Sigurohuni që të importoni UUID, nënshkruesin e afatit kohor dhe gjeneratorin e URL -së (Reverse)
import uuid
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name='profile')
    account_created = models.DateTimeField(default=timezone.now)
    last_seen = models.DateTimeField(default=timezone.now)
    can_login = models.DateTimeField(default=timezone.now)
    preferred_name = models.CharField(max_length=20,default='', null=True, blank=True)
    bio = models.TextField(blank=True, default='')
    # Shtoni këtë kod këtu
    uid = models.CharField(max_length=32, default=uuid.uuid4, null=True, blank=True)
    mfa_enabled = models.BooleanField(default=False)
    enable_mfa = models.BooleanField(default=False)
    phone_number = models.CharField(default='', null=True, blank=True, max_length=15)
    verification_code = models.CharField(default='', null=True, blank=True, max_length=15)
    verification_code_length = models.IntegerField(default=6)
    mfa_code_expires = models.DateTimeField(default=timezone.now)
    mfa_attempts = models.IntegerField(default=0)

    def make_auth_token(self):
        return TimestampSigner().sign(self.uid)

    # Dhe shtoni këtë funksion
    def create_auth_url(self):
        username, token = self.make_auth_token().split(":", 1)
        return reverse('users:mfa', kwargs={'username': username, 'token': token,})

    def check_auth_token(self, token):
        try:
            key = '%s:%s' % (self.uid, token)
            TimestampSigner().unsign(key, max_age=60 * settings.AUTH_VALID_MINUTES) # E vlefshme për 3 minuta
        except (BadSignature, SignatureExpired):
            return False
        return True
Sigurohuni që përdoruesit/modelet tuaja.py të duket kështu, përveç komenteve (kodi në linjat me #). Duke e prishur këtë, është e thjeshtë. Ne kemi disa importe, një TimestampSigner i cili është një mjet kriptografik që mund të gjenerojë një kod të sigurt dhe ta verifikojë atë në mënyrë që të sigurohemi që është i vlefshëm, është përdorur vetëm një herë, dhe jo më i vjetër se një numër i caktuar sekondash. Ne gjithashtu përdorim një UUID, i cili është një identifikues unik që identifikon përdoruesin tonë në nënshkrimin e shenjës, dhe në URL ku shenja i dërgohet përdoruesit. Ne do ta përdorim këtë kriptografi themelore për të ndërtuar një pamje të vërtetimit me dy faktorë. Para se të bëjmë ndonjë gjë tjetër, le të ekzekutojmë migrimet në mënyrë që modelet tona të përdoruesit të azhurnohen. Në direktorinë me menaxhimin.py, ekzekutoni komandat e mëposhtme për të bërë dhe kompletuar migrimet.

source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Kjo është e rëndësishme sepse sa herë që bëjmë ndryshime në modele, do të duhet të krijojmë tabelat dhe të azhurnojmë bazën e të dhënave me parazgjedhje para se të mund të përdorim modelet. Tjetra, le të improvizojmë pamjen tonë të hyrjes për të ridrejtuar në një pamje sekondare të vërtetimit. Në përdoruesit/pamjet.py, hiqni funksionin e hyrjes dhe ridrejtoni në URL që sapo kemi krijuar në modelet e përdoruesit.

# … Importet

def login(request):
    if request.method == “POST”:
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user and user.profile.can_login < timezone.now(): # Vini re se ne tani kontrollojmë nëse përdoruesi mund të regjistrohet
            # Hiqni funksionin auth_login që ishte këtu
            messages.success(request, 'Your password was accepted. Please continue.')
            if user.profile.mfa_enabled:
                return redirect(user.profile.create_auth_url()) # Shënim ne ridrejtojmë në një URL të re këtu
            else: # Nëse përdoruesi nuk po përdor vërtetimin shumë-faktor, thjesht regjistrohuni ato.
                auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                return redirect('feed:feed')
        else: # Nëse hyrja nuk ishte e suksesshme,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Kjo është pjesa ku ne azhurnojmë profilin e përdoruesve
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Kështu që ata nuk mund të regjistrohen përsëri për disa sekonda
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Pra, kjo është mjaft e thjeshtë, ne tani kemi një mënyrë për të ridrejtuar në pamjen e autentifikimit të dy faktorëve kur e krijojmë atë. Ne gjithashtu kemi një kthim në rast se përdoruesi nuk ka shtuar një numër telefoni. Ne do të shtojmë një pamje themelore për të shtuar një numër telefoni së shpejti dhe do të identifikohemi së shpejti me një mesazh me tekst. Së pari, na duhet një mënyrë e thjeshtë për të dërguar një mesazh me tekst nga kodi ynë. Për ta bërë këtë, ne mund të zgjedhim nga një numër i API -ve, por më i lehtë për mendimin tim është Twilio. Ata gjithashtu ofrojnë çmime të mira për projekte më të vogla, si dhe zbritje me shumicë. Krijoni një llogari në Twilio.com, plotësoni disa detaje në lidhje me projektin tuaj, blini një numër telefoni dhe kopjoni çelësat tuaj API në cilësimet tuaja. Pastaj, shtoni këtë kod nën një skedar të ri, përdoruesit/sms.py.

nano users/sms.py

# Importoni të gjitha paketat e nevojshme
from django.utils import timezone
import random
import datetime
from django.conf import settings
from feed.middleware import get_current_request
from django.contrib import messages
import traceback

account_sid = settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
source_phone = settings.PHONE_NUMBER

# Ky kod dërgon tekstin me Twilio
def send_text(target_phone, text):
    from twilio.rest import Client
    try:
        client = Client(account_sid, auth_token)
        if len(target_phone) >= 11:
            message = client.messages.create(
                to=target_phone,
                from_=source_phone,
                body=text)
    except:
        print(traceback.format_exc())

# Një funksion ndihmës për të marrë një numër me kaq shumë shifra
def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

# Dërgoni tekstin për të verifikuar përdoruesin
def send_verification_text(user):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    user.profile.verification_code = code
    user.profile.mfa_code_expires = timezone.now() + datetime.timedelta(minutes=3)
    user.profile.save()
    send_user_text(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)))

# Dërgoni një përdoruesi çdo tekst me këtë funksion
def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

# Vlerësoni kodin me këtë funksion
def check_verification_code(user, code):
    user.profile.mfa_attempts += 1
    result = user.profile.verification_code != None and code != '' and user.profile.verification_code == code and user.profile.mfa_code_expires > timezone.now() and user.profile.mfa_attempts <= 3
    if user.profile.mfa_attempts < 3 and result:
        user.profile.verification_code_length = 6
    elif user.profile.mfa_attempts > 2 and not result:
        user.profile.verification_code_length = 8
    user.profile.save()
    return result

# Vlerësoni kohën
def check_verification_time(user):
    result = user.profile.mfa_code_expires > timezone.now()
    return result
Sigurohuni që të ndryshoni cilësimet tuaja në mënyrë të përshtatshme, duke shtuar këto rreshta me çelësat tuaj:

# Sigurohuni që t'i kopjoni këto nga pulti juaj i Twilio
TWILIO_ACCOUNT_SID = “<your sid>”
TWILIO_AUTH_TOKEN = “<your token>”
PHONE_NUMBER = “<your twilio phone number>”
SITE_NAME = “<Your site name>”
AUTH_VALID_MINUTES = 3 # Numri i minutave faqja TFA është aktive një herë e menjëhershme
Së pari, do të na duhen forma për pikëpamjet tona të vërtetimit të dy faktorëve. Redaktimi i përdoruesve/formave.py, shtoni kodin e mëposhtëm.

# … Shuma
from django import forms

# Një formë për të hyrë në numrin tonë të telefonit
class PhoneNumberForm(forms.Form):
    phone_number = forms.RegexField(regex=r'^\+?1?\d{9,15}$', error_messages = {'invalid': "Phone number must be entered in the format: '+999999999'. Up to 15 digits is allowed."})
    def __init__(self, *args, **kwargs):
        super(PhoneNumberForm, self).__init__(*args, **kwargs)
        self.fields['phone_number'].label = phone_number_label

# Një formë për vërtetimin
class TfaForm(forms.Form):
    code = forms.IntegerField(required=False)
    def __init__(self, *args, **kwargs):
        super(TfaForm, self).__init__(*args, **kwargs)
        self.fields['code'].widget.attrs.update({'autocomplete': 'off'})
    help_texts = {
        'code': 'Please enter the six digit code after sending it to your phone with the button above.'
    }
Tjetra, le të krijojmë pikëpamjet në përdoruesit/pamjet.py

# … Shuma
from django.http import HttpResponseRedirect
from .forms import PhoneNumberForm, TfaForm

def mfa(request, username, token):
    user = User.objects.filter(profile__uuid=username).first()
    if not user: return HttpResponseRedirect(reverse('verify:age') + '?next=' + request.GET.get('next') if request.GET.get('next') else '/go/' if request.user.is_authenticated and request.user.profile.vendor else '/' if request.user.is_authenticated else reverse('users:login'))
    user = get_object_or_404(User, profile__uuid=username)
    next = request.GET.get('next','')
    if not user.profile.mfa_enabled:
        if not check_verification_time(user):
            user.profile.mfa_enabled = False
            user.profile.enable_two_factor_authentication = True
            user.profile.phone_number = '+1'
            user.profile.save()
            print('Logging in user')
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
            messages.warning(request, 'Please enter a valid phone number and verify it with a code.')
            return redirect(reverse('users:mfa_onboarding'))
    if request.method == 'POST':
        form = TfaForm(request.POST)
        code = form.data['code']
        if code and code != '' and code != None:
            token_validated = user.profile.check_auth_token(token)
            p = user.profile
            is_verified = check_verification_code(user, int(code))
            p.mfa_authenticated = is_verified
            if token_validated:
                if is_verified:
                    user.profile.mfa_enabled = True
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                    p.verfication_code = None
                    p.uid = get_uuid()
                    p.save()
                    messages.success(request, 'You have been authenticated. Welcome.')
                    qs = '?'
                    for key, value in request.GET.items():
                        qs = qs + key + '=' + value + '&'
                    if next != '' and not (next.startswith('/accounts/logout/') or next.startswith('/accounts/login/') or next.startswith('/admin/login/') or next.startswith('/accounts/register/')):
                        return HttpResponseRedirect(ext)
                    elif next.startswith('/accounts/logout/') or next.startswith('/accounts/login/') or next.startswith('/accounts/register/'):
                        return redirect('feed:feed')
                    elif request.META.get('HTTP_REFERER', '/').startswith('/accounts/login/'):
                        return redirect(reverse('feed:feed'))
                    elif not next:
                        return redirect(reverse('feed:feed')
                    else:
                        return HttpResponseRedirect('feed:feed')
                else:
                    messages.warning(request, 'The code you entered was not recognized. Please try again.')
            elif not token_validated:
                messages.warning(request, 'The URL token has expired or was not recognized. Please try again.')
                logout(request)
                return redirect(reverse('users:login'))
            if p.mfa_attempts > 3:
                messages.warning(request, 'You have entered the incorrect code more than 3 times. please send yourself a new code.')
                p.verification_code = None
                p.save()
        elif user.profile.can_send_mfa < timezone.now():
            user.profile.mfa_attempts = 0
            user.profile.can_send_mfa = timezone.now() + datetime.timedelta(minutes=2)
            user.profile.save()
            send_verification_text(user)
            messages.success(request, "Please enter the code sent to your phone number. The code will expire in 3 minutes.")
        else:
            messages.warning(request, 'You are sending too many two factor authentication codes. Wait a few minutes before sending another code.')
    form = TfaForm()
    hide_logo = None
    if user.profile.hide_logo:
        hide_logo = True
    return render(request, 'users/mfa.html', {'title': 'Enter Code', 'form': form, 'xsmall': True, 'user': user, 'hide_logo': hide_logo, 'accl_logout': user.profile.shake_to_logout, 'preload': False})

@login_required
def mfa_onboarding(request):
    if request.method == 'POST':
        form = PhoneNumberForm(request.POST)
        request.user.profile.phone_number = form.data['phone_number'].replace('-', '').replace('(','').replace(')','')
        request.user.profile.mfa_enabled = True
        request.user.profile.enable_two_factor_authentication = True
        request.user.profile.save()
        messages.success(request, 'You have added a phone number to your account.')
        user = request.user
        return redirect(user.profile.create_auth_url())
    form = PhoneNumberForm(initial={'phone_number': request.user.profile.phone_number if request.user.profile.phone_number else '+1'})
    return render(request, 'users/mfa_onboarding.html', {'title': 'Enter your phone number', 'form': form, 'small': True})
Do të na duhen gjithashtu shabllone për të dyja këto pikëpamje. Le të shtojmë së pari modelin e MFA -së.

nano users/templates/users/mfa.html
Shtoni këtë kod HTML në shabllon
 
{% extends 'base.html' %}
{% block content %}
{% load app_filters %}
{% load crispy_forms_tags %}
        <form action="{{ request.path }}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}" method="POST">
            {% csrf_token %}
            <legend class="border-bottom mb-4">Enter Verification Code</legend>
            <p>Step 1: Send the code</p>
	    <i>Never share your code with anyone, as it can be used to access your account temporarily.</i>
	    <div class="form-group">
                <button class="btn btn-outline-primary" type="submit">Send code</button>
            </div>
	    <hr>
	    <p>Step 2: Enter the code</p>
            <fieldset class="form-group">
                {{ form|crispy }}
		<p>Press the enter button to send yourself the code at {{ user.profile.phone_number|securephone }}. Then, enter the code and press enter.</p>
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-secondary" type="submit">Enter code</button>
            </div>
        </form>
{% endblock %}
 
Kjo është goxha vetë -shpjeguese. Formulari dërgon ose një kod ose një kod bosh, dhe do të vini re në pamjen që ne dërgojmë kodin nëse marrim një kod bosh. Atëherë ne kemi vetëm dy butona të paraqitura, dhe në këtë mënyrë ne mund ta dërgojmë kodin me secilin buton. Tjetra, ne do të shtojmë një formë të thjeshtë për të shtuar një numër telefoni.

nano users/templates/users/mfa_onboarding.html
Shtoni html -in e mëposhtëm:
 
{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Set Up Two Factor Authentication</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-secondary" type="submit">Add phone number</button>
            </div>
        </form>
{% endblock %}
 
Kjo formë është shumë më e thjeshtë, thjesht e bën formën e numrit të telefonit që kemi krijuar dhe i lejon përdoruesit të shtojë një numër telefoni. Kjo duket vërtet mirë! Për sa kohë që gjithçka është e vendosur siç duhet, ne duhet të jemi në gjendje të dërgojmë mesazhe, dhe ta regjistrojmë përdoruesin me numrin e tyre të telefonit sa më shpejt që të shtojmë modelet e URL -së. Gjëja e fundit që duhet të vendosim është një pamje e profilit, në mënyrë që të sigurohemi që përdoruesi të mund të ndryshojë numrin e tyre të telefonit pa u regjistruar. Gjithashtu, përfundimisht ne do të dëshirojmë të shtojmë një opsion "Stop to Lue", në mënyrë që përdoruesi të mund të shkruajë me tekst "Ndaloni" për të hequr dorë nga mesazhet e ardhshme me tekst. Le të shtojmë një pamje të profilit tek përdoruesit/Views.py. Kjo pamje do të azhurnojë bio, email, emrin e përdoruesit dhe numrin e telefonit të përdoruesit, si dhe do të na lejojë të mundësojmë vërtetimin e shumë faktorëve. Së pari, do të na duhen dy forma të tjera në përdoruesit/format.py

# ... shuma
class UserUpdateForm(forms.ModelForm):
    email = forms.EmailField()
    class Meta:
        model = User
        fields = ['username', 'email']

phone_number_label = 'Phone number (no spaces, parenthesis \'(\' or dashes \'-\', numbers beginning with + only)'

class ProfileUpdateForm(forms.ModelForm):
    subscribed = forms.BooleanField(required=False)
    phone_number = forms.CharField(required=False)
    def __init__(self, *args, **kwargs):
        super(ProfileUpdateForm, self).__init__(*args, **kwargs)
    class Meta:
        model = Profile
        fields = ['bio', 'phone_number', 'enable_mfa', 'subscribed']
Tjetra, ne mund të krijojmë një pamje për të përdorur të dyja këto forma. Redaktoni përdoruesit/Views.py dhe shtoni në pamje.

# Shtoni këto importe
from .forms import UserUpdateForm, ProfileUpdateForm
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_exempt
from .models import Profile
from .mfa import send_user_text

@csrf_exempt
@never_cache
@login_required
def profile(request):
    if request.method == 'POST':
        u_form = UserUpdateForm(request.POST, instance=request.user)
        p_form = ProfileUpdateForm(request.POST,
                                       request.FILES,
                                       instance=request.user.profile)
        if u_form.is_valid() and p_form.is_valid():
            new_phone_number = p_form.data['phone_number']
            u_form.save()
            profile = p_form.save(commit=False)
            profile.phone_number = profile.phone_number.replace('-', '').replace('(','').replace(')','')
            profile.save()
            if new_phone_number != oldprofile.phone_number and oldprofile.phone_number and len(oldprofile.phone_number) >= 11:
                profile.mfa_enabled = True
                profile.save()
                send_text(oldprofile.phone_number, 'Your phone number has been updated to ' + new_phone_number + '. Please refer to texts on that phone to log in. If you didnt make this change, please call us. - {}'.format(settings.SITE_NAME))
            if profile.enable_two_factor_authentication and profile.phone_number and len(profile.phone_number) < 11:
                profile.enable_two_factor_authentication = False
                messages.success(request, f'Two factor authentication can\'t be activated without entering a phone number. Please enter a phone number to enable two factor authentication.')
            profile.save()
            if new_phone_number != oldprofile.phone_number and new_phone_number and len(new_phone_number) >= 11:
                send_user_text(request.user, 'You have added this number to {} for two factor authentication. You can now use your number for two factor authentication. If you didnt make this change, please call us. - {}'.format(settings.SITE_NAME, settings.DOMAIN))
                profile.mfa_enabled = True
                profile.mfa_code_expires = timezone.now() + datetime.timedelta(minutes=3)
                profile.save()
                return redirect(profile.create_auth_url())
            messages.success(request, f'Your profile has been updated!')
            print('Profile updated')
            return redirect('users:profile')
    else:
        u_form = UserUpdateForm(instance=request.user)
        p_form = ProfileUpdateForm(instance=request.user.profile, initial={'phone_number': request.user.profile.phone_number if request.user.profile.phone_number else '+1'})
    context = {
        'u_form': u_form,
        'p_form': p_form,
        'title':'Update Your Profile',
    }
    return render(request, 'users/profile.html', context)
Do të na duhet gjithashtu një shabllon për këtë pamje.

nano users/templates/users/profile.html
 
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load feed_filters%}
{% block content %}
	<h2>Edit Your Profile</h2>  
	<form method="POST" enctype="multipart/form-data" id="profile-form">
          {% csrf_token %}
          <fieldset class="form-group">
              <legend class="border-bottom mb-4 mt-4">Profile info</legend>
              {{ u_form|crispy }}
              {{ p_form|crispy }}
          </fieldset>
          <div class="form-group">
              <button class="btn btn-outline-info" type="submit">Update}</button>
          </div>
	</form>
        <p style="text-color: green;" class="hide" id="posted">Saved</p>

{% endblock content %}
{% block javascript %}
var form = document.getElementById('profile-form');
$('input').change(function(){
	var formdata = new FormData(form);
	$.ajax({
		url: window.location.href,
		type: "POST",
		data: formdata,
		processData: false,
		contentType: false,
		timeout: 1000 * 60,
                success: function(data) {
                  $(posted).removeClass("hide");
		  setTimeout(function() {
			$(posted).addClass("fade-hidden");
			setTimeout(function() {
				$(posted).addClass("hide");
				$(posted).removeClass("fade-hidden");
			}, 2000);
		  }, 2000);
                }
	});
});
{% endblock %}
 
Do të vini re që kjo është një formë mjaft e thjeshtë, por ka disa JavaScript në të që poston automatikisht përmbajtjen e formularit pasi ato azhurnohen. Kjo është e dobishme për të pasur, kështu që ju jeni në gjendje të bëni redaktime pa pasur nevojë të shtypni dorëzimin çdo herë. Tjetra, ne kemi nevojë për URL që përfaqësojnë të gjitha këto pikëpamje në përdoruesit e URL -së. Redaktoni përdoruesit/urls.py dhe shtoni këtë kod:

# … Kodi i mëparshëm, Importet
from django.urls import path
from . import views

app_name='users'

urlpatterns = [
# … Modelet e URL -së që kemi futur më parë, shtoni tre linjat e ardhshme
    path('mfa/<str:username>/<str:token>/', views.mfa, name='mfa'),
    path('mfa/onboarding/', views.mfa_onboarding, name='mfa_onboarding'),
    path('profile/', views.profile, name='profile'),
]
Tani është një kohë e mirë për të provuar projektin tonë. Por së pari, le të drejtojmë një rezervë tjetër.

backup
Dhe ekzekutoni serverin. Para se të vendosemi në një server Linux, është një ide e mirë për të mundësuar vërtetimin e dy faktorëve në llogari. Ne do ta bëjmë këtë duke shkuar në URL -në tonë të profilit,/përdoruesit/profilin/, dhe duke kontrolluar kutinë për të aktivizuar vërtetimin pas hyrjes në numrin tonë të telefonit, dhe pastaj të paraqisni formularin.

python manage.py runserver localhost:8000
Vizitoni faqen në internet duke shkuar në shfletuesin tuaj të internetit, unë jam duke përdorur Google Chrome në këtë shembull, dhe duke hyrë në URL https: // localhost: 8000/llogari/profil/ Ju do të jeni në gjendje të regjistroheni nëse është e nevojshme dhe të mundësoni vërtetimin e dy faktorëve. Ky projekt ka nevojë për një server për të ekzekutuar në mënyrë që të mund të dërgojë me të vërtetë postë. Por së pari, na duhet një mënyrë për të parë gabime. Do të vini re që nëse ekzekutoni serverin në modalitetin e debugimit, me cilësimet.Debug të barabartë me True, serveri tregon gabime automatikisht. Për të treguar gabime pa përdorur modalitetin e debugimit, i cili është i pasigurt në një server prodhimi, duhet të shtojmë një pamje për të. Gabimet më të rëndësishme që duhet të jemi në gjendje të trajtojmë janë: Gabim 500 - një problem me kodin tonë Gabim 404 - Një faqe që nuk u gjet (URL e thyer) Gabim 403 - një gabim i mohuar Le të shtojmë një aplikacion të ri për të trajtuar këto gabime, të quajtura gabime.

python manage.py startapp errors
Shtojeni këtë në cilësimet.py siç kemi bërë më parë, në vendosjen e instaluar_apps, dhe filloni duke shtuar referenca në disa pamje në aplikacion/urls.py, ku aplikacioni është emri i projektit tuaj django.

handler404 = 'errors.views.handler404'
handler500 = 'errors.views.handler500'
handler403 = 'errors.views.handler403'
Kjo është gjithçka që na nevojitet përveç pamjeve të gabimit, shablloneve dhe pak ndërmjetës. Le t'i përcaktojmë ato si të tilla:

from django.shortcuts import render, redirect
from django.http import HttpResponse
from stacktrace.models import Error
from errors.middleware import get_current_exception
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .logs import get_logs
from face.tests import is_superuser_or_vendor
from django.views.decorators.csrf import csrf_exempt
from errors.highlight import highlight_code
from django.shortcuts import redirect
from django.urls import reverse

# Krijoni pikëpamjet tuaja këtu.
@login_required
@user_passes_test(is_superuser_or_vendor)
def logs(request):
    logs = highlight_code(get_logs())
    return render(request, 'errors/live_error.html', {'title': 'Error Logs', 'pagetitle': 'Error Logs', 'notes': 'These are the recent error logs.', 'trace': logs, 'full': True})

@login_required
@user_passes_test(is_superuser_or_vendor)
def logs_api(request):
    logs = highlight_code(get_logs())
    return HttpResponse(logs)

@login_required
def handler404(request, exception):
    if not request.path.endswith('/'): return redirect(request.path + '/')
    return render(request, 'errors/error.html', {'title': 'Error 404', 'pagetitle': 'Error 404', 'notes': 'This page was not found on the server. It may have moved or been deleted.', 'is_404': True})

def handler500(request):
    print(get_current_exception())
    user = None
    if hasattr(request, 'user') and request.user and request.user.is_authenticated:
        user = request.user
    try:
        Error.objects.create(user=user, stack_trace=get_current_exception(), notes='Logged by 500 handler.')
    except: pass
    return render(request, 'errors/error.html', {'title': 'Error 500', 'pagetitle': 'Error 500', 'notes': 'There is a problem with the server, or with a request coming from you. Thank you for your understanding while we get things set up.', 'trace': get_current_exception()})

def handler403(request, exception):
    return render(request, 'errors/error.html', {'title': 'Error 403', 'pagetitle': 'Error 403', 'notes': 'You don\'t have permission to preform this request. If you think this is in error, please contact the server administrator.', 'is_403': True})

def handler400(request, exception):
    return render(request, 'errors/error.html', {'title': 'Error 400', 'pagetitle': 'Error 400', 'notes': 'This was a bad request.'})
Tjetra, le të përcaktojmë Middleware për të trajtuar këto gabime. Ne do ta bëjmë këtë duke shtuar së pari në Middleware_classes në Settions.py, me emrin e ndërmjetësit tonë.

MIDDLEWARE_CLASSES = [
    # ... Middleware e mëparshme
    'errors.middleware.ExceptionVerboseMiddleware,
]
Tjetra, le të shtojmë ndërmjetësin.

from threading import local
import traceback
from django.utils.deprecation import MiddlewareMixin

_error = local()

class ExceptionVerboseMiddleware(MiddlewareMixin):
    def process_exception(self, request, exception):
        _error.value = traceback.format_exc()

def get_current_exception():
    try:
        return _error.value
    except AttributeError:
        return None

def set_current_exception(exception):
    try:
        _error.value = exception
    except AttributeError:
        print('Attribute error setting exception.')
Ne shtojmë një funksion për të marrë përjashtimin aktual duke përdorur një lokal të fillesë, i cili na ndihmon të gjurmojmë çdo gabim në kodin tonë. Për sa i përket modeleve, na duhet vetëm një, sepse ne e përcaktojmë dinamikisht titullin në pamje. Modeli thjesht duhet të japë titullin dhe "gjurmën", gjurmët tona të gabimit nga konteksti.

nano errors/templates/errors/error.html
 
{% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 
Ky është modeli ynë më i thjeshtë akoma, por kjo është sa e lehtë është të shohësh gabimet në projektin tonë. Tjetra, le të çaktivizojmë Debugin në Cilësimet.

nano app/settings.py
Gjeni këtë linjë ku është vendosur në të vërtetë, dhe ndryshojeni në false

DEBUG = False
Shkoni përpara dhe rezervoni aplikacionin tani. Ne jemi të gatshëm të vendosim në një server të largët Linux, dhe të vazhdojmë të shtojmë veçori nga atje.

sudo backup
Para se ta postojmë këtë kod në një server, duhet të konsiderojmë se mund të ketë disa çështje me kodin. Në varësi të rastit, faqet që pranojnë informacione të postuara për ta do të kenë probleme me postimin e spamit dhe vështirësi në heqjen e spamit. Kjo nuk duhet të ndodhë menjëherë, por nëse po ndodh, ne më vonë do të shqyrtojmë se si të moderojmë automatikisht spam një skanim i ID e tyre ose një skanim biometrik, si një gjurmë gishti ose njohje e fytyrës. Duke parë shembullin e vërtetimit të shumë faktorëve që kemi ekzaminuar, në prodhim, gjërat mund të jenë të ndryshme. Vini re se si ne jemi duke kufizuar hyrjet për kufizimin e vlerësimit dhe shenjat e skadimit. Nëse robotët janë duke hyrë në një sit, vërtetimi i dy faktorëve mund të jetë më i vështirë pasi ato mund të hyjnë në kode në të njëjtën kohë përdoruesi. Për të luftuar këtë, le të përdorim një model në modelet e përdoruesit, duke deklaruar se si bashkëveprojmë me faqen kur jemiAutentifikimi i përdorimit të vërtetimit të shumë faktorëve me një numër telefoni. Ne gjithashtu do të shtojmë një mundësi për të vërtetuar me email. Filloni duke redaktuar modelet e përdoruesit me

nano users/models.py
Kjo është se si duhet të duket modeli që po shtojmë. Ne nuk kemi nevojë për asnjë metodë, thjesht ndryshore për të ruajtur një ID, përdoruesin, kohën e duhur, skadimin, gjatësinë dhe përpjekjet kundër çdo vërtetimi shumë faktorësh (një kod si 123456 i dërguar në një telefon ose email).

# Një shenjë themelore e përdorur për t'u identifikuar në faqen e internetit
class MFAToken(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='mfa_tokens')
    timestamp = models.DateTimeField(default=timezone.now)
    expires = models.DateTimeField(default=timezone.now)
    token = models.CharField(default='', max_length=100)
    length = models.IntegerField(default=6)
    attempts = models.IntegerField(default=0)
    uid = models.CharField(default=uuid.uuid4, max_length=100)
Le të shtojmë gjithashtu një privilegj për përdoruesin tonë, dhe ne do ta vendosim me dorë tani për tani, përpara se të migrojmë përfundimisht në regjistrimin e përdoruesve të privilegjuar automatikisht. Në modelet e përdoruesit, shtoni këtë rresht në profil:

    vendor = models.BooleanField(default=False)
Ashtu si me çdo ndryshim në bazën e të dhënave, ne duhet të bëjmë migrime dhe të migrojmë bazën e të dhënave sa herë që redaktojmë një skedar modele.py në Django. Mos harroni, për ta bërë këtë ne e përdorim së pari burimin (nëse nuk është përdorur tashmë pasi terminali ishte i hapur) dhe më pas Python menaxhon.py për të bërë migrimet dhe migruar.

cd project-directory-you-named # (Nëse është e nevojshme)
source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Tani për tani, ju mund të regjistroni çdo llogari që keni krijuar si shitës duke përdorur guaskën.

python manage.py shell
from users.models import Profile
p = Profile.objects.get(user__username='Charlotte')
p.vendor = True
p.save()
exit()
Tani, le të evoluojmë pamjen tonë të vërtetimit shumë faktor për të përdorur këtë shenjë. Së pari, ne duhet të modifikojmë shërbimet tona ndihmëse të MPJ -së. Duke përdorur nano,

nano users/mfa.py

from django.utils import timezone
import random
import datetime
from django.conf import settings
from feed.middleware import get_current_request
from django.contrib import messages
from .email import send_html_email
import traceback
from .models import MFAToken

account_sid = settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
source_phone = settings.PHONE_NUMBER

def send_text(target_phone, text):
    from twilio.rest import Client
    try:
        client = Client(account_sid, auth_token)
        if len(target_phone) >= 11:
            message = client.messages.create(
                to=target_phone,
                from_=source_phone,
                body=text + ' Text STOP to cancel.')
    except:
        messages.warning(get_current_request(), 'There was an error sending the message.')
        print(traceback.format_exc())

def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

def send_verification_text(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_user_text(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)))

def send_verification_email(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_html_email(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)), "<p>Dear {},</p><p>Your verification code for {} is {}. Thank you for using this code to secure your account.</p><h2>{}</h2><p>Sincerely, {}</p>".format(user.profile.name, settings.SITE_NAME, str(code), str(code), settings.SITE_NAME))

def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

def check_verification_code(user, token, code):
    token.attempts = token.attempts + 1
    profile = user.profile
    result = (token != None and code != '' and token.token == code and (token.expires > timezone.now()) and token.attempts <= settings.MFA_TOKEN_ATTEMPTS)
    if token.attempts < 3 and result:
        profile.verification_code_length = 6
    elif token.attempts > 1 and not result:
        profile.verification_code_length = profile.verification_code_length + 2
        if profile.verification_code_length > settings.MFA_TOKEN_LENGTH: profile.verification_code_length = settings.MFA_TOKEN_LENGTH
    token.save()
    profile.save()
    return result

# Autentifikoni përdoruesin duke përdorur emailin ose numrin e telefonit të tij
def mfa(request, username, usertoken):
    token = MFAToken.objects.filter(uid=username, expires__gt=timezone.now() + datetime.timedelta(seconds=30)).order_by('-timestamp').last() # Filtroni shenjën sipas vlerës së kaluar në URL (një UUID)
    if not token: token = MFAToken.objects.create(user=User.objects.filter(profile__uuid=username).first(), uid=username, expires=timezone.now() + datetime.timedelta(seconds=115)) # Nëse kjo seancë nuk është krijuar, krijoni atë
    user = User.objects.filter(id=token.user.id).first() # Merrni përdoruesin nga shenja
    if not user and request.user.is_authenticated: return redirect(reverse('feed:home')) # Nëse ato tashmë janë vërtetuar, regjistrohuni
    if not user: raise PermissionDenied() # Mohoni nëse nuk u gjet asnjë përdorues
    next = request.GET.get('next','')
    if not user.profile.enable_two_factor_authentication and user.is_active and user.profile.check_auth_token(usertoken, token): # Kontrolloni shenjën e autorit
        auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Hyni në përdorues nëse nuk janë regjistruar tashmë
        user.profile.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES) # Vendosni një skadim në vërtetimin e tyre shumë faktor
        user.profile.save()
        return HttpResponseRedirect(next if next != '' else reverse('landing:landing')) # Ridrejtoni përdoruesin në faqen tjetër
    if not user.profile.mfa_enabled: # Kontrolloni nëse është aktivizuar MFA
        if not check_verification_time(user, token): # Kontrolloni kohën
            user.profile.mfa_enabled = False # Pastroni numrin e telefonit
            user.profile.enable_two_factor_authentication = True # Aktivizo MPJ
            user.profile.phone_number = '+1' # Çaktivizo numrin e telefonit
            user.profile.save() # Ruani profilin
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Regjistrohuni në përdoruesin nëse MPJ -ja e tyre nuk është e aktivizuar
            messages.warning(request, 'Please enter a valid phone number and verify it with a code.')
            return redirect(reverse('users:mfa_onboarding'))
    if request.method == 'POST' and not fraud_detect(request, True): # Nëse kërkesa është një kërkesë POST
        form = TfaForm(request.POST) # Çastin e formularit
        code = str(form.data.get('code', None)) # Merrni kodin
        if code and code != '' and code != None: # Sigurohuni që nuk është bosh
            token_validated = user.profile.check_auth_token(usertoken) # Kontrolloni shenjën e autorit
            p = user.profile
            is_verified = check_verification_code(user, token, code) # Kontrolloni kodin
            p.mfa_authenticated = is_verified
            if token_validated: # Nëse gjithçka
                if is_verified: # Është në rregull
                    user.profile.mfa_enabled = True # Aktivizo MFA (nëse nuk është e aktivizuar tashmë)
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Hyni në përdorues
                    face = user.faces.filter(session_key=None).last() 
                    p.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES)
                    p.save()
                    messages.success(request, 'You have been authenticated. Welcome.')
                    qs = '?'
                    for key, value in request.GET.items(): # Ndërtoni një QueryString për parametrin tjetër (nëse ka)
                        qs = qs + key + '=' + value + '&'
                    if next != '' and not (next.startswith('/accounts/logout/') or  next.startswith('/accounts/login/') or next.startswith('/admin/login/') or next.startswith('/accounts/register/')):
                        return HttpResponseRedirect(next) # Ridrejtoj
                    elif next.startswith('/accounts/logout/') or next.startswith('/accounts/login/') or next.startswith('/accounts/register/'):
                        return redirect(reverse('/'))
                    elif request.META.get('HTTP_REFERER', '/').startswith('/accounts/login/'):
                        return redirect(reverse('/'))
                    elif not next:
                        return redirect(reverse('/'))
                    else:
                        return HttpResponseRedirect(reverse('verify:age') + '?next=' + request.META.get('HTTP_REFERER', '/'))
                else:
                    messages.warning(request, 'The code you entered was not recognized. Please try again.')
            elif not token_validated: # Nëse shenja ishte e pavlefshme
                messages.warning(request, 'The URL token has expired or was not recognized. Please try again.')
                logout(request)
                return redirect(reverse('users:login'))
            if p.mfa_attempts > 3: # Nëse do të kishte shumë përpjekje
                messages.warning(request, 'You have entered the incorrect code more than 3 times. please send yourself a new code.')
                p.verification_code = None
                p.save()
        elif user.profile.can_send_mfa < timezone.now():
            user.profile.mfa_attempts = 0
            user.profile.can_send_mfa = timezone.now() + datetime.timedelta(minutes=2)
            user.profile.save()
            if form.data.get('send_email', False): # Dërgoni emailin (ose tekstin)
                send_mfa_verification_email(user, token)
            else:
                send_verification_text(user, token)
            messages.success(request, "Please enter the code sent to your phone number or email. The code will expire in 3 minutes.")
        elif user.profile.can_send_mfa < timezone.now() + datetime.timedelta(seconds=115):
            messages.warning(request, 'You are sending too many two factor authentication codes. Wait a few minutes before sending another code.')
    form = TfaForm()
    hide_logo = None
    if user.profile.hide_logo:
        hide_logo = True
    if request.user.is_authenticated: return redirect(reverse('/'))
    # Jepni formularin (për kërkesat e marrjes)
    return render(request, 'users/mfa.html', {'title': 'Enter Code', 'form': form, 'xsmall': True, 'user': user, 'hide_logo': hide_logo, 'accl_logout': user.profile.shake_to_logout, 'preload': False, 'autofocus': request.method == 'POST'})
Kur po shtojmë në këtë kod, sigurohuni që të importoni funksionin për të dërguar një email. Në krye të skedarit, përdoruesi shikon (me importe të tjera), shtoni

from .mfa import send_verification_email as send_mfa_verification_email
Tani, ne duhet ta shkruajmë atë funksion para se të funksionojë ndonjë prej kësaj. Ai duhet të zgjasë funksionin tonë të dërgimit të postës elektronike, dhe thjesht t'i dërgojë një email përdoruesit me kodin e verifikimit.

nano users/mfa.py

def send_verification_email(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_html_email(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)), "<p>Dear {},</p><p>Your verification code for {} is {}. Thank you for using this code to secure your account.</p><h2>{}</h2><p>Sincerely, {}</p>".format(user.profile.name, settings.SITE_NAME, str(code), str(code), settings.SITE_NAME))
Pra, kjo funksionon shumë mirë, tani kemi një sistem të vërtetimit shumë faktorë që varet nga një numër telefoni ose email për t'u identifikuar. Por gjithashtu na duhet një mënyrë për të hequr, ose të paktën të fshehim përdoruesit që nuk po bashkëpunojnë me kushtet tona. Këta mund të jenë spammers, robotë ose kushdo që nuk do të thotë mirë për punën tonë. Shikoni një pamje që kam për monitorimin e përdoruesve në faqen time të internetit:

# shuma
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .tests import is_superuser_or_vendor # Ne do të duhet të krijojmë këtë provë

@login_required
@user_passes_test(is_superuser_or_vendor)
def users(request):
    # Merrni listën e përdoruesve
    new_today = User.objects.filter(is_active=True, date_joined__gte=timezone.now() - datetime.timedelta(hours=24)).count()
    new_this_month = User.objects.filter(is_active=True, date_joined__gte=timezone.now() - datetime.timedelta(hours=24*30)).count()
    subscribers = User.objects.filter(is_active=True, profile__subscribed=True).count()
    return render(request, 'users/users.html', { # Ktheni përdoruesit në një shabllon
        'title': 'All Accounts',
        'users': User.objects.all(),
        'new_today': new_today,
        'new_this_month': new_this_month,
        'subscribers': subscribers
    })
Vini re se ky kod përdor një test, do të na duhet ta deklarojmë këtë test në një skedar Tests.py dhe ta importojmë. Redaktimi i përdoruesve/tests.py, le të krijojmë testin.

def is_superuser_or_vendor(user):
    return user.profile.vendor or user.is_superuser
Kjo është në lidhje me modelin e përdoruesve/përdoruesve.html, i cili duket diçka si kjo:
 
{% extends 'base.html' %}
{% load app_filters %}
{% block content %}
<h1>All Registered Visitors</h1>
<p>{{ new_today|nts|capitalize }} new today, {{ new_this_month|nts }} new this month, {{ subscribers|nts }} subscribers, {{ users.count|nts }} total.</p>
<hr style="color: red;">
{% for user in users %}
{% include 'users/_user.html' %}
<hr style="color: blue;">
{% endfor %}
{% endblock %}
 
Vini re se shablloni përfshin një model tjetër, përdorues/_user.html. Kur përdorni një shabllon që ka një nën -tabelë dhe duke mos përdorur shtrihet, është një ide e mirë për të shtuar një nënvizim (_) përpara se emri i skedarit të zgjasë, në mënyrë që të dallohet shabllonet. Vini re se kjo është shumë Jinja, ju mund të mos i keni të përcaktuara të gjitha këto ndryshore. Por kjo është se si duket kodi im.
 
{% load app_filters %}
<div>
<img src="{{ user.profile.get_image_url }}" alt="@{{ user.profile.name }}'s profile photo" width="120" height="120" align="left" style="margin-top:5px; margin-right:10px; margin-bottom:10px; border-radius: 50%;"/>
    <div class="article-metadata">
      <p class="mr-2">@{{ user.username }} - {{ user.profile.name }} ({{ user.profile.preferred_name }})</p>
      <small class="text-muted">Last seen {{ user.profile.last_seen|date:"F d, Y" }} {{ user.profile.last_seen|time:"H:i" }}</small>
      <small class="text-muted">Joined on {{ user.profile.date_joined|date:"F d, Y" }} {{ user.profile.date_joined|time:"H:i" }}</small>
      <small>{{ user.email }}</small>
      {% if user.profile.phone_number %}<small><i class="bi bi-phone-fill"></i>{{ user.profile.phone_number }}</small>{% endif %}
      {% if user.verifications.last %}
      <small>'{{ user.verifications.last.full_name }}'</small>
      <small><i class="bi bi-123"></i> {{ user.verifications.last.document_number }}</small>
      <small><i class="bi bi-calendar-heart-fill"></i> {{ user.verifications.last.birthdate }}</small>
      <a href="{{ user|document_front }}" class="btn btn-sm btn-outline-primary" title="ID front"><i class="bi bi-person-badge-fill"></i> ID front</a>
      <a href="{{ user|document_back }}" class="btn btn-sm btn-outline-primary" title="ID back"><i class="bi bi-upc-scan"></i> ID back</a>
      {% endif %}
      <small># {{User.id}} </small>
      <small>{% if user.profile.subscribed %}Subscribed{% else %}Not subscribed{% endif %}</small>
    </div>
    {%if not user.is_superuser %}
    <div style="float: right;">{% include 'users/toggle_active.html' %}</div>
    {% endif %}
    {% autoescape off %}    
    <p class="article-content">{{ user.bio }}</p>
    {% endautoescape %}
    <hr>
    <p>{% if user.profile.identity_verified %}Verified user.{% else %}Unverified user.{% endif %} Verifications: {{ user.verifications.count|nts }}</p>
 
Ne gjithashtu kemi nevojë për një tjetër nën -paraburgim, TOGGLE_ACTIVE.HTML. Ky shabllon duhet të jetë një formë që na lejon të ndryshojmë nëse një përdorues është aktiv.
 
<form style="display: inline-block;" action="{% url 'users:toggle-user-active' user.id %}" method="POST" id="publishForm">
<button class="btn btn-sm btn-outline-danger" type="submit">{% if user.is_active %}<i class="bi bi-eye-fill"></i>{% else %}<i class="bi bi-eye-slash-fill"></i>{% endif %}</button>
</form>
 
Ne gjithashtu do të duhet të shtojmë një pamje për të ndryshuar aktivitetin e përdoruesit, dhe modelet e përshtatshme të URL -së. Ndërsa jemi në të, le të shtojmë një pamje për të fshirë një përdorues në rast se kemi nevojë për atë.

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
@login_required
@user_passes_test(is_superuser_or_vendor)
def toggle_user_active(request, pk):
    user = User.objects.get(id=pk)
    if request.method == 'POST':
        user.is_active = not user.is_active
        user.save()
    return HttpResponse('<i class="bi bi-eye-fill"></i>' if user.is_active else '<i class="bi bi-eye-slash-fill"></i>')


# Shuma
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import DeleteView

class UserDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = User
    success_url = '/' # Ridrejtimi i URL -së së Suksesit
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        return context

    def test_func(self): # Testoni nëse përdoruesi është superuser dhe ka leje për të fshirë
        user = self.get_object()
        if self.request.user != user and self.request.user.is_superuser:
            return True
        return False
Ndërsa kjo është praktike kur është e nevojshme, fshirja e një përdoruesi nuk duhet të jetë i nevojshëm shumicën e kohës, ne thjesht mund të ndërrojmë shikueshmërinë e përdoruesve që vizitojnë faqen nëse kemi nevojë për t'i hedhur poshtë. Modelet e URL -së që kemi shtuar duken kështu. Me Nano, modifikoni përdoruesit/urls.py dhe shtoni këto rreshta:

nano users/urls.py
Linjat duhet të shkojnë në listën e shtigjeve në pamjet e përdoruesit, përpara përfundimit "]" por pas fillimit "[".

# …
    path('user/<int:pk>/delete/', UserDeleteView.as_view(template_name='blog/user_confirm_delete.html'), name='delete-user'),
    path('user/<int:pk>/active/', views.toggle_user_active, name='toggle-user-active'),
# …
Tani, sigurohuni që të rezervoni faqen në mënyrë që të mund ta shkarkoni në serverin në internet që do të vazhdojmë të punojmë. Nga linja e komandës,

sudo backup
Tani faqja jonë është mbështetur. Pra, tani kemi disa veçori më të dobishme. Po në lidhje me foton e madhe këtu? Ky kod ende nuk është i arritshëm nga Interneti, ne nuk kemi ende server postar, dhe ne duhet të zgjerojmë aplikacionin tonë për të përfshirë një proces të verifikimit gjithëpërfshirës, ​​si dhe paraqitje të qetë për të na ndihmuar të eksplorojmë faqen, së bashku me protokollet e sigurta për vërtetimin e përdoruesve të privilegjuar . Ne do të arrijmë në të gjitha këto. Gjëja më e rëndësishme për tani thjesht do të jetë marrja e këtij kodi në internet, gjë që ne mund të bëjmë me vetëm disa linja të Bash në një server Ubuntu. Ju do të duhet të merrni me qira një server për këtë, megjithëse, përveç nëse keni një server në shtëpi dhe një pajtim në internet të biznesit që ju lejon të hapni porte. Unë personalisht e drejtoj faqen time në një HP Z440 që është instaluar në banesën time, por zakonisht është shumë më e lirë për nevojat themelore për të marrë me qira një server virtual privat (VPS). Mbani në mend se kodi që ne po ekzekutojmë tani është relativisht i hollë, do të duhet të mirëmbahet dhe të përmirësohet para se të jemiGati për të përdorur atë që kemi për të ndërtuar një produkt. Sigurohuni që të jeni të kujdesshëm se çfarë bëni me internetin, sigurohuni nëse e vendosni këtë faqe publikisht në internet në një server Linux, ju keni një plan për të bllokuar ndërveprimet e padëshiruara me faqen tuaj të internetit. Kjo ka të ngjarë të mos jetë problem në fillim, por ne do të shikojmë në një larmi zgjidhjesh për të luftuar këtë, përfshirë mësimin e makinerive, inteligjencën artificiale dhe vizionin e kompjuterit. Kur bëhet problem, shikoni më tej në këtë tekst për një zgjidhje. Për sa i përket marrjes me qira të një VPS, ka shumë vende që mund të shkoni. Google Cloud ka serverë VPS, Ionos, Kamatera, Amazon AWS, dhe më shumë ofrues ofrojnë zgjidhje të serverit cloud që do t'i përshtaten nevojave tona. Ju do të duhet të klikoni nëpër format e tyre dhe të zgjidhni një plan për të filluar. Ju mund të shkoni me një plan bazë me çdo ofrues, por sigurohuni që ofruesi ju lejon të hapni portet e serverëve të portit për të dërguar email (kjo duhet të jetë porti 587 dhe porti 25), disa ofrues i bllokojnë këto porte. Deri më tani kam pasurPërvoja EST me Ionos dhe Kamatera, të dy do të më lejojnë të dërgoj email të pakufizuar dhe çmimet e tyre janë mjaft të lira. Ju do të lidheni me serverin tuaj të ri mbi një protokoll të quajtur SSH ose Secure Shell, i cili ju lejon të ndërlidhni nga distanca me serverin saktësisht si kompjuteri juaj personal, nga kompjuteri juaj personal. Kur të vendosni serverin, ofruesi i pritjes ka të ngjarë të ju kërkojë të shtoni një çelës SSH, ose ata do t'ju japin një emër përdoruesi dhe fjalëkalimi. Keyelësi SSH është se si do të hyni në server nga linja e komandës për të modifikuar kodin. Përdorni opsionet më poshtë SSH-KeyGen për të gjeneruar një SSH

ssh-keygen
Ruani skedarin dhe e rishkruani nëse keni nevojë, është mirë të rrotulloni çelësat tuaj SSH nëse nuk keni tashmë. Tani, ju mund të përdorni komandën e mëposhtme për të parë çelësin tuaj SSH. Ju do të dëshironi ta kopjoni atë në serverin tuaj të largët, në mënyrë që ta përdorni për të vërtetuar.

cat ~/.ssh/id_rsa.pub
Nëse nuk keni qenë në gjendje të shihni një çelës SSH kur shtypni atë komandë (një varg i gjatë shifrash dhe shkronjash duke filluar me "ssh-rsa aaa"), provoni të gjeneroni një çelës RSA (ato janë më të sigurta, kështu që unë këshilloj t'i përdorni ato .) Kodi i mëposhtëm do të gjenerojë një çelës RSA SSH 4096 bit.

ssh-keygen -t rsa -b 4096
Krijoni një VPS që funksionon Ubuntu, megjithatë ju planifikoni ta bëni këtë. Pasi të keni krijuar një VPS duke klikuar nëpër format në faqen e internetit të ofruesve (kamatera.com, ionos.com ose të ngjashme), do të dëshironi të regjistroheni. Për ta bërë këtë, përdorni komandën SSH me adresën tuaj IP (adresa Kjo duket si xx.xx.xx.xx). Ju gjithashtu do të duhet të jeni të ndjeshëm ndaj emrit të paracaktuar të përdoruesit në serverin që kemi krijuar, për shembull, Ubuntu.

ssh ubuntu@XX.XX.XX.XX
Ju mund t'ju kërkohet një fjalëkalim, nëse ju kërkohet një fjalëkalim, futni atë brenda. Ne nuk do të përdorim emrin e paracaktuar të përdoruesit, kështu që le të fillojmë duke krijuar një përdorues të ri dhe duke shtuar një çelës SSH në llogarinë e tyre. Le të fillojmë duke shtuar një skedar të ri sshd_config, i cili i thotë serverit se si të përdorë SSH.

nano sshd_config

# Ky është skedari i konfigurimit të sistemit të serverit SSHD.  Shoh
# sshd_config (5) për më shumë informacion.

# Ky sshd u përpilua me shteg =/usr/lokale/sbin:/usr/lokale/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lojëra

# Strategjia e përdorur për opsione në SSHD_Config të paracaktuar të dërguar me të
# OpenSsh është të specifikojë opsionet me vlerën e tyre të paracaktuar ku
# e mundur, por lërini ata të komentuar.  Opsionet e pa komentuara tejkalojnë
# Vlera e paracaktuar.

# Porti 22
# Adresafamilja ndonjë
# Adresa e listës 0.0.0.0
# Dëgjoni Adresa ::

# HostKey/etj/ssh/ssh_host_rsa_key
# HostKey/etj/ssh/ssh_host_ecdsa_key
# HostKey/etj/ssh/ssh_host_ed25519_key

# Shifra dhe çelës
# REKEKYLIMIT PASRFUNDIM

# Prerje
# SYSLOGFACILITETI AUTH
# Informacione të Loglevel

# Autentifikimi:

# Logringracetime 2m
# Lejetrootlogin ndalon fjalën
# StriktModa Po
# Maxauthtries 6
# Maxessions 10

PubkeyAuthentication yes

# Presin që .ssh/autorizuar_keys2 të mos merret parasysh si parazgjedhje në të ardhmen.
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# Autorizohet

# AutorizohetKeysCommand asnjë
# AutorizohetKeysCommandUser Askush

# Që kjo të funksionojë, do t'ju duhet gjithashtu çelësa të hostit në/etj/ssh/ssh_nard_hosts
# HostBasedAutentication nr
# Ndryshoni në po nëse nuk besoni ~/.ssh/diln_hosts për
# Autentifikim host
# Injorues i njohur
# Mos lexoni skedarët e përdoruesit ~/.rhosts dhe ~/.Shosts
# Ingorererhosts po

# Për të çaktivizuar fjalëkalimet e qarta të tekstit të tunelizuara, ndryshoni në jo këtu!
PasswordAuthentication no
# Lejeptypasswords nr

# Ndryshoni në Po për të mundësuar fjalëkalimet e përgjigjes së sfidës (kini kujdes me të
# disa module dhe fije PAM)
KbdInteractiveAuthentication no

# Opsionet e Kerberos
# Kerberosauthentication nr
# Kerberosorlocalpasswd po
# Kerberosticketcleanup po
# Shufra kerberoscotted nr

# Opsionet GSSAPI
# GSSAPIAUNENTIKIMI NR
# Gssapicleanupcredentials po
# GssapistrictAcceptorCheck Po
# Gssapikeyexchange nr

# Vendoseni këtë në 'po' për të mundësuar vërtetimin e PAM, përpunimin e llogarisë,
# dhe përpunimi i seancave. Nëse kjo është e aktivizuar, autentifikimi PAM do
# lejohen përmes KBDinteractiveAautentifikimit dhe
# FjalëkalimiAutentifikimi.  Në varësi të konfigurimit tuaj PAM,
# Autentifikimi i PAM përmes KBDinteractiveAauthentication mund të anashkalojë
# Vendosja e "lejetrootlogin pa fjalëkalim".
# Nëse thjesht dëshironi të ekzekutohen llogaria Pam dhe Session Checks
# Autentifikimi PAM, pastaj aktivizoni këtë, por vendosni fjalëkaliminAutentifikim
# dhe KBDinteractiveAauthentication to 'Jo'.
UsePAM yes

# LejoniPorgorning Po
# ALLONITCPPORRIVE PO
# GatewayPorts nr
X11Forwarding yes
# X11DisplayOffset 10
# X11USELOCALHOST Po
# Permitty po
PrintMotd no
# Printlastlog po
# Tcpkeepalive po
# Përfundim
# Kompresimi i vonuar
# Intervali i Klientalit 0
# ClientaliveCountmax 3
# I perdorur në
# Pidfile /run/sshd.pid
# MAXSTARTUPS 10: 30: 100
# Pemitittunl nr
# Chrootdirectory asnjë
# Shtesa e versionit asnjë

# Asnjë shteg i paracaktuar i banderolës
Banner /etc/banner

# Lejoni klientin të kalojë variablat e mjedisit lokal
AcceptEnv LANG LC_*

# tejkaloni parazgjedhjen e asnjë nënsistemi
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Shembull i cilësimeve mbizotëruese në bazë të përdoruesit
# Përputhni përdoruesin anoncvs
# X11 Përfundimi Nr
# Allowcppforwarding nr
# Lejimi në
# Serveri ForceCommand CVS
PermitRootLogin no
Mos harroni, Ctrl+X dhe Y për të ruajtur skedarin. Tjetra, le të shkruajmë një skenar themelor të quajtur Initialize (të gjitha në drejtorinë e paracaktuar të shtëpisë së përdoruesit tonë).

nano initialize
Shtoni këto rreshta në skedar, duke zëvendësuarMe çelësin tuaj SSH që keni gjetur duke përdorur CAT. (.ssh/id_rsa.pub)

# / bin / bash
sudo apt install -y nano git openssh-server
sudo cp sshd_config /etc/ssh/sshd_config
sudo service ssh restart
sudo service sshd restart
echo "/root/.ssh/id_rsa" | sudo su root -c "ssh-keygen -t rsa -N ''"
echo "root ssh key:"
sudo su root -c "cat /root/.ssh/id_rsa.pub"
sudo adduser --disabled-password --gecos "" team
sudo passwd -d team
sudo usermod -aG sudo team
echo "/home/team/.ssh/id_rsa" | su team -c "ssh-keygen -t rsa -N ''"
cat /home/team/.ssh/id_rsa.pub >> /home/team/.ssh/authorized_keys
echo '<key here>' >> /home/team/.ssh/authorized_keys
echo "team ssh key:"
cat /home/team/.ssh/id_rsa.pub
Për t'ju përshkuar këtë skedar, le të fillojmë rreshtin sipas linjës. Rreshti i parë i tregon përpiluesit se ky është një skenar bash. Atëherë ne jemi duke instaluar varësi, duke kopjuar sshd_config në drejtorinë e saktë, duke rifilluar SSH, duke gjeneruar çelësa SSH për rrënjë, duke shtuar 'ekipin' e përdoruesit (mund të zgjidhni një emër që ju pëlqen për këtë, përdorni komandën adduser me emrin e tyre dhe fjalëkalimin e paaftë për të tani). Ne gjithashtu shtojmë ekipin në grupin sudo, gjenerojmë çelësin e tyre SSH, shtojmë çelësin tonë edhe për çelësat e autorizuar dhe të tyre, dhe shtypni çelësin e tyre. Ky përdorues i ri do të jetë mënyra se si ne futemi në sit. Në një terminal të ri, shkoni përpara dhe hapni përsëri serverin.

ssh team@XX.XX.XX.XX
Ju nuk duhet të keni nevojë për një fjalëkalim këtë herë, duke qenë pasi keni një çelës SSH. Ne gjithashtu kemi çaktivizuar hyrjen me fjalëkalim për ta mbajtur faqen më të sigurt. Tani, ky server fillon plotësisht bosh pa asnjë informacion mbi të. Le të fillojmë duke klonuar projektin tonë nga GIT, në mënyrë që të mund ta shkarkojmë dhe ekzekutojmë atë në makinën e largët. Në serverin e largët të lidhur mbi SSH, së pari shtypni çelësin tuaj SSH:

cat ~/.ssh/id_rsa.pub
Tjetra, ngjitni këtë çelës në cilësimet GIT si ne më parë për të vendosur depo tonë Git. Tani mund ta klonojmë projektin tonë direkt në server. Sigurohuni që e keni mbështetur projektin në vend të parë në vend, kështu që është në serverin GIT për ta shkarkuar.

git clone git://github.com/you/yourproject.git
Perfekt. Tani të gjitha skedarët janë këtu. Ne mund t'i shohim me ls

ls
Tani, le të fillojmë të vendosim serverin. Së pari, kopjoni drejtorinë tuaj të projektit në një emër të thjeshtë, të paharrueshëm që do të përdorim për projektin.

cp -r yourproject whatyoucalledit
Ku "Whatyoucalledit" është emri i ri i projektit tuaj. Tjetra, ne do të duhet të ndërtojmë një mjet themelor për të vendosur serverin. Ne do ta ruajmë këtë mjet dhe do ta përdorim atë në të ardhmen. Për të ndërtuar këtë mjet, le të krijojmë një binar të përdoruesit për të përcaktuar se si ne redaktojmë një skenar. Përdorimi i Bash, Redakto/USR/Bin/Accript

sudo nano /usr/bin/ascript
Sigurohuni që të përdorni sudo atje, në mënyrë që të keni leje për të modifikuar skedarin. Në skedar, shtoni këto rreshta:

# / bin / bash
if [ ! -f /usr/bin/$1 ]; then
    sudo touch /usr/bin/$1
    echo "# ! / bin / bash ">> / usr / bin / $ 1
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
    echo $1 | sudo tee -a /etc/ascripts
else
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
fi
Mos harroni se ky skenar merr një argument, emrin e skenarit, si 1 $. Së pari kontrollon nëse skedari ekziston, ose e krijon ndryshe, shton rreshtin e parë për të deklaruar se skenari është bash, ndryshon lejet e tij, e redakton atë dhe shton emrin e tij në /etj /përshkrime që na lejon të ruajmë emrat e skripteve ne po krijojnë. Nëse skedari tashmë ekziston, thjesht ndryshoni lejet dhe modifikoni atë. Ruani skedarin, dhe tjetër ne do të ndryshojmë lejet e saj. Për sa kohë që ne e përdorim këtë skenar, ne nuk do të duhet ta bëjmë atë përsëri.

sudo chmod a+x /usr/bin/ascript
Perfekt. Tani le të krijojmë një skenar të quajtur Setup. Së pari, për të mos ju kapërcyer, por hidhni një sy se si duket skenari im i konfigurimit. Ne do të ecim nëpër atë që duhet të duket ky skenar në projektin tuaj, nuk do të keni nevojë për gjithçka në skenarin tim për të filluar.

# / bin / bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
# sudo chmod a+x skriptet/përdoruesit e përdorimit
# ./scripts/usersetup
# Ssh-çelës
# Drejtoria e projektit
DIR="/home/team/femmebabe"
USER="team"
# Komandat e log
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# Nano konfigurim
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Konfigurim git
echo "Git configuration"
sudo git config --global user.email "jasper.camber.holton@gmail.com" && sudo git config --global user.name "Jasper Holton"
git config --global user.email "jasper.camber.holton@gmail.com"
git config --global user.name "Jasper Holton"
git config --global --add safe.directory $"$DIR"
sudo ssh-keyscan -t rsa gitlab.com | sudo tee -a /root/.ssh/known_hosts
sudo ssh-keyscan -t rsa github.com | sudo tee -a /root/.ssh/known_hosts
echo "Mounting setup"
sudo mount -o remount,size=16G,exec /tmp
# Përditësoni dhe instaloni
echo "Update and install packages"
sudo apt update && sudo NEEDRESTART_MODE=a apt upgrade -y
sudo apt purge postgresql-client-14 postgresql-client-common postgresql-common postgresql-contrib postgresql -y
echo "postfix postfix/mailname string femmebabe.com" | sudo debconf-set-selections
echo "postfix postfix/main_mailer_type string 'Internet Site'" | sudo debconf-set-selections
sudo NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt install -y postfix
sudo NEEDRESTART_MODE=a apt install -y rkhunter clamav-daemon libx264-dev ffmpeg libapache2-mod-wsgi-py3 apache2 cmake python-is-python3 python3-venv python3-pip python3-django expect tesseract-ocr openjdk-8-jdk redis-server libopencv-dev python3-opencv python3-dev libsasl2-dev opendkim opendkim-tools dovecot-core dovecot-pop3d dovecot-imapd auditd procmail libpq-dev postgresql postgresql-contrib libheif-dev snapd git software-properties-common certbot python3-certbot-apache
echo "-a exit,always -F arch=b64 -F euid=0 -S execve" | sudo tee -a /etc/audit/audit.rules
echo "-a exit,always -F arch=b32 -F euid=0 -S execve" | sudo tee -a /etc/audit/audit.rules
# Aktivizo antivirusin e clamav
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Vendosni emrin e hostit
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname localhost
# Setup Postgres
echo "Postgres setup"
sudo -u postgres psql -U postgres -c "DROP DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE USER django WITH PASSWORD 'password';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET client_encoding TO 'utf8';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET default_transaction_isolation TO 'read committed';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET timezone TO 'UTC';"
sudo -u postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE database TO django;"
# Konfigurimi i bazës së të dhënave rezervë
echo "Building database from backup, this may take a while."
cat db.json.?? > db.json
echo "Configuring firewall"
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow 22
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 'Postfix'
sudo ufw allow 'Postfix SMTPS'
sudo ufw allow 'Postfix Submission'
sudo ufw allow 'Dovecot POP3'
sudo ufw allow 'Dovecot Secure POP3'
sudo ufw allow 110/tcp
sudo ufw allow 25/tcp
echo "y" | sudo ufw enable
# IPatables me aftësi të kufizuara
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Instaloni bitdefender
cd $DIR
echo "Runnning BitDefender antivirus installer"
wget https://cloud.gravityzone.bitdefender.com/Packages/NIX/0/7aTSsy/setup_downloader.tar
mkdir bitdefender
tar -xf setup_downloader.tar -C bitdefender
sudo rm setup_downloader.tar
sed -i -e 's/{LOGINPASSWD/z&A*3BPd_qBGUMs/g' bitdefender/installer
sudo chmod a+x bitdefender/installer
sudo ./bitdefender/installer
# Setup Postfix
cd $DIR
echo "Mail services configuration"
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
sudo cp config/etc_postfix_main.cf /etc/postfix/main.cf
sudo cp config/etc_postfix_master.cf /etc/postfix/master.cf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo cp config/etc_dovecot_conf.d_10-auth.conf /etc/dovecot/conf.d/10-auth.conf
sudo cp config/etc_dovecot_conf.d_10-master.conf /etc/dovecot/conf.d/10-master.conf
sudo cp config/etc_dovecot_dovecot.conf /etc/dovecot/dovecot.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_opendkim.conf /etc/opendkim.conf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo adduser postfix opendkim
sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys
sudo mkdir /etc/opendkim/keys/femmebabe.com
sudo mkdir /var/spool/postfix/opendkim
sudo echo "*@femmebabe.com     sendonly._domainkey.femmebabe.com" | sudo tee -a /etc/opendkim/signing.table
sudo echo "sendonly._domainkey.femmebabe.com    femmebabe.com:sendonly:/etc/opendkim/keys/femmebabe.com/sendonly.private" | sudo tee -a /etc/opendkim/key.table
sudo echo "127.0.0.1" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "localhost" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "*.femmebabe.com" | sudo tee -a /etc/opendkim/trusted.hosts
sudo chown -R opendkim:opendkim /etc/opendkim
sudo opendkim-genkey -b 2048 -d femmebabe.com -D /etc/opendkim/keys/femmebabe.com -s sendonly -v
sudo chmod go-rw /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys/femmebabe.com/sendonly.private
sudo chown opendkim:postfix /var/spool/postfix/opendkim
cd $DIR
sudo cp mailbox/* /var/mail/
sudo chown :users /var/mail/*
sudo chmod -R a+rwx /var/mail/*
sudo systemctl restart opendkim postfix dovecot
# Krijoni Dirs
cd $DIR
mkdir media/audio
mkdir media/audio/fingerprints
mkdir media/security
mkdir media/secure
mkdir media/secure/media
mkdir media/secure/video
mkdir media/secure/profile
mkdir media/secure/face
mkdir media/images
mkdir media/live
mkdir media/live/files
mkdir media/live/stills
mkdir media/files
mkdir temp
mkdir temp/data
mkdir temp/gfpgan
mkdir mail/inbox
mkdir mailbox
# Konfigurimi i virtytit
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
# Merrni dhe ndërtoni varësi
echo "Getting and building dependencies, this may take a whike"
cd $DIR
git clone https://github.com/sukhitashvili/violence-detection.git
cp config/vd-requirements.txt violence-detection/requirements.txt
cp config/vd-model.py violence-detection/model.py
cd violence-detection
pip3 install -r requirements.txt
cd $DIR
wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth -P experiments/pretrained_models
git clone https://github.com/TencentARC/GFPGAN.git
git clone https://github.com/davisking/dlib.git
cd dlib
mkdir build; cd build; cmake ..; cmake --build .
cd ..
source venv/bin/activate
python setup.py install
cd $DIR
source venv/bin/activate
cd $DIR/GFPGAN/
echo "Installing python dependencies"
pip install basicsr
pip install facexlib
pip install -r requirements.txt
python setup.py develop
pip install realesrgan
cd $DIR
sudo chown -R team:users gfpgan
echo "Installing ta-lib"
wget https://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
tar xvzf ta-lib-0.4.0-src.tar.gz
sudo rm ta-lib-*
cd ta-lib
sudo ./configure
sudo make
sudo make install
# Vendosni rregullat e firewall
cd $DIR
# Instaloni varësitë PYPI
echo "Installing remaining python dependencies (this may take a while)"
sudo systemctl mask tmp.mount
cd $DIR
source venv/bin/activate
pip3 install -U "celery[redis]"
pip3 install -r requirements.txt --use-deprecated=legacy-resolver --use-pep517
pip3 install --upgrade opencv-python # == 4.5.4.60
pip3 install --upgrade opencv-contrib-python # == 4.5.4.60
# PIP Instaloni OpenCV-Python == 4.5.5.64
# PIP Instaloni OpenCV-Contrib-Python == 4.5.5.64
pip3 install --upgrade opencv-python-headless
pip3 uninstall channels
pip3 uninstall daphne
pip3 install channels["daphne"]
pip3 install Pillow==9.5.0
pip3 install librosa
pip3 install -U 'Twisted[tls,http2]'
pip3 install --upgrade certifi requests urllib3 numpy oauthlib twisted pyjwt sqlparse cryptography astral webauthn docbarcodes pdf417 deepface --no-cache-dir
pip3 install tensorflow==2.15.1
# Instaloni CertBot
echo "Installing certificates"
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap install redis
sudo systemctl enable apache2
sudo systemctl start apache2
# RUN CERTBOT
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email jasper.camber.holton@gmail.com
# Rifresko serverin e postës
sudo systemctl restart opendkim postfix dovecot
# Kopjimi i certifikatave
# sudo cp /etc/letsencrypt/live/femmebabe.com/privkey.pem privkey.pem
# sudo cp /etc/lettesencrypt/live/femmebabe.com/cert.pem cert.pem
# Arnoj
cp scripts/content.py $"/home/team/femmebabe/venv/lib/python${PYTHON_VERSION}/site-packages/pyxb/binding/content.py"
cp scripts/pwa_webpush_forms.py $"/home/team/femmebabe/venv/lib/python${PYTHON_VERSION}/site-packages/pwa_webpush/forms.py"
cp scripts/webauth_views.py $"/home/team/femmebabe/venv/lib/python${PYTHON_VERSION}/site-packages/webauth/views.py"
cp scripts/json.py $"venv/lib/python${PYTHON_VERSION}/site-packages/django/core/serializers/json.py"
# Vendosni Cilësimet e Përdoruesit
sudo gpasswd -a www-data users
# Vendosni lejet
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# Sudo Chown -r Ekipi: Përdoruesit/Var/Run/
# Sudo Chown Root: rrënjë/vrap/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
# sudo chmod 664 db.sqlite3
# sudo chown www-data: përdoruesit db.sqlite3
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
sudo chown -R team:users ./gfpgan/
sudo chown -R team:users ./temp/
sudo chmod a+r team /var/mail/$USER
# Kopjoni konfigurimin dhe vendosni lejet
echo "Configuring remaining services"
sudo cp config/apis.json /etc/apis.json
sudo cp config/config.json /etc/config.json
sudo cp config/femmebabe-le-ssl.conf /etc/apache2/sites-available/femmebabe-le-ssl.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_init.d_celery /etc/init.d/celery
sudo cp config/etc_init.d_celerybeat /etc/init.d/celerybeat
sudo cp config/etc_default_celerybeat /etc/default/celerybeat
sudo cp config/etc_default_celery /etc/default/celery
sudo cp config/etc_systemd_system_daphne.service /etc/systemd/system/daphne.service
sudo cp config/etc_systemd_system_celery.service /etc/systemd/system/celery.service
sudo cp config/etc_systemd_system_celerybeat.service /etc/systemd/system/celerybeat.service
sudo chmod a+x /etc/init.d/celery
sudo chmod a+x /etc/init.d/celerybeat
# Konfigurim i bazës së të dhënave
echo "Running migrations, this should be quick"
python manage.py makemigrations
python manage.py migrate --run-syncdb
echo "Loading data, this may take a while"
python manage.py loaddata db.json
echo "Setup crontab/sudoers configuration"
sudo crontab -l -u root | cat - config/crontab | sudo crontab -u root -
sudo sh -c "cat config/sudoers >> /etc/sudoers"
# Injektoni konfigurimin PAM dhe hiqni konfigurimin e gabuar të SSH
# sudo sed -i '' -e '$ d' /tc/pam.d/sshd
# Sudo sed -i '' -dhe $ d ' /etj /profil
echo "session required pam_exec.so seteuid /home/team/femmebabe/pam.sh" | sudo tee -a /etc/pam.d/sshd
echo "session required pam_exec.so seteuid /home/team/femmebabe/logout.sh" | sudo tee -a /etc/pam.d/sshd
sudo chmod a+x pam.sh
sudo rm /etc/ssh/sshd_config.d/50-cloud-init.conf
# Kopjoni skriptet e koshit dhe vendosni lejet
echo "Copying scripts"
sudo cp scripts/reload /usr/bin/
sudo cp scripts/check /usr/bin/
sudo cp scripts/enagpu /usr/bin/
sudo cp scripts/disgpu /usr/bin/
sudo cp scripts/activate /usr/bin/
sudo cp scripts/backup /usr/bin/
sudo cp scripts/ascript /usr/bin/
sudo cp scripts/setup /usr/bin/
sudo cp scripts/addsetup /usr/bin/
sudo cp scripts/watchlogs /usr/bin/
sudo cp scripts/logs /usr/bin/
sudo cp scripts/cmds /usr/bin/
sudo cp scripts/setup /usr/bin/
sudo cp scripts/pushweb /usr/bin/
sudo cp scripts/purgecache /usr/bin/
sudo cp config/banner /etc/banner
cd /usr/bin/
sudo chmod a+x activate
sudo chmod a+x backup
sudo chmod a+x ascript
# Rifresko dhe Aktivizo Shërbimet
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable daphne.service
sudo systemctl enable celery.service
sudo systemctl enable celerybeat.service
sudo systemctl enable clamav-daemon
sudo systemctl start daphne.service
sudo systemctl start celery.service
sudo systemctl start celerybeat.service
sudo systemctl start clamav-daemon
# Aktivizo Modulet Apache
echo "Enabling apache2"
sudo a2enmod rewrite
sudo a2enmod wsgi
sudo a2enmod headers
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_balancer
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
# sudo a2dismod mpm_event
# sudo a2dismod mpm_worker
# sudo a2enmod mpm_pefork
# Çaktivizo faqen e paracaktuar
sudo a2dissite 000-default
sudo a2dissite 000-default-le-ssl
# Aktivizo për sitin
sudo a2ensite femmebabe-le-ssl
# Rifresko Daemon dhe rinisni Apache, Postfix dhe Opendkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
sudo systemctl start daphne
# Vendosni lejet
sudo chown -R :www-data /var/www/
sudo chown -R :www-data /var/www/.deepface
# Konfigurimi i ndërrimit
echo "Allocating swap, this may take a while"
sudo swapoff /swapfile
sudo rm /swapfile
sudo fallocate -l 8G /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1024 count=8388608
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/fstab
sudo swapon --show
# Motor titullar
echo "Initializing routine caption"
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/routine_caption.py
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/setup_mail.py
# Konfiguroj
echo "Setting up git"
cd $DIR
sudo rm -r .git
git init --initial-branch=main
echo "Setting user password"
sudo usermod --password $(echo team | openssl passwd -1 -stdin) team
# Shfaq IPv6 dhe OpendKim për konfigurimin e domain
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
sudo cat /etc/opendkim/keys/femmebabe.com/sendonly.txt | tr -d '\n' | sed 's/\s//g' | sed 's/""//g' | awk -F'[)(]' '{print $2}'
# Konfigurimi i përfunduar
echo "Setup completed in"
wc -l scripts/setup
echo "lines of code."
echo "Total time:"
duration=$SECONDS
echo "$((duration / 60)) minutes and $((duration % 60)) seconds elapsed."
echo "TODO:"
echo "- COPY above IPv6 address to domain DNS configuration"
echo "- COPY domain key to domain DNS configuration"
echo "- ADD new git repository with git remote add originlab <repo>."
echo "- OPEN port 25"
echo "- INSTALL antivirus as per reccomendations"
echo "- TEST"
echo "If neccesary,"
echo "- DEBUG"
echo "- FIX setup and backup scripts"
echo "- Fix server"
echo ""
echo "Thank you for using the femmebabe installer. Have a great day!"
echo "Goodbye."
Kjo është shumë konfigurim! Me pak fjalë, ky kod regjistron komandat, konfiguron nano dhe git, kopjon mbi skedarë, shkarkime dhe instalon pako ubuntu apt, varësitë e python, konfiguron postfix, konfiguron postgresi çaktivizon iptables, shkarkon një antivirus, bën drejtori, varësi nga klonet, instalon certifikata dhe Vendos serverin, instalon konfigurimin, fillon dhe mundëson Sever, ndan shkëmbimin, vendos lejet dhe shtyp IP, adresën IPv6 dhe Key OpendKim. Shumë e thjeshtë, por duket si shumë kod. Ne nuk do të kemi nevojë për shumë nga kjo sepse nuk kemi varësi, ne nuk po përdorim selino, selinebeat ose dafne, por do të instalojmë disa prej tyre sidoqoftë për të filluar. Vini re se ky kod ka një domen të deklaruar disa herë. Ne gjithashtu do të duhet të blejmë një emër domain (i cili është një tarifë e vogël vjetore). Unë rekomandoj Squarespace për blerjen e një domeni, paraqitja e tyre ështëIntuitiv dhe i lehtë për t’u përdorur. Ju mund të blini ndonjë domen të zgjedhjes suaj, por unë jam duke përdorur domain femmebabe.com në këtë shembull. Pasi të keni blerë një domen, drejtohuni në panelin e konfigurimit të Squarespace DNS dhe shtoni një rekord që tregon domenin tuaj në server me adresë IP. Duhet të duket kështu: @ A xx.xx.xx.xx Me operatorin @ si host, do të thotë të gjithë nënfushat nën këtë domen dhe domeni rrënjësor do të ridrejtohen të gjithë në server. Ka më shumë rekorde për të deklaruar, por ne mund të kalojmë në këto pasi të jemi gati të dërgojmë postë. Mbani në mend, mund të duhen disa ditë para se të jeni në gjendje të dërgoni me sukses postë nga serveri. Regjistrimet e DNS që po vendosim do të marrin kohë për të përhapur. Sidoqoftë, e vetmja rekord që duhet të fillojmë është një rekord. Pra, tani ne mund të plotësojmë skenarin e mëposhtëm sipas projektit tonë dhe ta ekzekutojmë atë. Le të fillojmë me një skenar më të vogël të konfigurimit për të instaluar atë që na nevojitet për një përparim themelor. Ne nuk do të përdorim kaq shumë varësi ose postgreSQL akoma, ne thjesht do tëPërgatitni një server themelor HTTP dhe shqetësohuni për certifikimin e tij kur të bëhet. Mos harroni, për të marrë një certifikatë HTTPS dhe për të ekzekutuar serverin në mënyrë të sigurt, do të na duhet të blejmë një domen së bashku me Qiraja një server. Tani për tani, zëvendësoni "ekipin" në këtë skedar me emrin e përdoruesit tuaj, "dir" me drejtorinë e projektit tuaj dhe furnizoni emailin dhe domenin tuaj në etiketat <>. Për më tepër, para se të ekzekutojmë këtë kod, duhet të ndryshojmë cilësimet në firewall që ofruesi i pritjes mbështet, nëse ka. Zakonisht kjo është në skedën 'Rrjetet' e ofruesit tuaj të pritjes, ose nëse jeni vetë pritës, është në seksionin 'Port Forwarding' të ruterit tuaj. Ju gjithashtu do të dëshironi të vendosni një IP statike përmes ruterit tuaj me adresën e makinës tuaj të serverit, nëse jeni duke përdorur vetë -pritjen. Ju do të duhet të hapni portet e mëposhtme për qasje në lexim/shkrim. 22 (SSH) 25 (postë) 587 (postë) 110 (Klienti i Postës) 80 (http) 443

# / bin / bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
DIR="/home/team/<yourproject>"
USER="team"
# Komandat e log
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# Nano konfigurim
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Konfigurim git
echo "Git configuration"
sudo git config --global user.email "<youremail>@gmail.com" && sudo git config --global user.name "<yourname>"
git config --global --add safe.directory $"$DIR"
sudo ssh-keyscan -t rsa gitlab.com | sudo tee -a /root/.ssh/known_hosts
sudo ssh-keyscan -t rsa github.com | sudo tee -a /root/.ssh/known_hosts
# Përditësoni dhe instaloni
echo "Update and install packages"
sudo apt update && sudo NEEDRESTART_MODE=a apt upgrade -y
sudo apt purge postgresql-client-14 postgresql-client-common postgresql-common postgresql-contrib postgresql -y
echo "postfix postfix/mailname string femmebabe.com" | sudo debconf-set-selections
echo "postfix postfix/main_mailer_type string 'Internet Site'" | sudo debconf-set-selections
sudo NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt install -y postfix
sudo NEEDRESTART_MODE=a apt install -y rkhunter clamav-daemon libx264-dev ffmpeg libapache2-mod-wsgi-py3 apache2 cmake python-is-python3 python3-venv python3-pip python3-django expect tesseract-ocr openjdk-8-jdk redis-server libopencv-dev python3-opencv python3-dev libsasl2-dev opendkim opendkim-tools dovecot-core dovecot-pop3d dovecot-imapd auditd procmail libpq-dev postgresql postgresql-contrib libheif-dev snapd git software-properties-common certbot python3-certbot-apache
# Aktivizo antivirusin e clamav
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Vendosni emrin e hostit
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname femmebabe
# Konfigurimi i bazës së të dhënave rezervë
echo "Building database from backup, this may take a while."
cat db.json.?? > db.json
echo "Configuring firewall"
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow 22
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 'Postfix'
sudo ufw allow 'Postfix SMTPS'
sudo ufw allow 'Postfix Submission'
sudo ufw allow 'Dovecot POP3'
sudo ufw allow 'Dovecot Secure POP3'
sudo ufw allow 110/tcp
sudo ufw allow 25/tcp
echo "y" | sudo ufw enable
# IPatables me aftësi të kufizuara
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Konfigurimi i virtytit
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
# Instaloni CertBot
echo "Installing certificates"
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap install redis
sudo systemctl enable apache2
sudo systemctl start apache2
# RUN CERTBOT
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email <youremail>@gmail.com
# Vendosni Cilësimet e Përdoruesit
sudo gpasswd -a www-data users
# Vendosni lejet
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# Sudo Chown -r Ekipi: Përdoruesit/Var/Run/
# Sudo Chown Root: rrënjë/vrap/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
# Rifresko dhe Aktivizo Shërbimet
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Aktivizo Modulet Apache
echo "Enabling apache2"
sudo a2enmod rewrite
sudo a2enmod wsgi
sudo a2enmod headers
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_balancer
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
# Rifresko Daemon dhe rinisni Apache, Postfix dhe Opendkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
# Shfaq IPv6 dhe OpendKim për konfigurimin e domain
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
Para se të ekzekutoni këtë kod, sigurohuni që domeni që keni blerë është i lidhur me serverin. Për ta bërë këtë, hapni një terminal në makinën tuaj lokale dhe drejtojeni këtë komandë me domenin tuaj:

ping femmebabe.com # Vendosni domenin tuaj këtu, pas ping
Nëse të gjithë duken mirë dhe serveri po dërgon përgjigje, ne jemi të gatshëm të ekzekutojmë skriptin dhe të instalojmë pako, si dhe të fillojmë, aktivizoni dhe certifikojmë serverin tonë Apache. Kjo nuk është e gjithë konfigurimi i nevojshëm për të konfiguruar Postfix, ne do ta shikojmë atë konfigurim më vonë. Tani për tani, ekzekutoni këtë kod konfigurimi dhe duhet të duhen disa minuta për të instaluar dhe vërtetuar serverin tuaj. Edhe një herë, sigurohuni që të zëvendësoni emrin, emailin dhe emrin e domain në skenar sipas emrit që keni blerë. Tani që serveri është siguruar, ju mund të shkoni në URL në çdo shfletues në internet dhe të kontrolloni për t'u siguruar që serveri po funksionon HTTPS. Nëse nuk është kështu, provoni të prisni pak kohë që të dhënat e DNS të kapin dhe pastaj të ekzekutoni komandën e mëposhtme për të rigjykuar certifikimin e CertBot:

sudo certbot --apache --non-interactive --agree-tos --domains <domain>.com --email <youremail>@gmail.com
Për sa kohë që keni konfiguruar gjithçka në mënyrë korrekte, duhet të jeni në gjendje të hyni në faqen e paracaktuar të Apache vetëm për të ditur që kodi juaj është duke punuar dhe shfaq një faqe të drejtpërdrejtë. Tjetra, le të modifikojmë cilësimet.py për të ndryshuar mënyrën tonë të paracaktuar të debugimit në prodhim. Ne gjithashtu do të konfigurojmë domenin në cilësimet, si dhe IP -të e brendshme.

nano yourproject/settings.py
Në cilësimet, ndryshoni/shtoni këto rreshta.

DEBUG = False

# Konfigurim i faqes
SITE_NAME = 'Femme Babe'
PROTOCOL = 'https'
DOMAIN = 'femmebabe.com'
SITE_ID = 1
BASE_URL = PROTOCOL + '://' + DOMAIN
ALLOWED_HOSTS = [DOMAIN]

INTERNAL_IPS = [
    'XX.XX.XX.XX',
]
Tani, do të na duhet të konfigurojmë Apache2. Le të modifikojmë skedarin e konfigurimit që do të vendosim me këtë rresht:

sudo nano /etc/apache2/sites-available/femmebabe-le-ssl.conf
Ky skedar konfigurimi duhet të ketë emrin tonë të domain në të, dhe emrin e përdoruesit dhe projektit. Unë jam duke përdorur emrin e domain femmebabe.com, ekipin e përdoruesit dhe emrin e projektit Femmebabe.

ServerSignature Off
ServerTokens Prod
<IfModule mod_ssl.c>
<VirtualHost *:80> 
	Redirect permanent / https://femmebabe.com/
</VirtualHost>
<VirtualHost *:443>
	ServerName femmebabe.com
	ServerAdmin team@femmebabe.com
	DocumentRoot /var/www/html

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
	
	Alias /static /home/team/femmebabe/static
	<Directory /home/team/femmebabe/static>
		Require all granted
	</Directory>

Alias /media/icons /home/team/femmebabe/media/
<Directory /home/team/femmebabe/media>
Require all granted
</Directory>

	<Directory /home/team/femmebabe/femmebabe>
		<Files wsgi.py>
			Require all granted
		</Files>
	</Directory>

	WSGIScriptAlias / /home/team/femmebabe/femmebabe/wsgi.py
	WSGIDaemonProcess femmebabe python-path=/home/team/femmebabe/ python-home=/home/team/femmebabe/venv header-buffer-size=100000000000 user=team
	WSGIProcessGroup femmebabe
	WSGIApplicationGroup %{GLOBAL}
	
	<Directory /home/team/femmebabe/static>
                Options Indexes FollowSymLinks
                AllowOverride All
	</Directory>

	<IfModule mod_rewrite.c>
		RewriteEngine on
		RewriteCond %{REQUEST_URI} \.(css|webp|webm|gif|png|mp3|wav|jpeg|jpg|svg|webp)$ [NC]
		RewriteCond %{HTTP_REFERER} !^https://femmebabe.com/media/.*$ [NC]
		RewriteRule ^(.+?)/$ /media/$1 [F,L]
	</IfModule>

	Include /etc/letsencrypt/options-ssl-apache.conf
	SSLCertificateFile /etc/letsencrypt/live/femmebabe.com/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/femmebabe.com/privkey.pem

	Header set X-Frame-Options: "SAMEORIGIN"
	Header set Access-Control-Allow-Origin "https://femmebabe.com"

	TimeOut 60000
	LimitRequestBody 0

	<FilesMatch ".(ico|pdf|flv|jpg|jpeg|png|gif|webp|JPG|JPEG|wav|mp3|mp4|public|js|css|swf|webp|svg)$">
		Header set Cache-Control "max-age=30, public"
	</FilesMatch>
</VirtualHost>
</IfModule>
<IfModule mod_ssl.c>
<VirtualHost *:80>
	ServerName femmebabe.com
	ServerAdmin team@femmebabe.com
	DocumentRoot /var/www/html

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	RewriteEngine on
	RewriteCond %{SERVER_NAME} =femmebabe.com
	RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
</IfModule>
Sigurohuni që të zëvendësoni emrin e projektit, drejtorive dhe domenit në këtë kod shembull kur konfiguroni serverin tuaj. Tani, do të na duhet të çaktivizojmë faqen e paracaktuar. Kjo mund të bëhet duke përdorur Bash.

sudo a2dissite 000-default-le-ssl
sudo a2dissite 000-default
sudo a2dissite default-ssl
Tjetra, ne mund të mundësojmë sitin e paracaktuar dhe të rifreskoni Apache2, duke përdorur gjithashtu bash. Mos harroni të zëvendësoni femmebabe me emrin e skedarit që keni deklaruar kur redaktoni në/etj/apache2/faqet-të disponueshme/.

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Kthehuni në domenin tuaj në Navbar. Ju duhet të shihni faqen që keni konfiguruar në shfletuesin tuaj të internetit. Urime! Nëse nuk e shihni, mund t'ju duhet të bëni disa ndryshime. Rishikoni me kujdes cilësimet në projektin tuaj, konfigurimin e Apache dhe sigurohuni që të mos keni gabime dhe të ekzekutoni komandat e mëposhtme për të kontrolluar projektin për gabime.

cd projectname
source venv/bin/activate
python manage.py check
Nëse keni gabime në projektin tuaj Python, gjurmoni ato atje ku janë dhe rregulloni ato. Ju mund të mos jeni në gjendje të shihni të gjitha gabimet tuaja në varësi të vendit ku janë, kështu që nëse keni një gabim që thotë thjesht "Populloni nuk është i ri gabim

nano venv/lib/python3.12/site-packages/django/apps/registry.py
Shkoni në rreshtin 83, ku është ngritur ky gabim në kohën e ekzekutimit (ngrini RuntimeError ("Populloni () nuk është rigjenerues")), dhe shtoni një koment para kësaj linje, pastaj shtoni, me të njëjtën indentacion, vetë.App_Configs = {}. Kjo duket kështu:

            if self.loading:
                # Parandaloni thirrjet reentrante për të shmangur ekzekutimin e appConfig.Ready ()
                # Metodat dy herë.
# Rritni RuntimeError ("Populate () nuk është reentrant")
                self.app_configs = {}
            self.loading = True
Pastaj mund ta kontrolloni përsëri projektin dhe të ekspozoni gabimin.

python manage.py check
Atëherë mund ta shihni gabimin dhe ta rregulloni. Kur e keni rregulluar dhe kodi përpilon pa gabime, sigurohuni që të ndryshoni skedarin përsëri në mënyrë që të duket kështu:

            if self.loading:
                # Parandaloni thirrjet reentrante për të shmangur ekzekutimin e appConfig.Ready ()
                # Metodat dy herë.
                raise RuntimeError("populate() isn't reentrant")
# vetë.app_configs = {}
            self.loading = True
Me kusht që serveri të jetë në internet, kur të bëjmë ndonjë ndryshim të mëtejshëm në të, duhet të përdorim komandën e mëposhtme për të ringarkuar serverin:

sudo systemctl reload apache2
E mrekullueshme! Po në lidhje me dërgimin e postës? Për të filluar dërgimin e postës elektronike, së pari do të duhet të azhurnojmë konfigurimin e domain. Kjo duhet të jetë në panelin tuaj DNS në Squarespace, ose çfarëdo regjistruesi të emrit të domain që keni zgjedhur. Ne gjithashtu do të duhet të instalojmë dhe shtojmë konfigurimin, dhe të ekzekutojmë disa komanda. Së pari, le të marrim adresën IPv6 të serverit. Ne pastaj do të hapim DNS tuaj dhe do t'i shtojmë të dhënat. Për të marrë adresën IPv6 të serverit, përdorni këtë komandë:

ip -6 addr
Tani, ne mund të shtojmë të dhënat e mëposhtme në cilësimet DNS. Të dhënat e mia duken kështu. Sidoqoftë, për të dhënat tuaja, ju duhet të zëvendësoni adresën IP me IP -në tuaj (jo 75.147.182.214, kjo është e imja). Shtoni gjithashtu domenin tuaj në vend të femmebabe.com, si dhe adresën tuaj IPv6 të gjetur me komandën e mëparshme (ju nuk mund të përdorni timen, Fe80 :: 725A: FFF: FE49: 3E02). Mos u shqetësoni për domainKey tani për tani, kjo është krijuar kur vendosëm PostFix, serverin e postës, me Opendkim dhe shtypni çelësin. Ne do ta konfigurojmë këtë të fundit. Jam Një N/A 75.147.182.214 Jam Mx 10 femmebabe.com Jam Ptr N/A femmebabe.com Jam Txt N/A Txt @ v = spf1 mx ip75.147.182.214ip6: fe80 :: 725a: fff: fe49: 3e02 ~ të gjitha parazgjedhur._bimi Txt N/A v = bimi1; l = https: //femmebabe.com/media/static/femmebabe.svg _DMARC Txt N/A v = dmarc1; p = asnjë Sendonly._domainKey Txt N/ATani, do të duhet të shtojmë një konfigurim të vazhdueshëm për Postfix. E tëra që duhet të bëjmë është të sigurohemi që të zëvendësojmë emrin e domain, femmebabe.com, me emrin e domain që po përdorni. Le t'i shohim të gjitha skedarët e konfigurimit një nga një, dhe t'i instalojmë ato në një direktori të quajtur konfigurim në projektin tonë, për instalim në OS.

nano config/etc_postfix_main.cf
Shtojeni këtë tekst në skedar

# Shih /usr/share/postfix/main.cf.dist për një version të komentuar, më të plotë


# Debian specifik: Specifikimi i një emri skedari do të shkaktojë të parën
# linja e asaj skedari që do të përdoret si emër.  Default Debian
# është /etj /posta e postës.
# myorigin = /etj /emër postar

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# Shtojca .domain është puna e MUA -së.
append_dot_mydomain = no

# Uncomment rreshti tjetër për të gjeneruar paralajmërime "postë të vonuar"
# vonesë_warning_time = 4h

readme_directory = no

# Shihni http://www.postfix.org/compatibility_readme.html - Default në 3.6 ON
# instalime të freskëta.
compatibility_level = 3.6



# Parametrat TLS
smtpd_tls_cert_file=/etc/letsencrypt/live/femmebabe.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/femmebabe.com/privkey.pem
smtpd_tls_security_level=may

smtp_tls_CApath=/etc/ssl/certs
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_relay_restrictions = permit_sasl_authenticated, defer_unauth_destination
myhostname = femmebabe.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = femmebabe.com, localhost, $myhostname
smtp_helo_name = femmebabe.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all

# Konfigurimi i Milterit
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

smtp_tls_security_level = encrypt
smtp_tls_loglevel = 1

virtual_transport=lmtp:unix:private/dovecot-lmtp

smtpd_sasl_path = private/auth
Konfigurimi tjetër!

nano config/etc_postfix_master.cf
Shtoni këto rreshta:

# 
# Skedari i konfigurimit të procesit master postfix.  Për detaje mbi formatin
# të skedarit, shiko faqen manuale Master (5) (komanda: "Njeriu 5 Master" ose
# On-line: http://www.postfix.org/master.5.html).
# 
# Mos harroni të ekzekutoni "Reload Postfix" pas redaktimit të kësaj skedari.
# 
# ===================================================== ==========================
# Lloji i Shërbimit Komanda Private jopriv chroot wake maxProc + argumenton
# (Po) (po) (jo) (kurrë) (100)
# ===================================================== ==========================
smtp      inet  n       -       y       -       -       smtpd
# Smtp inet n - y - 1 pas ekranit
# Smtpd Pass - - Y - - Smtpd
# Dnsblog unix - - y - 0 dnsblog
# Tlsproxy unix - - y - 0 tlsproxy
# Zgjidhni një: Aktivizoni dorëzimin vetëm për klientët Loopback, ose për ndonjë klient.
# 127.0.0.1: Submision inet n - y - - smtpd
submission inet n       -       y       -       -       smtpd
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=no
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
# -o syslog_name = postfix/dorëzimi
# -o smtpd_tls_securance_level = encrypt
# -o smtpd_sasl_auth_enable = po
# -o smtpd_tls_auth_only = po
# -o smtpd_reject_unlisted_recipient = nr
# -O smtpd_client_restrictions = $ MUA_CLIENT_RESTRICTIONS
# -o smtpd_helo_restrictions = $ MUA_HELO_RESTRICTIONS
# -O smtpd_siender_restrictions = $ MUA_Sender_restrictions
# -O smtpd_recipient_restrictions =
# -O smtpd_relay_restrictions = leje_sasl_authenciatecated, refuzoj
# -O milter_macro_daemon_name = me origjinë
# Zgjidhni një: Aktivizoni SMTPS vetëm për klientët Loopback, ose për ndonjë klient.
# 127.0.0.1:smtps inet n - y - - smtpd
# smtps inet n - y - - smtpd
# -O syslog_name = postfix/smtps
# -o smtpd_tls_wrappermode = po
# -o smtpd_sasl_auth_enable = po
# -o smtpd_reject_unlisted_recipient = nr
# -O smtpd_client_restrictions = $ MUA_CLIENT_RESTRICTIONS
# -o smtpd_helo_restrictions = $ MUA_HELO_RESTRICTIONS
# -O smtpd_siender_restrictions = $ MUA_Sender_restrictions
# -o smtpd_recipient_trival =
# -O smtpd_relay_restrictions = leje_sasl_authenciatecated, refuzoj
# -O milter_macro_daemon_name = me origjinë
# 628 inet n - y - - qmqpd
pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
# qmgr unix n - n 300 1 oqmg
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
        -o syslog_name=postfix/$service_name
# -o smtp_helo_timeout = 5 -o smtp_connect_timeout = 5
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
postlog   unix-dgram n  -       n       -       1       postlogd
# 
# ===================================================== ====================
# Ndërfaqe në softuerin jo-postar. Sigurohuni që të ekzaminoni manualin
# Faqet e softuerit jo-postar për të zbuluar se çfarë opsionesh dëshiron.
# 
# Shumë nga shërbimet e mëposhtme përdorin dorëzimin e tubit postfix (8)
# agjent  Shihni faqen e Gruas Tub (8) për informacion në lidhje me $ {marrës}
# dhe opsione të tjera të zarfit të mesazheve.
# ===================================================== ====================
# 
# Maildrop. Shikoni skedarin postfix maildrop_readme për detaje.
# Specifikoni gjithashtu në Main.cf: maildrop_destination_recipient_limit = 1
# 
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# 
# ===================================================== ====================
# 
# Versionet e fundit të Cyrus mund të përdorin hyrjen ekzistuese "LMTP" Master.CF.
# 
# Specifikoni në Cyrus.conf:
# lmtp cmd = "lmtpd -a" dëgjo = "localhost: lmtp" proto = tcp4
# 
# Specifikoni në Main.cf një ose më shumë nga sa vijon:
# mailbox_transport = lmtp: inet: localhost
# Virtual_transport = lmtp: inet: localhost
# 
# ===================================================== ====================
# 
# Cyrus 2.1.5 (Amos Gouaux)
# Specifikoni gjithashtu në main.cf: cyrus_destination_recipient_limit = 1
# 
# Cyrus unix - n n - - tub
# flamuj = përdorues drx = cyrus arg =/cyrus/bin/dorëshkrim -e -r $ {dërgues} -m $ {shtesë} $ {përdorues}
# 
# ===================================================== ====================
# Shembull i vjetër i dorëzimit përmes Kirit.
# 
# Old -Cyrus unix - n n - - tub
# Flamurët = r përdorues = Cyrus argv =/cyrus/bin/dorëzimi -e -m $ {shtesë} $ {përdorues}
# 
# ===================================================== ====================
# 
# Shikoni skedarin PostFix UUCP_ReadMe për detajet e konfigurimit.
# 
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
# 
# Metodat e tjera të shpërndarjes së jashtme.
# 
ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
Dhe konfigurimi i Opendkim. OpendKim identifikon serverët e postës elektronike me çelësat e domain për t'i bërë ata më të sigurt. Pa të, posta nuk është nënshkruar dhe mund të mos e bëjë atë në një kuti.

nano config/etc_default_opendkim
Shtoni këto rreshta:

# Shënim: Ky është një skedar i konfigurimit të trashëgimisë. Nuk përdoret nga opendkim
# shërbimi i sistemuar. Ju lutemi përdorni parametrat përkatës të konfigurimit në
# /etc/opendkim.conf në vend.
# 
# Më parë, dikush do të redaktonte cilësimet e paracaktuara këtu, dhe pastaj ekzekutimin
# /lib/opendkim/opendkim.service.generate për të gjeneruar skedarë të tejkaluar të sistemit në
# /etc/systemd/system/opendkim.service.d/override.conf dhe
# /etc/tmpfiles.d/opendkim.conf. Ndërsa kjo është akoma e mundur, tani është
# Rekomandohet të rregulloni cilësimet direkt në /etc/opendkim.conf.
# 
# Daemon_opts = ""
# Ndryshoni në/var/spool/postfix/run/opendkim për të përdorur një fole UNIX me
# Postfix në një Chroot:
# Rundir =/ishte/spool/postfix/vrap/opendkim
RUNDIR=/run/opendkim
# 
# Uncomment për të specifikuar një fole alternative
# Vini re se përcaktimi i kësaj do të tejkalojë çdo vlerë fole në opendkim.conf
# Default:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Dëgjoni të gjitha ndërfaqet në portin 54321:
# Fole = inet: 54321
# Dëgjoni në Loopback në portin 12345:
# Fole = inet: 12345@localhost
# Dëgjoni është 192.0.2.1 është porti 12345:
# Fole = inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

nano config/etc_dovecot_conf.d_10-master.conf
Shtoni këto rreshta:

0-master.conf 
# default_process_limit = 100
# default_client_limit = 1000

# Default VSZ (madhësia e memorjes virtuale) kufiri për proceset e shërbimit. Kjo është kryesisht
# synuar për të kapur dhe vrarë proceset që rrjedhin kujtesën para se të hanë lart
# gjithçka.
# default_vsz_limit = 256m

# Përdoruesi i hyrjes përdoret nga brenda nga proceset e hyrjes. Kjo është më e pabesueshme
# Përdoruesi në sistemin Dovecot. Nuk duhet të ketë qasje në asgjë fare.
# default_login_user = dovenull

# Përdoruesi i brendshëm përdoret nga proceset e paracaktuar. Duhet të jetë e ndarë nga
# Përdoruesi i hyrjes, në mënyrë që proceset e hyrjes të mos mund të shqetësojnë proceset e tjera.
# default_internal_user = dovecot

service imap-login {
  inet_listener imap {
    # Porti = 143
  }
  inet_listener imaps {
    # Porti = 993
    # ssl = po
  }

  # Numri i lidhjeve për të trajtuar përpara se të filloni një proces të ri. Në mënyrë tipike
  # Vlerat e vetme të dobishme janë 0 (të pakufizuara) ose 1. 1 është më e sigurt, por 0
  # është më e shpejtë. <doc/wiki/loginprocess.txt>
  # shërbimi_count = 1

  # Numri i proceseve për të vazhduar gjithmonë duke pritur për më shumë lidhje.
  # proces_min_avail = 0

  # Nëse vendosni shërbimin_count = 0, me siguri duhet ta rritni këtë.
  # vsz_limit = $default_vsz_limit
}

service pop3-login {
  inet_listener pop3 {
    # Porti = 110
  }
  inet_listener pop3s {
    # Porti = 995
    # ssl = po
  }
}

service submission-login {
  inet_listener submission {
    # Porti = 587
  }
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    group = postfix
    mode = 0666
    user = postfix
  }

  # Krijoni një dëgjues inet vetëm nëse nuk mund të përdorni prizën e mësipërme UNIX
  # inet_lister lmtp
    # Shmangni bërjen e LMTP të dukshme për të gjithë internetin
    # Adresa =
    # porti =
  # }
}

service imap {
  # Shumica e kujtesës shkon në skedarë mmap () ing. Ju mund të keni nevojë për të rritur këtë
  # Kufizoni nëse keni kuti postare të mëdha.
  # vsz_limit = $default_vsz_limit

  # Max. Numri i proceseve IMAP (Lidhjet)
  # Procesi_limit = 1024
}

service pop3 {
  # Max. Numri i proceseve POP3 (lidhjet)
  # Procesi_limit = 1024
}

service submission {
  # Max. Numri i proceseve të paraqitjes SMTP (Lidhjet)
  # Procesi_limit = 1024
}

service auth {
  # auth_socket_path tregon për këtë prizë USERDB si parazgjedhje. Është tipike
  # përdoret nga dovecot-lda, doveadm, ndoshta procesi IMAP, etj. Përdoruesit që kanë
  # Lejet e plota për këtë fole janë në gjendje të marrin një listë të të gjithë emrave të përdoruesve dhe
  # Merrni rezultatet e kërkimeve të të gjithëve të të gjithëve.
  # 
  # Mënyra e paracaktuar 0666 lejon këdo që të lidhet me prizën, por
  # Kërkimet e përdoruesit do të kenë sukses vetëm nëse përdoruesi kthen një fushë "uid" që
  # përputhet me UID -in e procesit të telefonuesit. Gjithashtu nëse UID ose GID i telefonuesit përputhet me
  # UID ose gid i Socket kërkimi ka sukses. Thingdo gjë tjetër shkakton një dështim.
  # 
  # Për t'i dhënë telefonuesit leje të plota për të kërkuar të gjithë përdoruesit, vendosni mënyrën
  # diçka tjetër se 0666 dhe dovecot lejon kernelin të zbatojë
  # Lejet (p.sh. 0777 lejojnë të gjithë lejet e plota).
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # Procesi i punëtorëve të autorit është i ekzekutuar si rrënjë si parazgjedhje, në mënyrë që të mund të hyjë
  # /etj/hije. Nëse kjo nuk është e nevojshme, përdoruesi duhet të ndryshohet në
  # $ default_interal_user.
  # Përdoruesi = rrënjë
}

service dict {
  # Nëse përdoret proxy DICT, proceset e postës duhet të kenë qasje në prizën e tij.
  # Për shembull: mode = 0660, grup = vmail dhe global mail_access_groups = vmail
  unix_listener dict {
    # Mënyra = 0600
    # Përdoruesi =
    # grup =
  }
}
Edhe një herë, sigurohuni që të zëvendësoni domenin në të gjitha këto skedarë, femmebabe.com, me domenin që keni zgjedhur. Redaktoni skedarin tjetër, konfigurimin e dovecot,

nano config/etc_dovecot_dovecot
Dhe shtoni këto linja

## Skedar konfigurimi ovecot

# Nëse jeni me nxitim, shihni http://wiki2.dovecot.org/quickconfiguration

# Komanda "doveconf -n" jep një prodhim të pastër të cilësimeve të ndryshuara. E përdor atë
# Në vend të kopjimit dhe ngjitjes së skedarëve kur postoni në listën e postës Dovecot.

# '# 'Karakteri dhe gjithçka pasi të trajtohet si komente. Hapësirë ​​shtesë
# dhe skedat injorohen. Nëse doni të përdorni njërën nga këto në mënyrë të qartë, vendosni
# value inside quotes, eg.: key = "# Char dhe gjurmimi i hapësirës së bardhë "

# Shumica (por jo të gjitha) cilësimet mund të tejkalohen nga protokolle të ndryshme dhe/ose
# IP -të e burimit/destinacionit duke vendosur cilësimet brenda seksioneve, për shembull:
# Protokolli IMAP {}, Lokal 127.0.0.1 {}, Remote 10.0.0.0/8 {}

# Vlerat e paracaktuar tregohen për secilën cilësim, nuk kërkohet të mosveproni
# ato Këto janë përjashtime për këtë edhe pse: asnjë seksion (p.sh. hapësira e emrave {})
# ose cilësimet e shtojcave shtohen si parazgjedhje, ato renditen vetëm si shembuj.
# Shtigjet janë gjithashtu vetëm shembuj me parazgjedhjet e vërteta që bazohen në konfigurim
# opsione. Shtigjet e listuara këtu janë për konfigurim --Prefix =/usr
# --sysconfdir=/etc --localstatedir=/var

# Aktivizo protokollet e instaluara
!include_try /usr/share/dovecot/protocols.d/*.protocol

# Një listë e ndarë me presje të IP -ve ose ushtrive ku të dëgjoni për lidhje.
# "*" dëgjon në të gjitha ndërfaqet IPv4 ",:" dëgjon në të gjitha ndërfaqet IPv6.
# Nëse doni të specifikoni porte jo të paracaktuara ose ndonjë gjë më komplekse,
# Redakto Conf.D/Master.Conf.
# Dëgjo = *, ::

# Drejtoria Baza ku të ruani të dhënat e ekzekutimit.
# base_dir =/var/run/dovecot/

# Emri i këtij instanca. Në doveadm të konfigurimit shumë-instance dhe komanda të tjera
# mund të përdorë -i <instanca_name> për të zgjedhur se cili shembull është përdorur (një alternative
# te -c <config_path>). Emri i shembullit i shtohet gjithashtu proceseve dovecot
# në daljen e PS.
# instanca_name = dovecot

# Mesazh përshëndetje për klientët.
# login_greeting = dovecot gati.

# Lista e ndarë në hapësirë ​​e vargut të besueshëm të rrjetit. Lidhjet nga këto
# IP -të lejohen të tejkalojnë adresat dhe portet e tyre IP (për prerjet dhe
# për kontrollet e vërtetimit). Disable_plainText_auth gjithashtu injorohet për të
# Këto rrjete. Në mënyrë tipike ju do të specifikoni serverët tuaj të proxy IMAP këtu.
# login_trusted_networks =

# Lista e ndarë në hapësirë ​​e bazave të kontrollit të hyrjes së hyrjes (p.sh. TCPWRAP)
# login_access_sockets =

# Me proxy_maybe = po nëse destinacioni proxy përputhet me ndonjë prej këtyre IP -ve, mos bëj
# Proxying. Kjo nuk është e nevojshme normalisht, por mund të jetë e dobishme nëse destinacioni
# IP është p.sh. IP i një balanceri ngarkese.
# auth_proxy_self =

# Tregoni më shumë tituj të procesit të foljes (në PS). Aktualisht tregon emrin e përdoruesit dhe
# Adresa IP. E dobishme për të parë se kush janë në të vërtetë duke përdorur proceset IMAP
# (p.sh. kuti postare të përbashkëta ose nëse e njëjta UID përdoret për llogari të shumta).
# verbose_proctitle = jo

# Nëse të gjitha proceset do të vriten kur Procesi Master Dovecot mbyllet.
# Vendosja e kësaj në "jo" do të thotë që Dovecot mund të përmirësohet pa
# duke detyruar lidhjet ekzistuese të klientëve të mbyllen (megjithëse mund të jetë edhe kjo
# Një problem nëse azhurnimi është p.sh. për shkak të një rregullimi të sigurisë).
# Shutdown_clients = po

# Nëse jo-zero, ekzekutoni komandat e postës përmes kësaj shumë lidhje me serverin Doveadm,
# në vend që t'i drejtoni ato direkt në të njëjtin proces.
# doveadm_worker_count = 0
# Prizë ose host unix: porti i përdorur për t'u lidhur me serverin Doveadm
# doveadm_socket_path = doveadm-server

# Lista e ndarë në hapësirë ​​e variablave të mjedisit që janë ruajtur në dovecot
# Fillimi dhe u kalua në të gjitha proceset e fëmijës së saj. Ju gjithashtu mund të jepni
# çelës = çifte vlerash për të vendosur gjithmonë cilësime specifike.
# Import_environment = tz

## 
## Cilësimet e serverit të fjalorit
## 

# Fjalori mund të përdoret për të ruajtur çelësin = listat e vlerës. Kjo përdoret nga disa
# Shtojca. Fjalori mund të arrihet ose direkt ose megjithëse a
# Serveri i Fjalorit. Emrat e fjalorit të mëposhtëm të bllokimit të diktave të kodit të URI -ve
# Kur përdoret serveri. Këto më pas mund të referohen duke përdorur URI në format
# "Proxy :: <name>".

dict {
  # kuota = mysql: /andc/dovecot/dovecot-dic--sql.conf.ext
}

# Shumica e konfigurimit aktual përfshihen më poshtë. Emrat e skedarëve janë
# Të renditura së pari me vlerën e tyre ASCII dhe u analizuan në atë mënyrë. 00-prefiksat
# Në skedarët e skedarëve kanë për qëllim ta bëjnë më të lehtë kuptimin e renditjes.
!include conf.d/*.conf

# Një skedar konfigurimi gjithashtu mund të përpiqet të përfshihet pa dhënë një gabim nëse
# Nuk është gjetur:
!include_try local.conf

passdb {
  driver = passwd-file
  args = /etc/dovecot/passwd
}
userdb {
  driver = passwd
}

protocols = imap pop3

# Lejon Dovecot të dëgjojë të gjitha lidhjet hyrëse (IPv4 / IPv6)

listen = *, ::
Shtoni një fjalëkalim për përdoruesin e dovecot:

nano config/etc_dovecot_passwd
Pjesa e parë e skedarit, para zorrës së trashë, është emri i përdoruesit. Pjesa e fundit, "YourPassword", tregon fjalëkalimin që dëshironi të jepni serverin tuaj të postës.

team:{plain}yourpassword
Tjetra, konfigurimi i opendkim

nano config/etc_opendkim.conf
Dhe shtoni këto rreshta:

# Ky është një konfigurim themelor për nënshkrimin dhe verifikimin. Mund të jetë lehtësisht
# Përshtatur për t'iu përshtatur një instalimi themelor. Shiko opendkim.conf (5) dhe
# /usr/share/doc/opendkim/examples/opendkim.conf.sample për të plotë
# Dokumentacioni i parametrave të konfigurimit në dispozicion.

Syslog			yes
SyslogSuccess		yes
# Regjistrohuni jo

# Parametrat e zakonshëm të nënshkrimit dhe verifikimit. Në Debian, titulli "nga" është
# i tepruar, sepse shpesh është çelësi i identitetit që përdoret nga sistemet e reputacionit
# dhe kështu disi të ndjeshëm ndaj sigurisë.
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# Nënshkrimi i domenit, selektorit dhe çelësit (kërkohet). Për shembull, kryeni nënshkrimin
# Për domenin "shembull.com" me selektorin "2020" (2020._domainkey.example.com),
# duke përdorur çelësin privat të ruajtur në /etc/dkimkeys/example.private. Më kokrrizore
# Opsionet e konfigurimit mund të gjenden në /usr/share/doc/opendkim/readme.opendkim.
# Shembull i domenit.com
# Zgjedhësi 2020
# Keyfile /etc/dkimkeys/example.private

# Në Debian, Opendkim drejton si përdorues "Opendkim". Kërkohet një Umask prej 007
# Përdorimi i një fole lokale me MTA që hyjnë në prizë si një jo-privilegjuar
# Përdoruesi (për shembull, Postfix). Ju mund të duhet të shtoni përdoruesin "PostFix" në grup
# "Opendkim" në atë rast.
UserID			opendkim
UMask			007

# Fole për lidhjen MTA (kërkohet). Nëse MTA është brenda një burgu Chroot,
# Duhet të sigurohet që priza të jetë e arritshme. Në Debian, Postfix shkon në
# një kroot në/var/spool/postfix, prandaj do të duhej të ishte një fole UNIX
# konfiguruar siç tregohet në rreshtin e fundit më poshtë.
# Fole lokale: /run/opendkim/opendkim.sock
# Inet Socket: 8891@localhost
# Fole inet: 8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Pritësit për të cilët të nënshkruajnë në vend se të verifikoni, parazgjedhja është 127.0.0.1. Shoh
# Seksioni i Operacionit të Opendkim (8) për më shumë informacion.
# InternalHosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# Spiranca e besimit mundëson DNSSEC. Në Debian, jepet dosja e spirancës së besimit
# nga paketa dns-root-të dhëna.
TrustAnchorFile		/usr/share/dns/root.key
# Serverat e emrave 127.0.0.1

# Harta e fushave nga adresat në çelësat e përdorur për të nënshkruar mesazhe
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# Një grup i ushtrive të brendshme, posta e të cilëve duhet të nënshkruhet
InternalHosts       /etc/opendkim/trusted.hosts

nano config/etc_default_opendkim
Dhe shtoni këto linja

# Shënim: Ky është një skedar i konfigurimit të trashëgimisë. Nuk përdoret nga opendkim
# shërbimi i sistemuar. Ju lutemi përdorni parametrat përkatës të konfigurimit në
# /etc/opendkim.conf në vend.
# 
# Më parë, dikush do të redaktonte cilësimet e paracaktuara këtu, dhe pastaj ekzekutimin
# /lib/opendkim/opendkim.service.generate për të gjeneruar skedarë të tejkaluar të sistemit në
# /etc/systemd/system/opendkim.service.d/override.conf dhe
# /etc/tmpfiles.d/opendkim.conf. Ndërsa kjo është akoma e mundur, tani është
# Rekomandohet të rregulloni cilësimet direkt në /etc/opendkim.conf.
# 
# Daemon_opts = ""
# Ndryshoni në/var/spool/postfix/run/opendkim për të përdorur një fole UNIX me
# Postfix në një Chroot:
# Rundir =/ishte/spool/postfix/vrap/opendkim
RUNDIR=/run/opendkim
# 
# Uncomment për të specifikuar një fole alternative
# Vini re se përcaktimi i kësaj do të tejkalojë çdo vlerë fole në opendkim.conf
# Default:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Dëgjoni të gjitha ndërfaqet në portin 54321:
# Fole = inet: 54321
# Dëgjoni në Loopback në portin 12345:
# Fole = inet: 12345@localhost
# Dëgjoni është 192.0.2.1 është porti 12345:
# Fole = inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Kur të jemi të gatshëm të vendosim serverin tonë Postfix, ne do të ekzekutojmë kodin e mëposhtëm, me emrin e duhur të domain -it të ngulitur. Filloni duke krijuar një skenar

touch scripts/postfixsetup
sudo chmod a+x scripts/postfixsetup
nano scripts/postfixsetup
Tani, në Nano, redaktori i tekstit, modifikoni këtë skedar në mënyrë që të përfshijë emrin tuaj të domain në vend të femmebabe.com.

# / bin / bash
# Setup Postfix
cd $DIR
echo "Mail services configuration"
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
sudo cp config/etc_postfix_main.cf /etc/postfix/main.cf
sudo cp config/etc_postfix_master.cf /etc/postfix/master.cf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo cp config/etc_dovecot_conf.d_10-auth.conf /etc/dovecot/conf.d/10-auth.conf
sudo cp config/etc_dovecot_conf.d_10-master.conf /etc/dovecot/conf.d/10-master.conf
sudo cp config/etc_dovecot_dovecot.conf /etc/dovecot/dovecot.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_opendkim.conf /etc/opendkim.conf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo adduser postfix opendkim
sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys
sudo mkdir /etc/opendkim/keys/femmebabe.com
sudo mkdir /var/spool/postfix/opendkim
sudo echo "*@femmebabe.com     sendonly._domainkey.femmebabe.com" | sudo tee -a /etc/opendkim/signing.table
sudo echo "sendonly._domainkey.femmebabe.com    femmebabe.com:sendonly:/etc/opendkim/keys/femmebabe.com/sendonly.private" | sudo tee -a /etc/opendkim/key.table
sudo echo "127.0.0.1" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "localhost" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "*.femmebabe.com" | sudo tee -a /etc/opendkim/trusted.hosts
sudo chown -R opendkim:opendkim /etc/opendkim
sudo opendkim-genkey -b 2048 -d femmebabe.com -D /etc/opendkim/keys/femmebabe.com -s sendonly -v
sudo chmod go-rw /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys/femmebabe.com/sendonly.private
sudo chown opendkim:postfix /var/spool/postfix/opendkim
cd $DIR
sudo cp mailbox/* /var/mail/
sudo chown :users /var/mail/*
sudo chmod -R a+rwx /var/mail/*
sudo systemctl restart opendkim postfix dovecot
sudo cat /etc/opendkim/keys/femmebabe.com/sendonly.txt | tr -d '\n' | sed 's/\s//g' | sed 's/""//g' | awk -F'[)(]' '{print $2}'
Tani, ekzekutoni skenarin e përfunduar për të konfiguruar Postfix, Opendkim dhe Dovecot.

./scripts/postfixsetup
Pasi të ketë ekzekutuar ky skenar, kopjoni rreshtin e fundit që shtyp dhe ngjitni atë në konfigurimin tuaj DNS si vlerë për Sendonly._DomainKey. Ky është çelësi Opendkim i përdorur për të identifikuar domenin tuaj kur dërgoni postë të sigurt. E mrekullueshme! Brenda disa ditësh, duhet të jeni në gjendje të dërgoni postë nga serveri me kusht që gjithçka të konfigurohet si duhet. Nëse thjesht keni konfiguruar DNS për serverin tuaj të postës, duhet të duhen më pak se 72 orë që regjistrimet të azhurnohen. Zakonisht është shumë më e shpejtë. Ju mund të kontrolloni nëse serveri juaj po punon duke përdorur këtë komandë, furnizoni emailin tuaj:

echo “test” | mail -s “Test Email” youremail@gmail.com
Nëse gjithçka duket se po funksionon si duhet, duhet të jeni në gjendje të dërgoni email me serverin tuaj. Nëse nuk po funksionon, provoni të shikoni shkrimet për të parë se cili mund të jetë gabimi.

tail –lines 150 /var/log/mail.log
Kjo do të ofrojë informacione foljore në lidhje me postën që po dërgohet nga serveri dhe nëse po funksionon siç duhet. Ju duhet të jeni në gjendje të shihni emailin edhe në kutinë tuaj, nëse nuk është aty, kontrolloni dosjen tuaj të spamit. Ju gjithashtu do të duhet të konfiguroni cilësimet tuaja në cilësimet tuaja.py në mënyrë që serveri juaj i postës elektronike të mund të flasë me aplikacionin tuaj Django, projektin. Shtoni ose zëvendësoni këto rreshta në cilësimet tuaja

EMAIL_HOST = DOMAIN
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = 'team@femmebabe.com'
EMAIL_HOST_USER = 'team' # 'Love@mamasheen.com'
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
Vini re se ne jemi duke përdorur një skedar konfigurimi për të marrë fjalëkalimin. Le ta ngarkojmë këtë skedar në cilësimet si kështu, në fillim të skedarit.:

import os
import json

# Konfigurimi i hapur dhe i ngarkuar
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Le ta krijojmë këtë skedar dhe të shtojmë një çelës sekret për të, si dhe fjalëkalimin e postës. Për të gjeneruar një çelës sekret, përdorni këtë komandë, me çfarëdo gjatësi që ju pëlqen në fund:

openssl rand -base64 64
Tani, kopjoni tekstin që OpenSSL gjeneroi dhe modifikoni /etc/config.json

sudo nano /etc/config.json
Shtoni rreshtat e mëposhtëm në skedarin tuaj, me çelësin që hapet i gjeneruar si çelësi sekret.

{
	"SECRET_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-generated-using-openssl)",
	"EMAIL_HOST_PASSWORD": "yourpassword"
}
Formati JSON është i thjeshtë dhe i lehtë për t’u përdorur, ne mund të deklarojmë çelësa të tjerë që duam t'i përdorim edhe në projektin tonë në këtë mënyrë, dhe t'i mbajmë të ndara nga drejtoria jonë e projektit, në mënyrë që përdoruesit e tjerë të mos mund t'u shkruajnë atyre dhe kështu që ata nuk mund të lexohen vetëm nga drejtoria jonë e projektit. Kjo është praktikë e rekomanduar për çelësat API, nga të cilat ne do të përdorim më shumë se disa këtu. Ju gjithashtu do të dëshironi të rezervoni projektin tuaj për t'u siguruar që gjithçka është ruajtur dhe do të keni mundësi të rikuperoni punën tuaj më vonë edhe nëse nuk dëshironi më të merrni me qira një server.

sudo backup
Tani, provoni të dërgoni një email HTML nga serveri në internet, me kusht që të dërgoni një nga linja e komandës po funksionon. Kërkoni shembullin tuaj të përdoruesit në guaskë dhe dërgoni një email HTML tek ai përdorues përmes Django. Ndryshoni emrin tim në kodin, Charlotte, në emrin tuaj të përdoruesit.

python manage.py shell
from django.contrib.auth.models import User
u = User.objects.get(username='Charlotte')
from users.email import send_welcome_email
send_welcome_email(u)
exit()
Nëse komanda e parë nuk funksionon, sigurohuni që të përdorni

source venv/bin/activate
Me kusht që gjithçka të jetë e vendosur si duhet, tani do të merrni një email të mirëseardhur në kutinë tuaj postare të dërguar nga aplikacioni juaj në internet. Punë e mirë! Ju keni bërë një rrugë të gjatë. Doja të shtoja, nëse jeni duke luftuar ndonjëherë me gabime fare ndërsa punoni në një projekt si ky, mos hezitoni të kërkoni përgjigje dhe të kërkoni ndihmë. Google, midis motorëve të tjerë të kërkimit, janë burime të shkëlqyera për të kërkuar ndihmë për programim. Thjesht kërkoni për gabimin që po merrni, dhe do të jeni në gjendje të shihni se si njerëzit e tjerë e zgjidhin problemin. Gjithashtu, ju jeni të mirëpritur të kontaktoni me mua, arsimtarët tuaj (mësuesit, profesorët, tutorët), çdo bashkëmoshatar në internet që janë në dispozicion për ndihmë programimi, ose konsultoheni përsëri me këtë libër ose burime të tjera për të gjetur zgjidhje për çështjet që po përjetoni. E kuptoj që kjo nuk është e lehtë, por edhe nëse keni lexuar në këtë larg dhe nuk po shkruani ndonjë kod, ju po mësoni shumë për ndërtimin e një aplikacioni në internet nga e para. Pat veten në anën e pasme, ju jeni duke bërë një të shkëlqyeshmepunë Faleminderit që morët kohën për të lexuar këtë Udhëzues për Zhvillimin e Uebit të Edicionit të Tretë. Në botimet e ardhshme, unë do të përfshij më shumë shembuj të rëndësishëm të diskutuar në fillim të dokumentit dhe ne do të zhyten shumë më thellë në botën e softuerit dhe zhvillimit të harduerit. Rrini zgjuar për atë që do të vijë, dhe unë mezi pres t'ju mësoj se si të ndërtoni një softuer të jashtëzakonshëm. Shihemi në tjetrin






I afërt
Faqe 1
Kërcim
Shih artikullin e plotë
Vazhdoni të lexoni

Blej | Blej me kripto



https://glamgirlx.com/sq/practical-web-based-deep -


(Klikoni ose prekni për të shkarkuar imazhin)
Argëtim profesional, foto, video, audio, transmetim të drejtpërdrejtë dhe lojëra të rastësishme, si dhe skanim të identitetit, zhvillim në ueb dhe shërbime të zëvendësimit.

Më lini një këshillë në bitcoin duke përdorur këtë adresë: 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2025

Kushtet e Shërbimit