Lajme - Sit
Tre trembëdhjetë - lojë me karta në internet Luaj tre trembëdhjetë me një mik duke klikuar lidhjen më poshtë për të gjeneruar një kod ftese ose për t'u bashkuar me një lojë.Ftesë me kod lotteh.com/games/"titulli =" bashkohuni me një lojë "> bashkohuni me lojën
Shpërthej

nga Daisy / Shiko | Blej | Bleni me cryptocurrency



Luaj Ngjyra Sudoku Online - Lojë Falas Colordoku Kjo është një lojë falas për të luajtur me ngjyra Sudoku (Colordoku).

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


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ë të projekteve që shprehin krijimtarinë, sigurojnë lehtësinë e përdorimit dhe funksionimin, portretizimin e humbjes dhe karakterit, dhe të sigurojnë lehtësinë e përdorimit, si dhe shërbimet e rëndësishme që janë të gjitha ato që janë tërheqëse, të gjitha ato që janë tërheqëse, që të sigurojnë lehtësinë e përdorimit, të sigurojnë lehtësinë e përdorimit të përdorimit, të sigurojnë lehtësinë e përdorimit, të ofrojnë lehtësinë e përdorimit. 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 butona të shtypjes së kohës, dhe veçanërisht duke humbur para duke paguar për pajtime të shtrenjta për softuer pak njerëz që donin të përdorin gjithsesi kufizimet e tij në lehtësi të përdorimit dhe fleksibilitetit. Nëse keni disa minuta për të lexuar përmes këtij libri dhe të mësoni atë që unë 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 për të mësuar të kodoni dhe shkruaj softuerin tuaj, të merrni këtë libër në shtëpi dhe të lini mënjanë ca kohë për të mësuar të ndërtoni audiencën tuaj me ndikim, të fuqishëm, të efektshëm dhe të rëndësishëm në internet, një faqe në internet që është e gjithë mbi ju dhe bën saktësisht se çfarë dëshironi dhe plotësoni nevojat e audiencës suaj. 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, unë do t'ju ndërtoja YouTube, tiktok, Twitter, Google, apo edhe një aplikacion të sigurisë së lartë vetëm që mund të hyni. 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 ndërtimin e një aplikacioni (faqja e internetit) 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ës, 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 kushte 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 në gjithçka që bëni. Unë jam një inxhinier vetë, një softuerZhvilluesi, dhe një student, dhe unë po e 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 kanë nevojë ta bëjnë jetën e tyre më të lehtë duke dhënë shembuj për të kopjuar që përshtaten së bashku si një enigmë e madhe në një aplikacion të funksionimit, të dobishëm, të madh, funksional, koheziv dhe angazhues 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 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 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ë e kuptoni atë, do të hasni në mënyrë të pashmangshme vështirësi me informacionin që ju po gllabëroni dhe madje po botoni. 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 apo edhe të 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 larguar në një rrugë të çmendurisë që lëUnë 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 ...
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ë të projekteve që shprehin krijimtarinë, sigurojnë lehtësinë e përdorimit dhe funksionimin, portretizimin e humbjes dhe karakterit, dhe të sigurojnë lehtësinë e përdorimit, si dhe shërbimet e rëndësishme që janë të gjitha ato që janë tërheqëse, të gjitha ato që janë tërheqëse, që të sigurojnë lehtësinë e përdorimit, të sigurojnë lehtësinë e përdorimit të përdorimit, të sigurojnë lehtësinë e përdorimit, të ofrojnë lehtësinë e përdorimit. 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ë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 butona të shtypjes së kohës, dhe veçanërisht duke humbur para duke paguar për pajtime të shtrenjta për softuerët që disa njerëz donin të përdorin gjithsesi kufizimet e tij në lehtësi të përdorimit dhe fleksibilitetit. Nëse keni disa minuta për të lexuar përmes këtij libri dhe të mësoni atë që unë 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 për të mësuar të kodoni dhe shkruaj softuerin tuaj, të merrni këtë libër në shtëpi dhe të lini mënjanë ca kohë për të mësuar të ndërtoni audiencën tuaj me ndikim, të fuqishëm, të efektshëm dhe të rëndësishëm në internet, një faqe në internet që është e gjithë mbi ju dhe bën saktësisht se çfarë dëshironi dhe plotësoni nevojat e audiencës suaj. 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, unë do t'ju ndërtoja YouTube, tiktok, Twitter, Google, apo edhe një aplikacion të sigurisë së lartë vetëm që mund të hyni. 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 ndërtimin e një aplikacioni (faqja e internetit) 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ës, 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 kushte 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 në gjithçka që bëni. Unë jam një inxhinier vetë,Zhvilluesi, dhe një student, dhe unë po e 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 kanë nevojë ta bëjnë jetën e tyre më të lehtë duke dhënë shembuj për të kopjuar që përshtaten së bashku si një enigmë e madhe në një aplikacion të funksionimit, të dobishëm, të madh, funksional, koheziv dhe angazhues 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ë e kuptoni atë, do të hasni në mënyrë të pashmangshme vështirësi me informacionin që ju po gllabëroni dhe madje po botoni. 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 apo edhe të keni sukses në një mënyrë të gabuar: Kështu e arrita këtë larg, dhe pse unë mund t'ju sjell këtë tekst dhe t'ju ndihmoj të keni sukses pa u larguar 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 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 mund të aplikoni ato 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ë kem sukses në pikën ku 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. You can find code here, instructions for how to learn to code, information on debugging code and fixing errors, troubleshooting steps, instructions on how to back up and save your code, re-deploy if anyone breaks your code, secure your code, deploy your code, build interactive websites that are entertaining, engaging, and addictive, and you will get a sense of who I am, why this is important, and how to portray yourself, your app and company image, as well as the software 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 militantët 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 në mënyrë që të mbrojmë softuerin tonë dhe të demonstrojmë vetëmbrojtje dhe revizion. 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 në gome silikoni përkatësisht. 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ësishtE veçuar, funksionale dhe e 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ë që kompanitë e moshuara operojnë në, dhe nuk i bën thirrje prapa, kompanive të ndërlikuara të krijuara për të fituar para për njerëzit që nuk po bëjnë 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 linjë kodi që do t'ju duhet të shkruani si një shembull, të gatshëm për t'u grumbulluar së bashku në softuer ju dhe mbështetësit tuaj, mysafirë, klientele, klientele,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, veçori 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 komunikimi Bluetooth dhe afër Field (NFC). Ky libër do t'ju mësojë se si të përdorni një kompjuter të rrjetuar, 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, stilin gjëra të bukura duke përdorur CSS Styles me BOOTSAP, duke u mundësuar hyrjes së përdoruesve dhe ndërveprimit të rrjetit përmes mesazheve të rrjetave të tjera, të cilat kanë të bëjnë me mesazhe të tjera, duke përdorur mesazhe të tjera, të cilat përdorin mesazhe të tjera, të cilat mund të jenë të tjera, duke përdorur mesazhe të tjera, të cilat përdorin mesazhe të tjera, të tilla, duke përdorur mesazhe të tjera, të tilla, duke përdorur mesazhe të tjera, të tilla, duke përdorur mesazhe të tjera, të tilla, duke përdorur mesazhe të tjera, duke përdorur mesazhe të tjera, të cilat përdorin, duke përdorur mesazhe të tjera, të cilat përdorin, duke përdorur mesazhe të tjera, të tilla, duke përdorur, me të cilat, duke përdorur, duke përdorur, duke përdorur mesazhe të tjera. 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 të 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 duke përdorur faqet e internetit të tjera për të ndërtuar rrjetin më të mirë të faqeve të internetit që mund të lidheni direkt me tuajat, në mënyrë që të ndani të gjitha informacionet e dobishme që ju keni për të ofruar, dhe madje edhe më të rëndësishme të sjellin njerëz në programin tuaj dhe biznesin. 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 një softuer të dobishëm për uebin 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 përmes reklamave, si ta 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ë kërkime të zakonshme 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 e fundit (klientelën tuaj), dhe shitjen e vetes 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, softueri juaj dhe kompania juaj të 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 nevoe 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 të mësuarit 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ërbejnë 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 për 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 metrikat e parashikimit të buruara nga imazhet, siç është natyra e imazhit si një imazh autentik, i transferuar nga kompjuteri, ose një kopje optike (një foto e imazhit), ose një imazh i imazhit). 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, ndoshta me një shenjë konfirmimi për secilën hyrje të re ose adresë të re IP, por nëse po ndërtoni një shkallë të gjerë, të lehtë për t’u përdorur, në thelb të sigurt dhe softuer 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. This toolkit can render text, the webpages you see, and can also record images, audio and video (like a photo of a face or a state ID), can read and write to Bluetooth radio devices, and can read and write to near field transponder tags, inexpensive key cards, fobs, stickers, rings and even chip implants with unique serial numbers that can be read and written to with data generated and validated by a web server tied to the web site. 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 i rrjetuar në rrjet që funksionon për ju, bën ofertat tuaja, dhe duket dhe ndjehet mirë. Ku te filloj: Ju jeni të mirëpritur të kaloni seksionin me të cilin 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 dhe duke dokumentuar raste 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ë miku ose të afërmi, i cili mund të jetë i interesuar të mësojë vetë zhvillimin e uebit, dhe madje konsideroni ta huazoni atë përsëri dhe të mësoni prej tyre për të plotësuar boshllëqet ku unë ju dështova si mësues, ose mësues të tjerë kanë bërë 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 prekjen 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 gjë.) Git është një softuer i kontrollit të verifikimit që ju lejon të rezervoni redaktimet në softuerin tuaj 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ë automatikisht, të cilin ne do ta 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 operacionet e mësimit të thellë në kompjuterin tuaj. Ne do ta transferojmë kodin në një server në internet në të ardhmen e afërt, por 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 ta bërë këtë. 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 (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ë modifikojmë 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 më pas të lundrojmë në një shfletues në internet në kompjuterin që drejton kodin në http: // localhost: 8000 dhe të shohim një faqe në internet (funksionon!) Qetë serverin me kontrollin C, të njëjtën 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). Shabllonet, të cilat janë kodi html dhe gjuha e shablloneve dhe urë hendekun midis Python dhe HTML, që do të thotë se informacioni i Python mund të shërbehet si kod html që dikush mund të hyjë dhe mund të sigurojë një faqe në internet me qasje të kufizuar, ndërsa e bën kodin Python të arritshëm në internet dhe të dobishëm për një larmi qëllimesh në një pajisje të largët që nuk e bëneed 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ë kanale të shpejta, të komunikimit të thjeshtuar, selino, të cilat ekzekutojnë detyra asinkrone, dhe një numër të pjesëve të tjera të softuerit për zgjatjen e Django, veçanërisht në funksionet e shikimit, ku ekzekutohet shumica e kodit. 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 pamjes kanë tre përbërës, përbërësin e rrugës, i cili i tregon serverit ku pamja ekziston brenda serverit (shtegu URL që përdoruesi e shtyp në shiritin e navigimit për të hyrë në faqen e internetit), përbërësi i shikimit ku pamja është specifikuar, dhe një emër miqësor për pamjen, në mënyrë që të jetë e lehtë për të marrë modelin e tij kur të punoni me një model, veçanërisht në mënyrë që të jetë emri që mund të ndryshohet dhe të azhurnohet nëse është e nevojshme të bëni hapësirë ​​për një tjetër pamje ose të merrni një emër më shumë. 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 secilës 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ë personazh i fshirë aksidentalisht, 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 me formën ndërvepron me të. 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 tij, 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ë. Ai 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ë lak që i jep secilit postim në listën e postimeve si një paragraf në shabllon. 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ërqendrohemi në bërjen e faqes sonë më të sigurt, duke u mundësuar përdoruesve të regjistrohen me një emër përdoruesi dhe kodi, dhe përfundimisht edhe informacione më të rëndësishme që do t'ju ndihmojnë 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/format nano.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ë ishin të fundit në sit, disa informacione rreth tyre, si një biografi, zona kohore, etj. Gjithashtu, do të na duhet të azhurnojmë modelin tonë të ushqimit, të postojmë, të japim llogari për modelin e përdoruesit dhe postimet e atributeve 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 të fshirjes për të siguruar që postimet janë fshirë me përdoruesit, argumente të pavlefshme dhe të zbrazëta për t'u siguruar që ne mund ta heqim përdoruesin nëse është e nevojshme, dhe për të akomoduar mungesën e një përdoruesi në postime që ne kemi krijuar tashmë, dhe një emër të lidhur, të cilin mund t'i 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/bin/rezervë, e cila 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ë faqe në internet Django, dhe ju jeni të mirëpritur të zgjidhni cilindo 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.

# … Shuma

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 të identifikoheni 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ë "Stop" 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ë App/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 në sit dhe ta bëjmë më të ashpër që robotët të hyjnë në sit, së bashku me mënyrën e çaktivizimit të llogarive të përdoruesve, dhe të verifikojmë identitetin e një përdoruesi me një skanim të ID -së së tyre ose një skanim biometrik, si një gjurmë gishti ose njohje të 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ërdoruesve, 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

# Vërtetoni përdoruesin duke përdorur emailin ose numrin e telefonit të tyre
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 me 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 formularin
        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 gjithëpërfshirës të verifikimit, 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 4096 bit.

ssh-keygen -t rsa -b 4096
Krijoni një VPS që drejton 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 që 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, vërtetimi i 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

# Lejoni PO.
# ALLONITCPPORRIVE PO
# GatewayPorts nr
X11Forwarding yes
# X11DisplayOffset 10
# X11USELOCALHOST Po
# Pilula po
PrintMotd no
# Printlastlog po
# Tcpkeepalive po
# Përfundimi i Përgjithshëm në
# 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
# ALLONITCPPREWRING NO
# 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ë linjën sipas linjës. Rreshti i parë i tregon përpiluesit se ky është një skenar bash. Pastaj 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 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 që ne po krijojmë. 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, kopjet mbi skedarë, shkarkime dhe instalon pako ubuntu apt, varësitë e pythonit, konfiguron postfix, konfiguron postgresi 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
# Çaktivizo Iptables
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 riprodhuar", modifikoni skedarin e mëposhtëm në mjedisin virtual, Registry.py, për të ekspozuar gabimin.

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 Master (5) Manual (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 + Args
# (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 paraqitjen 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_trival =
# -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_restrictions =
# -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 oqmgr
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ë kroot:
# 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 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 kaloi 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: /etc/dovecot/dovecot-dict-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 fole: 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ë kroot:
# 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ë ato 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 ndonjë gabim 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

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Dy ngjyra lojtarësh sudoku online falas Luaj me ngjyra bashkëpunuese sudoku me një mik falas.Fto një mik Bashkohuni me një lojë
Shpërthej

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si të vesh bllokimin?


1. Filloni duke i rritur flokët deri në gjatësinë e dëshiruar. Flokët tuaj duhet të jenë të paktën 2-3 inç të gjatë për rezultatet më të mira.


2 Seksioni flokët tuaj në pjesë të vogla, madje edhe duke përdorur një krehër. Madhësia e seksioneve do të përcaktojë madhësinë e dreadlocks tuaj, prandaj sigurohuni që të zgjidhni një madhësi me të cilën jeni të kënaqur.


3. Filloni të bëni kthimin e secilës seksion të flokëve duke e shtrembëruar dhe duke e tërhequr fort drejt rrënjëve. Kjo do të krijojë nyje në flokë, të cilat përfundimisht do të formohen në dreadlocks.


4 Aplikoni dylli ose xhel në secilën pjesë të flokëve për të ndihmuar në mbajtjen e nyjeve në vend dhe inkurajimin e flokëve që të pjekin së bashku.


5. Vazhdoni të bëni kthimin dhe kthesën e secilës pjesë të flokëve derisa të keni përfunduar të gjithë kokën tuaj. Ky proces mund të jetë kohë, prandaj jini të durueshëm dhe bëni pushime sipas nevojës.


6 Pasi të jenë shtrembëruar të gjitha flokët tuaj, le të ulen për disa ditë për të lejuar që nyjet të shtrëngohen dhe të formohen në dreadlocks.


7 pas disa ditësh, ju mund të filloni të stiloni dhe të mirëmbani dreadlocks tuaj duke i larë ato me shampo pa mbetje dhe duke përdorur një goditje me grep për të ndihmuar në shtrëngimin e çdo nyje të lirshme.


8. Për t'i mbajtur dreadlocks tuaj të duken të rregullta dhe të rregullta, konsideroni të përdorni një shall ose bandana për t'i mbuluar ato kur flini ose në mjedise të ndyra. Mirëmbajtja dhe mirëmbajtja e rregullt do të ndihmojnë Dreadlocks tuaj të qëndrojnë të shëndetshëm dhe të gjallë.

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Unë dua të vesh grim. Si mund të vesh një përbërje magjepsëse?


Veshja e përbërjes magjepsëse zakonisht përfshin tipare të guximshme dhe të ekzagjeruara që rrisin bukurinë tuaj natyrore. Këtu janë disa këshilla se si të arrini një pamje magjepsëse të përbërjes:


1. Filloni me një bazë të përsosur duke aplikuar një abetare, fondacion dhe fshehës për të dalë edhe në tonin e lëkurës tuaj. Vendosni bazën tuaj me një pluhur të tejdukshëm për të siguruar mbulim të gjatë.


2. Përcaktoni vetullat tuaja me një laps balli ose pluhur për të kornizuar fytyrën tuaj. Plotësoni çdo zonë të rrallë dhe formoni faqet tuaja për të arritur një pamje të lëmuar.


3. Aplikoni një hije të shndritshme në një hije neutrale ose metalike në qepallat tuaja, duke u përqëndruar në qoshet e brendshme dhe qendrën e kapakut për të krijuar një efekt të ndritshëm. Përdorni një hije më të errët në rrudhë për të shtuar thellësinë dhe përkufizimin.


4. Rreshtoni sytë tuaj me një eyeliner të zi ose të errët kafe, duke u siguruar që të krijoni një efekt me krahë për dramën e shtuar. Përfundoni pamjen e syrit me disa pallto të bojë për vetulla të vëllimit ose rëna false për një pamje të guximshme dhe dramatike.


5. Shtoni një pop të ngjyrave në faqet tuaja me një skuqje në një ton rozë ose bukuroshe, duke e aplikuar atë në mollët e faqeve tuaja dhe duke u përzier lart drejt tempujve tuaj për një skuqje natyrale.


6. Plotësoni pamjen me një ngjyrë të guximshme të buzëve në një hije të kuqe, kumbull ose nudo, në varësi të preferencës tuaj personale. Përdorni një astar buzësh për të përcaktuar buzët tuaja dhe për të parandaluar çdo pendë ose gjakderdhje.


Mos harroni të përzieni të gjitha produktet tuaja të përbërjes pa probleme për një përfundim të lëmuar dhe të përsosur. Praktika dhe eksperimentimi janë thelbësore për të gjetur pamjen e përsosur të përbërjes magjepsëse që i përshtatet stilit dhe veçorive tuaja individuale.

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Pse duhet të përdor një mollë l në fjalën L?


Përdorimi i një Apple L në fjalën L mund të përmirësojë përvojën tuaj të shikimit në disa mënyra. Apple L është një pajisje transmetuese e njohur që ju lejon të përdorni me lehtësi dhe të shikoni shfaqjet tuaja të preferuara me video dhe audio me cilësi të lartë. Duke përdorur një Apple L në fjalën L, ju mund të shijoni vizuale të freskëta, të qarta dhe tinguj gjithëpërfshirës që do t'ju bëjnë të ndjeheni sikur keni të drejtë në mes të veprimit.


Për më tepër, Apple L ofron një ndërfaqe miqësore për përdoruesit që e bën të lehtë lundrimin nëpër episode, pauzë dhe skena të rivlerësimit dhe rregulloni përvojën tuaj të shikimit. Ju gjithashtu mund të përfitoni nga veçoritë si kërkimi i zërit dhe rekomandimet e personalizuara për t'ju ndihmuar të zbuloni përmbajtje të re për të shijuar.


Në përgjithësi, përdorimi i një Apple L në fjalën L mund t'ju ofrojë një përvojë premium transmetimi që do t'ju lejojë të zhytni plotësisht veten në botën tërheqëse të shfaqjes.

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Pse është më e sigurt të veshësh një maskë në publik?


Veshja e një maskë në publik është më e sigurt sepse ndihmon për të parandaluar përhapjen e pikave të frymëmarrjes që përmbajnë viruse, siç është COVID-19. Kur dikush me një virus vesh një maskë, ajo parandalon që pikat e tyre të frymëmarrjes të lëshohen në ajër dhe të infektojnë potencialisht të tjerët. Për më tepër, veshja e një maskë gjithashtu mund të mbrojë veshësin nga thithja e pikave të frymëmarrjes nga të tjerët që mund të infektohen. Kjo është veçanërisht e rëndësishme në situata kur distancimi shoqëror është i vështirë për tu mirëmbajtur, siç është në hapësirat e mbushura me njerëz ose në transportin publik. Në përgjithësi, veshja e një maskë është një mënyrë e thjeshtë dhe efektive për të ndihmuar në zvogëlimin e transmetimit të viruseve dhe për të mbrojtur si veten ashtu edhe ata përreth jush.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Cilat janë përfitimet e pirjes së çajit?


Pirja e çajit ka përfitime të shumta shëndetësore, duke përfshirë:


- I pasur me antioksidantë, të cilët ndihmojnë në mbrojtjen e trupit nga radikalët e lirë dhe të zvogëlojnë rrezikun e sëmundjeve kronike si kanceri dhe sëmundjet e zemrës.

- Përmban më pak kafeinë sesa kafe, duke siguruar një nxitje të energjisë më të butë dhe duke zvogëluar rrezikun e xhinseve ose pagjumësisë.

- Mund të përmirësojë shëndetin e zemrës duke ulur nivelin e kolesterolit dhe duke zvogëluar inflamacionin.

- Mund të ndihmojë në humbjen e peshës duke rritur metabolizmin dhe duke promovuar djegien e dhjamit.

- Mund të përmirësojë funksionin njohës dhe të ulë rrezikun e sëmundjeve neurodegjenerative si Alzheimer dhe Parkinson.

- Ndihmon në promovimin e relaksimit dhe zvogëlimin e niveleve të stresit.

- Mund të përmirësojë tretjen dhe shëndetin e zorrëve.

- Ndihmon për të mbajtur trupin të hidratuar dhe mund të kontribuojë në marrjen e përgjithshme të lëngjeve.

- Ofron një gamë të gjerë të aromave dhe ndryshimeve që i përshtaten preferencave individuale.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency



Si mund të ndërtoj një aplikacion në internet me stack të plotë me Django?


Ndërtimi i një aplikacioni të plotë në internet me Django përfshin disa hapa. Këtu është një skicë e përgjithshme e procesit:


1. Vendosni django: Së pari, instaloni django duke ekzekutuar `pip instaloni django` në linjën tuaj të komandës. Pastaj, krijoni një projekt të ri django duke ekzekutuar `django-admin startproject myProject`.


2. Krijoni aplikacione Django: Aplikacionet Django janë përbërës modularë të projektit tuaj që shërbejnë për qëllime specifike. Ju mund të krijoni aplikacione të shumta brenda projektit tuaj për të trajtuar funksionalitete të ndryshme.


3. Përcaktoni modele: Modelet në Django përdoren për të përcaktuar strukturën e tabelave tuaja të bazës së të dhënave. Krijoni modelet tuaja duke përcaktuar klasa në skedarin modele.py të secilës aplikacion.


4. Krijoni Pamje: Pamjet në Django janë funksione python që trajtojnë kërkesat e përdoruesve dhe përgjigjet e kthimit. Përcaktoni pikëpamjet për aplikacionin tuaj duke krijuar funksione në skedarin Views.py të secilës aplikacion.


5. Vendosni URL: URL -të në Django përdoren për të hartuar kërkesat e përdoruesve në pamje specifike. Përcaktoni modelet e URL -së për aplikacionin tuaj duke krijuar një skedar urls.py në secilën aplikacion dhe duke i përfshirë ato në skedarin kryesor URLS.py të projektit tuaj.


6. Krijoni shabllone: ​​Modelet në Django përdoren për të gjeneruar faqe HTML që i dërgohen shfletuesit të përdoruesit. Krijoni shabllone HTML për aplikacionin tuaj duke krijuar një dosje Templates në secilën aplikacion dhe duke shkruar kodin HTML në skedarë modelesh të veçanta.


7. Shërbyer skedarë statikë: skedarë statikë si CSS, JavaScript dhe imazhet shërbehen veçmas nga përmbajtja dinamike në Django. Konfiguroni cilësimet e skedarëve statikë në skedarin e cilësimeve të projektit tuaj për të shërbyer skedarë statikë nga dosja statike në secilën aplikacion.


8. Konfiguroni bazën e të dhënave: Vendosni cilësimet e bazës së të dhënave tuaja në skedarin Settings.py të projektit tuaj, duke përfshirë motorin e bazës së të dhënave, emrin, përdoruesin, fjalëkalimin dhe hostin.


9. Migroni bazën e të dhënave: Run `Python Manage.py Makemigrations` i ndjekur nga` Python Manage.py Migrate` në linjën tuaj të komandës për të krijuar dhe aplikuar migrimet e bazës së të dhënave bazuar në modelet tuaja.


10. Drejtoni serverin: Filloni serverin e zhvillimit django duke ekzekutuar `Python Manage.py Runserver` në linjën tuaj të komandës. Tani duhet të jeni në gjendje të hyni në aplikacionin tuaj në internet në `http: //127.0.0.1: 8000/` në shfletuesin tuaj.


Këto janë hapat themelorë për të ndërtuar një aplikacion të plotë në internet me Django. Nga këtu, ju mund të rregulloni dhe zgjeroni më tej aplikacionin tuaj duke shtuar vërtetimin, autorizimin, pikat e fundit të API, testimin dhe më shumë.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Sapo fillova të marr kontrollin e lindjes. Cilat janë efektet anësore më të zakonshme?


Efektet anësore më të zakonshme të pilulave të kontrollit të lindjes përfshijnë:


1. nauze

2. Butësia e gjirit

3. dhimbje koke

4. Shtimi në peshë

5. Ndryshimet e humorit

6. Spotting ose Bleeding Bleeding

7. Ndryshimet në epshi 

8. ACNE 

9. Frutja 


Shtë e rëndësishme të theksohet se çdo person mund të përjetojë efekte anësore të ndryshme, dhe disa individë mund të mos pësojnë fare. Nëse keni shqetësime për efektet anësore të kontrollit tuaj të lindjes, është më mirë të flisni me ofruesin tuaj të kujdesit shëndetësor.

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si mund të pres një server në internet nga shtëpia ime?


Pritja e një serveri në internet nga shtëpia juaj mund të bëhet duke ndjekur këto hapa:


1. Zgjidhni një softuer të serverit: Ju mund të zgjidhni nga opsione të ndryshme të softuerit të serverit si Apache, Nginx, Microsoft Internet Information Services (IIS), etj. Zgjidhni një që i përshtatet kërkesave tuaja.


2. Vendosni një adresë IP statike: Kontaktoni Ofruesin tuaj të Shërbimit të Internetit (ISP) dhe kërkoni një adresë IP statike për lidhjen tuaj në internet. Kjo do të sigurojë që faqja juaj e internetit të mbetet e arritshme edhe nëse adresa juaj IP ndryshon.


3. Konfiguroni ruterin tuaj: Hyni në panelin e administrimit të ruterit tuaj dhe portin përpara 80 (porti i paracaktuar për trafikun HTTP) në adresën IP të brendshme të serverit tuaj. Kjo do të lejojë që trafiku i jashtëm të arrijë serverin tuaj në internet.


4. Instaloni dhe konfiguroni softuerin e serverit: Instaloni softuerin e serverit në makinën tuaj të serverit dhe konfiguroni atë sipas nevojave tuaja, të tilla si vendosja e hosteve virtuale, certifikatat SSL, etj.


5. Testoni faqen tuaj të internetit: Kontrolloni nëse faqja juaj e internetit është e arritshme duke futur adresën tuaj IP statike në një shfletues në internet. Ju gjithashtu mund ta provoni atë duke përdorur mjete në internet si Pingdom ose GTMetrix.


6. Emri i domain dhe konfigurimi i DNS: Regjistroni një emër domain për faqen tuaj të internetit dhe vendosni regjistrimet DNS për të treguar adresën tuaj statike IP.


7. Masat e sigurisë: Implementimi i masave të sigurisë si firewalls, encryption, kopje rezervë të rregullt, etj., Për të mbrojtur serverin tuaj në internet nga kërcënimet në internet.


8. Monitoroni dhe mirëmbani: Monitoroni rregullisht serverin tuaj për çështjet e performancës, kërcënimet e sigurisë dhe azhurnimet e softuerit. Mbani të azhurnuar softuerin dhe aplikacionet e serverit tuaj për të siguruar funksionimin e qetë.


Ju lutemi vini re se mbajtja e një serveri në internet nga shtëpia juaj mund të mos jetë e përshtatshme për faqet e internetit të trafikut të lartë ose të dhëna të ndjeshme për shkak të rreziqeve të mundshme të sigurisë dhe gjerësisë së kufizuar të bandës. Konsideroni të përdorni një shërbim profesional të mbajtjes në internet për kërkesa të tilla.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si mund të marr publicitet dhe trafik organik për një faqe në internet?


1. Optimizimi i Motorit të Kërkimit (SEO): Optimizoni faqen tuaj të internetit për motorët e kërkimit për të përmirësuar dukshmërinë dhe renditjen në faqet e rezultateve të motorit të kërkimit.


2. Marketingu i përmbajtjes: Krijoni përmbajtje të vlefshme dhe të rëndësishme që tërheq dhe angazhon audiencën tuaj të synuar. Kjo mund të përfshijë postime në blog, artikuj, video, infografikë dhe forma të tjera të përmbajtjes.


3. Marketingu i mediave sociale: Promovoni faqen tuaj të internetit në platformat e mediave sociale si Facebook, Twitter, Instagram dhe LinkedIn për të arritur një audiencë më të gjerë dhe për të drejtuar trafikun në faqen tuaj të internetit.


4. Reklamimi i paguar: Konsideroni të drejtoni fushata reklamimi të paguara në motorët e kërkimit (Google Adwords), platformat e mediave sociale dhe faqet e internetit të tjera përkatëse për të drejtuar trafikun e synuar në faqen tuaj të internetit.


5. Marketingu i influencuesit: Partner me ndikuesit në kamare tuaj për të ndihmuar në promovimin e faqes suaj të internetit dhe për të arritur një audiencë më të madhe.


6. Marketingu me email: Ndërtoni një listë me email të pajtimtarëve dhe dërgoni azhurnime të rregullta, promovime dhe përmbajtje për të çuar trafikun përsëri në faqen tuaj të internetit.


7. Rrjetet: Lidhu me pronarët e tjerë të faqeve të internetit, blogerët dhe ndikuesit në industrinë tuaj për të bashkëpunuar, postuar për mysafirë ose për të shkëmbyer lidhje për të rritur dukshmërinë e faqes suaj të internetit.


8. Marrëdhëniet me publikun: Arriu me gazetarët, blogerët dhe mediat për të ngritur histori ose njoftime të vlefshme për lajmet e lidhura me faqen tuaj të internetit për të gjeneruar publicitet dhe trafik.


9


10. Komunitetet dhe forume në internet: Merrni pjesë në komunitetet dhe forume në internet që lidhen me kamare tuaj dhe angazhohuni me anëtarët duke ndarë njohuri të vlefshme, duke iu përgjigjur pyetjeve dhe duke promovuar faqen tuaj të internetit kur është e rëndësishme.

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Pse është e rrezikshme pirja e duhanit?


Pirja e duhanit është e rrezikshme për disa arsye:


1. Rreziku i rritur i kancerit: Pirja e duhanit është shkaku kryesor i llojeve të ndryshme të kancerit, përfshirë kancerin e mushkërive, fytit, gojës dhe fshikëzës.


2. Problemet e frymëmarrjes: Pirja e duhanit dëmton mushkëritë dhe mund të çojë në kushte kronike të frymëmarrjes siç është sëmundja pulmonare obstruktive kronike (COPD) dhe emfizema.


3. Sëmundja e zemrës: Pirja e duhanit është një faktor kryesor rreziku për sëmundjet e zemrës, duke përfshirë presionin e lartë të gjakut, sulmet në zemër dhe goditjen në tru.


4. Rreziku i rritur i infeksioneve: Pirja e duhanit dobëson sistemin imunitar, duke i bërë individët më të ndjeshëm ndaj infeksioneve të tilla si pneumonia dhe bronkiti.


5. Efektet e dëmshme në shtatëzani: Pirja e duhanit gjatë shtatëzanisë mund të çojë në komplikime të tilla si lindja e parakohshme, pesha e ulët e lindjes dhe defektet e lindjes.


6. Tymi i dorës së dytë: Pirja e duhanit jo vetëm që dëmton duhanpirësin, por gjithashtu paraqet një rrezik shëndetësor për ata që e rrethojnë përmes ekspozimit ndaj tymit të dorës së dytë.


Në përgjithësi, pirja e duhanit të cigareve është e rrezikshme sepse rrit ndjeshëm rrezikun e zhvillimit të kushteve serioze shëndetësore dhe në fund të fundit mund të çojë në vdekje të parakohshme.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si mund të shkruaj një postim profesional në blog?


Shkrimi i një postimi profesional në blog përfshin disa hapa kryesorë për të krijuar një pjesë të përmbajtjes së hartuar mirë dhe tërheqëse. Këtu janë disa këshilla për t'ju ndihmuar të shkruani një postim profesional në blog:

1. Zgjidhni një temë të rëndësishme dhe tërheqëse: Filloni duke identifikuar një temë që është e rëndësishme për audiencën tuaj dhe është diçka për të cilën jeni të ditur dhe të apasionuar. Sigurohuni që tema të jetë diçka që do të interesojë dhe rezonojë me lexuesit tuaj.

2. Kryerja e hulumtimeve të plota: Para se të filloni të shkruani, sigurohuni që të bëni hulumtime të hollësishme mbi temën tuaj të zgjedhur. Kjo do t'ju ndihmojë të mbledhni informacione, statistika dhe fakte përkatëse për të mbështetur pikat tuaja dhe për ta bërë postimin tuaj në blog më të besueshëm.

3. Krijoni një skicë: Organizoni idetë tuaja dhe pikat kryesore duke krijuar një skicë për postimin tuaj në blog. Kjo do t'ju ndihmojë të strukturoni përmbajtjen tuaj në një mënyrë logjike dhe koherente, duke e bërë më të lehtë për lexuesit të ndjekin së bashku.

4. Shkruani një hyrje bindëse: Filloni postimin tuaj në blog me një prezantim të fortë dhe tërheqës që tërheq vëmendjen e lexuesit. Përdorni një goditje për të tërhequr lexuesit dhe t'i bëni ata të duan të vazhdojnë të lexojnë.

5. Përdorni gjuhë të qartë dhe koncize: Shmangni përdorimin e zhargonit ose gjuhës tepër teknike në postimin tuaj në blog. Shkruani në një mënyrë të qartë dhe koncize për ta bërë përmbajtjen tuaj të lehtë për tu kuptuar për të gjithë lexuesit.

6. Përfshini vizuale: elementë vizualë si imazhe, infografikë dhe video mund të ndihmojnë në prishjen e tekstit dhe ta bëni postimin tuaj në blog vizualisht tërheqës. Ata gjithashtu mund të ndihmojnë në mbështetjen e pikave tuaja kryesore dhe ta bëjnë përmbajtjen tuaj më tërheqëse.

7. Vërtetim dhe modifikim: Para se të publikoni postimin tuaj në blog, sigurohuni që ta korrigjoni plotësisht dhe modifikoni atë për gabime të gramatikës, drejtshkrimit dhe formatimit. Konsideroni t'i kërkoni një kolegu ose mikut të rishikojë postimin tuaj për reagime përpara se ta botoni.

8. Shtoni një telefonatë në veprim: Përfundoni postimin tuaj në blog me një thirrje të fortë për të vepruar që inkurajon lexuesit të angazhohen me përmbajtjen tuaj, të tilla si pajtimi në blogun tuaj, komentimi ose ndarja e postimit tuaj në mediat sociale

Duke ndjekur këto këshilla, ju mund të krijoni një postim profesional dhe tërheqës në blog që do të rezonojë me audiencën tuaj dhe do t'ju krijojë si autoritet në fushën tuaj.

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Cila është mënyra më e mirë për të zier vezët?


Këtu është një mënyrë e thjeshtë për të zier vezët:


1. Vendosni vezët në një tigan dhe mbulojini me ujë të ftohtë.

2. Sillni ujin në një çiban mbi nxehtësinë e lartë.

3 Pasi uji të ziejë, zvogëloni nxehtësinë në të ulët dhe lërini vezët të ziejë për 9-12 minuta, në varësi të sa i dëshironi atyre.

4. Hiqni vezët nga nxehtësia dhe menjëherë transferojini ato në një tas me ujë të akullit që të ftohet shpejt.

5 Pasi të ftohet, ju mund të zhvisheni dhe të shijoni vezët tuaja të ziera në mënyrë të përsosur.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si mund të dërgoj email me një listë të postës elektronike në përputhje dhe lidhjet e çabonimit?


Për të dërguar një email me një listë të pajtueshme dhe një lidhje më të ngushtë të çabonimit, duhet të ndiqni këto hapa:


1. Sigurohuni që lista juaj e postës elektronike të jetë në përputhje me të gjitha rregulloret përkatëse, të tilla si Akti CAN-SPAM dhe GDPR. Kjo do të thotë që të gjithë marrësit duhet të kenë zgjedhur të marrin emailet tuaja dhe se ju keni pëlqimin e tyre të qartë për t'i kontaktuar ata.


2. Përfshini një lidhje të qartë dhe të spikatur të çabonimit në emailin tuaj. Sigurohuni që është e lehtë për tu gjetur dhe klikuar mbi, dhe se i merr marrësit direkt në një faqe ku ata lehtë mund të çabonohen nga lista juaj e postës.


3. Për ta bërë lidhjen e çabonimit "më të fortë", mund të përdorni një mundësi të një klikimi të vetëm. Kjo do të thotë që marrësit mund të çabonohen nga postat elektronike me vetëm një klik, pa pasur nevojë të plotësojnë ndonjë formë shtesë ose të japin ndonjë informacion personal.


4 Kur dërgoni emailin, sigurohuni që të personalizoni mesazhin dhe t'i drejtoheni marrësit me emër nëse është e mundur. Kjo mund të ndihmojë në rritjen e angazhimit dhe ta bëjë emailin të ndjehet më i rëndësishëm për marrësin.


5. Para se ta dërgoni emailin, provojeni atë për të siguruar që lidhja e çabonimit po funksionon siç duhet dhe që emaili të duket mirë në të gjitha pajisjet dhe klientët e postës elektronike.


Duke ndjekur këto hapa, ju mund të dërgoni një email me një listë të pajtueshme dhe një lidhje më të fortë të çabonimit për të siguruar që marrësit tuaj të kenë një përvojë pozitive dhe lehtë mund të heqin dorë nga marrja e postave elektronike të mëtejshme nga ju.

nga Daisy / Shiko | Blej | Bleni me cryptocurrency



Cilat janë përfitimet e marrjes së spironolaktonit si grua?


Spiro, ose spironolactone, shpesh përshkruhet për gratë me çekuilibër hormonal. Disa nga përfitimet e mundshme të marrjes së Spiro përfshijnë:


1. Trajtimi i puçrrave: Spiro mund të ndihmojë në uljen e akneve duke zvogëluar prodhimin e sebumit, i cili mund të bllokojë poret dhe të çojë në thyerje.


2. Reduktimi i rritjes së tepërt të flokëve: Spiro mund të ndihmojë në uljen e rritjes së tepërt të flokëve, e njohur si hirsutism, duke bllokuar efektet e hormoneve androgjene.


3. Menaxhimi i pabarazive hormonale: Spiro mund të përdoret për të menaxhuar kushte të tilla si sindromi i vezores polikistike (PCOS) ose pabarazitë hormonale që mund të shkaktojnë parregullsi menstruale ose simptoma të tjera.


4. Trajtimi i presionit të lartë të gjakut: Spiro është një diuretik dhe mund të ndihmojë në uljen e presionit të gjakut duke zvogëluar sasinë e kripës dhe ujit të mbajtur në trup.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Pse njerëzit implantojnë implantet NFC në duart e tyre?


Ka disa arsye pse njerëzit zgjedhin të implantojnë implantet e NFC (afër komunikimit në terren) në duart e tyre:


1. Komoditeti: Implantet e NFC lejojnë individët të përdorin lehtësisht informacionin, të hapin dyert, të bëjnë pagesa dhe të kryejnë detyra të tjera me një valë të thjeshtë të dorës së tyre. Kjo mund të jetë më e përshtatshme sesa të mbash rreth çelësat, kartat e identitetit ose telefonat inteligjentë.


2. Siguria: Implantet NFC mund të sigurojnë një shtresë të shtuar të sigurisë, pasi ato kërkojnë qasje fizike në trupin e individit për t'u aktivizuar. Kjo mund të ndihmojë në parandalimin e qasjes së paautorizuar në pajisje ose informacione të ndjeshme.


3. Eksperimentimi teknologjik: Disa njerëz zgjedhin të implantojnë çipat NFC si një mënyrë për të eksperimentuar me teknologjitë në zhvillim dhe t'i integrojnë ato në jetën e tyre të përditshme.


4. Identifikimi personal: Implantet e NFC mund të përdoren për qëllime të identifikimit personal, të tilla si ruajtja e informacionit mjekësor ose detajet e kontaktit që mund të arrihen lehtësisht në rast të emergjencave.


5. Biohacking: Disa individë i shohin implantet e NFC si një formë të biohacking, ku ata rritin trupat e tyre me teknologji për të rritur aftësitë ose përvojat e tyre.


Në përgjithësi, vendimi për të implantuar patate të skuqura NFC në duart e tyre është një zgjedhje personale që ndryshon nga personi në person bazuar në preferencat dhe besimet e tyre individuale.


Shpërthej

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Causesfarë e shkakton migrenën dhe si trajtohen ato?


Migrena është dhimbje koke të rënda që shpesh shoqërohen me simptoma të tjera si vjellje, ndjeshmëri ndaj dritës dhe tingullit dhe shqetësime vizuale. Shkaku i saktë i migrenave nuk është kuptuar plotësisht, por besohet se ka të bëjë me ndryshimet në rrjedhën e gjakut dhe kimikatet në tru.


Trajtimi për migrene zakonisht përfshin një kombinim të ndryshimeve të stilit të jetës, ilaçeve dhe terapive alternative. Disa opsione të zakonshme të trajtimit përfshijnë:


1. Marrja e qetësuesve të dhimbjes mbi-counter si ibuprofen ose acetaminofen

2. Ilaçet me recetë të dizajnuara posaçërisht për të trajtuar migrenat, të tilla si triptans dhe ergotamines

3. Shmangia e shkaktuesve të tillë si ushqime të caktuara, stresi, mungesa e gjumit ose ndryshimet hormonale

4. Praktikimi i teknikave të relaksimit siç janë frymëmarrja e thellë ose meditimi

5. Aplikimi i paketave të nxehta ose të ftohta në kokë ose qafë

6. Marrja e stërvitjes së rregullt dhe mbajtja e një diete të shëndetshme


Shtë e rëndësishme për individët që vuajnë nga migrena për të punuar me ofruesin e tyre të kujdesit shëndetësor për të zhvilluar një plan trajtimi që është përshtatur për nevojat dhe shkaktuesit e tyre specifike. Në disa raste, mund të jetë i nevojshëm një kombinim i terapive për të menaxhuar në mënyrë efektive migrenat dhe për të përmirësuar cilësinë e jetës.

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Cilat janë përfitimet e marrjes së progesteronit?


1. Rregullon ciklin menstrual: Progesteroni luan një rol kryesor në rregullimin e ciklit menstrual dhe mund të ndihmojë në rivendosjen e ekuilibrit për individët me periudha të parregullta.


2. Mbështet pjellorinë: Progesteroni është thelbësor për ruajtjen e një shtatëzënie të shëndetshme duke përgatitur mitrën për implantim dhe mbështetjen e rritjes së fetusit.


3 Ndihmon në ekuilibrin e hormoneve: Progesteroni funksionon në harmoni me estrogjenin për të ruajtur ekuilibrin hormonal në trup, i cili mund të ndihmojë në zbutjen e simptomave të pabarazive hormonale si PMS, menopauzës dhe PCOS.


4. Përmirëson gjendjen shpirtërore: Progesteroni është treguar se ka një efekt qetësues në tru dhe mund të ndihmojë në uljen e simptomave të ankthit dhe depresionit.


5. Mbështet shëndetin e kockave: Progesteroni punon me hormone të tjera si estrogjeni dhe testosteroni për të mbështetur densitetin e kockave dhe për të zvogëluar rrezikun e osteoporozës.


6. Përmirëson gjumin: Progesteroni mund të ndihmojë në rregullimin e ciklit të zgjimit të gjumit dhe përmirësimin e cilësisë së gjumit.


7. Mbështet shëndetin e lëkurës: Progesteroni mund të ketë një efekt pozitiv në shëndetin e lëkurës duke promovuar prodhimin e kolagjenit dhe duke zvogëluar inflamacionin.


8. Redukton rrezikun e kancereve të caktuara: Progesteroni është treguar se ka një efekt mbrojtës kundër llojeve të caktuara të kancerit, siç është kanceri endometrial.


Shtë e rëndësishme të theksohet se progesteroni duhet të përdoret nën drejtimin e një ofruesi të kujdesit shëndetësor, pasi mund të ketë efekte anësore dhe ndërveprime me ilaçe të tjera.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Cilat janë përfitimet për të pasur një aparat fotografik sigurie?


1. Parandalimi i veprimtarisë kriminale - kamerat e sigurisë mund të veprojnë si një pengesë për kriminelët e mundshëm, pasi ata kanë më pak të ngjarë të kryejnë një krim nëse e dinë se po shikohen.


2. Mbikëqyrja dhe monitorimi - Kamerat e sigurisë ju lejojnë të monitoroni pronën tuaj dhe të mbani një sy në çdo aktivitet të dyshimtë në kohë reale, duke ndihmuar në parandalimin e vjedhjes, vandalizmit ose krimeve të tjera.


3


4


5. Paqja e mendjes - të keni instaluar kamera sigurie mund të sigurojë paqen e mendjes, duke e ditur që prona juaj po monitorohet dhe kërcënimet e mundshme po zbulohen dhe regjistrohen.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si po rritet kaq shpejt tregu i kriptove?


Ekzistojnë disa faktorë që kontribuojnë në rritjen e shpejtë të tregut të cryptocurrency. 


1. Rritja e vetëdijes dhe birësimit: Ndërsa më shumë njerëz bëhen të vetëdijshëm për cryptocurrency dhe përfitimet e tyre të mundshme, kërkesa për investime të cryptocurrency është rritur ndjeshëm. Ky interes i shtuar ka çuar në një rritje të numrit të përdoruesve dhe investitorëve që marrin pjesë në treg.


2. Përfshirja institucionale: Gjatë viteve të fundit, ne kemi parë një numër në rritje të investitorëve institucionalë, të tilla si fondet mbrojtëse, bankat dhe institucionet e tjera financiare, duke u përfshirë në tregun e cryptocurrency. Kjo ka shtuar besueshmëri në treg dhe ka tërhequr edhe më shumë investitorë.


3. Përparimet e Teknologjisë: Zhvillimet teknologjike në hapësirën e blockchain e kanë bërë më të lehtë për kriptocurrency të reja të krijohen dhe tregtohen. Për më tepër, përparimet në masat e sigurisë dhe kornizat rregullatore e kanë bërë tregun më tërheqës për investitorët.


4. Luhatshmëria e tregut: Natyra shumë e paqëndrueshme e tregut të cryptocurrency ka tërhequr tregtarët dhe investitorët që kërkojnë të përfitojnë nga luhatjet e çmimeve dhe të fitojnë fitime të konsiderueshme në një periudhë relativisht të shkurtër kohore.


5. Pranimi global: Cryptocurrency tani pranohet si një formë pagese nga një numër në rritje i tregtarëve dhe bizneseve në të gjithë botën. Kjo ka ndihmuar në legjitimimin e cryptocurrency si një alternative e vlefshme për monedhat tradicionale të fiat.


Në përgjithësi, këta faktorë kanë kontribuar në rritjen e shpejtë të tregut të cryptocurrency dhe ka të ngjarë të vazhdojnë të drejtojnë zgjerimin e tij në të ardhmen.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


A është sheqeri me të vërtetë jo i shëndetshëm?


Konsumi i tepërt i sheqerit mund të çojë në çështje të ndryshme shëndetësore, të tilla si shtimi në peshë, mbipesha, diabeti, sëmundjet e zemrës dhe problemet e dhëmbëve. Rekomandohet të kufizoni marrjen e sheqernave të shtuar në dietën tonë për të mbajtur shëndet të mirë. Sidoqoftë, sheqernat natyrale që gjenden në fruta dhe perime nuk konsiderohen të dëmshme në sasi të moderuar dhe mund të jenë pjesë e një diete të shëndetshme. Moderimi është thelbësor kur bëhet fjalë për konsumin e sheqerit.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si mund të bëj fotot më të mira të vetvetes?


1. Ndriçimi: Drita natyrale është gjithmonë më e mira për të bërë fotografi. Pozicionohuni përballë një dritareje ose dilni jashtë për të përfituar nga rrezet e diellit natyror. Shmangni ndriçimin e ashpër të sipërm ose dritën e diellit të drejtpërdrejtë, pasi mund të krijojë hije të paqarta në fytyrën tuaj.


2. Sfondi: Zgjidhni një sfond të pastër dhe të palidhur për të shmangur shpërqendrimet në fotot tuaja. Një mur i thjeshtë, një ambient skenik në natyrë ose një sfond i thjeshtë mund të funksionojë mirë për të theksuar veten në foto.


3. POZA: Eksperimentoni me poza të ndryshme për të gjetur atë që i lajkaton më shumë tiparet tuaja. Shmangni këndet e pakëndshme dhe në vend të kësaj, përpiquni të zgjasni qafën tuaj dhe ta ngjitni kokën pak për të krijuar një pamje më lajkuese.


4. Përbërja: Kushtojini vëmendje përbërjes së fotove tuaja. Përdorni rregullin e të tretëve duke e vendosur veten jashtë qendrës në kornizë për të krijuar një imazh më tërheqës vizualisht. Ju gjithashtu mund të eksperimentoni me kënde dhe këndvështrime të ndryshme për të shtuar interes në fotot tuaja.


5. Buzëqeshje dhe shprehje: Një buzëqeshje e mirëfilltë mund të lartësojë menjëherë fotot tuaja. Relaksohuni fytyrën tuaj, mendoni për diçka që ju bën të lumtur dhe lëreni që buzëqeshja juaj natyrale të shkëlqejë. Gjithashtu, provoni shprehje të ndryshme të fytyrës për të përcjellë humor dhe emocione të ndryshme në fotot tuaja.


6. Përdorni një timer ose shkop selfie: Për të marrë një goditje të qëndrueshme dhe të kompozuar mirë, konsideroni të përdorni një kohëmatës në kamerën tuaj ose një shkop selfie për të zgjatur shtrirjen tuaj dhe për të kapur një kornizë më të gjerë. Kjo do t'ju ndihmojë të shmangni selfie të paqarta ose të paqarta.


7. Redaktoni fotot tuaja: Pasi të keni fotografuar, përdorni mjete ose aplikacione për redaktimin e fotografive për të përmirësuar ngjyrat, ndriçimin dhe pamjen e përgjithshme të imazheve tuaja. Ju mund të rregulloni shkëlqimin, kontrastin dhe ngopjen për t'i bërë fotot tuaja të pop.


Mos harroni, praktika e bën të përsosur, prandaj mos kini frikë të eksperimentoni dhe të argëtoheni ndërsa bëni foto nga vetja.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency



Si i gjej klientët për biznesin tim të vogël për zhvillimin e faqes në internet?


Këtu janë disa strategji që mund të përdorni për të tërhequr klientët për biznesin tuaj të zhvillimit të uebit:


1. Ndërtoni një prani të fortë në internet: Krijoni një uebfaqe profesionale që tregon shërbimet tuaja, portofolin dhe dëshmitë e klientit. Përdorni kanale të mediave sociale për të promovuar biznesin tuaj dhe për t'u angazhuar me klientët e mundshëm.


2. Rrjeti: Merrni pjesë në ngjarje të industrisë, konferenca dhe takime për t'u lidhur me profesionistë të tjerë në këtë fushë dhe klientë të mundshëm. Bashkohuni me komunitetet në internet dhe forume në lidhje me zhvillimin e uebit për të zgjeruar rrjetin tuaj.


3. Ofroni stimuj referimi: Inkurajoni klientët e kënaqur t'u referojnë shërbimet tuaja të tjerëve duke ofruar zbritje ose stimuj të tjerë për referime të suksesshme.


4. Bashkëpunoni me bizneset e tjera: Partner me agjencitë e marketingut dixhital, projektuesit grafikë ose profesionistë të tjerë që mund të kenë nevojë për shërbime të zhvillimit të uebit për klientët e tyre.


5. Reklamoni: Investoni në reklamat në internet përmes Google Adwords, reklamave të mediave sociale ose reklamave për të arritur një audiencë më të gjerë.


6


7. Marketingu i përmbajtjes: Krijoni përmbajtje të vlefshme siç janë postimet në blog, whitepapers ose webinars që demonstrojnë ekspertizën tuaj në zhvillimin e uebit dhe tërheqin klientë të mundshëm përmes motorëve të kërkimit dhe mediave sociale.


8. Merrni pjesë në shfaqje tregtare dhe ngjarje: Merrni pjesë në shfaqjet dhe ngjarjet e tregtisë së industrisë për t'u lidhur me klientët e mundshëm dhe për të shfaqur shërbimet tuaja.


9. Ofroni konsultime falas: Ofroni konsultime falas për klientët e mundshëm për të diskutuar nevojat e tyre dhe se si shërbimet tuaja mund t'i ndihmojnë ata të arrijnë qëllimet e tyre.


10. Kërkoni vlerësime dhe dëshmitë: Inkurajoni klientët e kënaqur të lënë vlerësime dhe dëshmi në faqen tuaj të internetit ose platforma të tjera të rishikimit për të ndërtuar besueshmëri dhe për të tërhequr klientë të rinj.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si mund të ndërtoj një server mail me postfix?


Për të ndërtuar një server me postë me Postfix, ndiqni këto hapa:


1. Instaloni PostFix: Përdorni menaxherin tuaj të paketave për të instaluar PostFix në serverin tuaj. Për shembull, në Debian/Ubuntu, ju mund të ekzekutoni `sudo apt-get instaloni postfix`.


2. Konfiguroni PostFix: Skedarët e konfigurimit PostFix janë të vendosura në `/etj/postfix/`. Skedari kryesor i konfigurimit është `main.cf`. Ju mund ta modifikoni këtë skedar për të vendosur serverin tuaj të postës sipas kërkesave tuaja. Disa konfigurime të zakonshme që mund t'ju duhet të vendosni, përfshijnë emrin e domain, cilësimet e stafetave të postës, fushat virtuale, etj.


3. Vendosni të dhënat e DNS: Për të siguruar shpërndarjen e postës, duhet të vendosni regjistrimet e nevojshme DNS (MX dhe SPF Records) për domenin tuaj. Kontaktoni Regjistruesin e Domain -it ose ofruesin DNS për ndihmë nëse është e nevojshme.


4. Konfiguroni fushat dhe përdoruesit virtualë: Nëse doni të prisni fusha të shumta në serverin tuaj të postës, do t'ju duhet të konfiguroni fushat dhe përdoruesit virtualë. Kjo mund të bëhet duke përdorur cilësimet `Virtual_alias_maps` dhe` virtual_mailbox_maps` në skedarin e konfigurimit Postfix.


5. Siguroni serverin tuaj të postës: Sigurohuni që serveri juaj i postës të jetë i sigurt duke vendosur rregulla të firewall, duke përdorur kriptimin TLS për postën hyrëse dhe dalëse, dhe duke zbatuar masa të tjera të sigurisë të rekomanduara për serverët e postës.


6. Testoni serverin tuaj të postës: Pasi të jetë vendosur gjithçka, duhet të provoni serverin tuaj të postës duke dërguar dhe marrë email të provës. Përdorni mjete si Telnet ose Mailx për të dërguar me dorë postë elektronike dhe kontrolloni nëse ato merren me sukses.


Mos harroni të azhurnoni në mënyrë periodike dhe të mirëmbani serverin tuaj të postës për të siguruar që ai të funksionojë pa probleme dhe me siguri. Shtë gjithashtu një ide e mirë për të monitoruar regjistrat e serverëve të postës për çdo çështje ose aktivitet të dyshimtë.

nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si mund të bëj fotot më të mira të vetvetes?


1. Ndriçimi: Drita natyrale është gjithmonë më e mira për të bërë fotografi. Pozicionohuni përballë një dritareje ose dilni jashtë për të përfituar nga rrezet e diellit natyror. Shmangni ndriçimin e ashpër të sipërm ose dritën e diellit të drejtpërdrejtë, pasi mund të krijojë hije të paqarta në fytyrën tuaj.


2. Sfondi: Zgjidhni një sfond të pastër dhe të palidhur për të shmangur shpërqendrimet në fotot tuaja. Një mur i thjeshtë, një ambient skenik në natyrë ose një sfond i thjeshtë mund të funksionojë mirë për të theksuar veten në foto.


3. POZA: Eksperimentoni me poza të ndryshme për të gjetur atë që i lajkaton më shumë tiparet tuaja. Shmangni këndet e pakëndshme dhe në vend të kësaj, përpiquni të zgjasni qafën tuaj dhe ta ngjitni kokën pak për të krijuar një pamje më lajkuese.


4. Përbërja: Kushtojini vëmendje përbërjes së fotove tuaja. Përdorni rregullin e të tretëve duke e vendosur veten jashtë qendrës në kornizë për të krijuar një imazh më tërheqës vizualisht. Ju gjithashtu mund të eksperimentoni me kënde dhe këndvështrime të ndryshme për të shtuar interes në fotot tuaja.


5. Buzëqeshje dhe shprehje: Një buzëqeshje e mirëfilltë mund të lartësojë menjëherë fotot tuaja. Relaksohuni fytyrën tuaj, mendoni për diçka që ju bën të lumtur dhe lëreni që buzëqeshja juaj natyrale të shkëlqejë. Gjithashtu, provoni shprehje të ndryshme të fytyrës për të përcjellë humor dhe emocione të ndryshme në fotot tuaja.


6. Përdorni një timer ose shkop selfie: Për të marrë një goditje të qëndrueshme dhe të kompozuar mirë, konsideroni të përdorni një kohëmatës në kamerën tuaj ose një shkop selfie për të zgjatur shtrirjen tuaj dhe për të kapur një kornizë më të gjerë. Kjo do t'ju ndihmojë të shmangni selfie të paqarta ose të paqarta.


7. Redaktoni fotot tuaja: Pasi të keni fotografuar, përdorni mjete ose aplikacione për redaktimin e fotografive për të përmirësuar ngjyrat, ndriçimin dhe pamjen e përgjithshme të imazheve tuaja. Ju mund të rregulloni shkëlqimin, kontrastin dhe ngopjen për t'i bërë fotot tuaja të pop.


Mos harroni, praktika e bën të përsosur, prandaj mos kini frikë të eksperimentoni dhe të argëtoheni ndërsa bëni foto nga vetja.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency


Si mund të shkruaj një libër të mirë?


1. Zhvilloni një ide ose koncept të qartë: Para se të filloni të shkruani, sigurohuni që të keni një ide të fortë për librin tuaj. Kjo mund të jetë një komplot, karakter, temë ose vendosje që dëshironi të eksploroni në shkrimin tuaj.


2. Krijoni një skicë: Skiconi pikat kryesore të komplotit, personazhet dhe temat e librit tuaj përpara se të filloni të shkruani. Kjo do t'ju ndihmojë të qëndroni të organizuar dhe të përqendruar ndërsa shkruani.


3 Kjo do t'ju ndihmojë të qëndroni të motivuar dhe të përparoni në shkrimin tuaj.


4. Sapo filloni të shkruani: Ndonjëherë pjesa më e vështirë e shkrimit të një libri po fillon. Mos u shqetësoni për përsosmërinë në këtë fazë, thjesht filloni të shkruani dhe merrni idetë tuaja në letër.


5. Bashkohuni me një grup shkrimi ose komuniteti: Konsideroni të bashkoheni në një grup shkrimi ose komuniteti për mbështetje, reagime dhe motivim. Shkrimi mund të jetë një ndjekje e vetmuar, kështu që të kesh një komunitet të shkrimtarëve të tjerë mund të jetë i paçmueshëm.


6. Redaktoni dhe rishikoni: Pasi të keni përfunduar një draft të librit tuaj, kthehuni dhe rishikoni dhe modifikoni atë për të përmirësuar qartësinë, strukturën dhe rrjedhën e shkrimit tuaj. Kjo mund të përfshijë hartime të shumta dhe rishikime përpara se libri juaj të jetë gati për botim.


7. Kërkoni përshtypje: Ndani punën tuaj me të tjerët, të tilla si lexuesit e beta, grupet e shkrimit ose redaktorët profesionistë, për të marrë përshtypje për shkrimin tuaj. Kjo mund t'ju ndihmojë të identifikoni fushat për përmirësim dhe ta bëni librin tuaj më të fortë.


8. Vazhdoni të shkruani: Të shkruash një libër është një maratonë, jo një sprint. Vazhdoni të shtyni përpara, të qëndroni të përkushtuar dhe të vazhdoni të punoni në librin tuaj derisa të përfundojë.


nga Daisy / Shiko | Blej | Bleni me cryptocurrency




https://glamgirlx.com -


(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