рдлреНрд▓рд╛рд╕реНрдХ рдореЗрдЧрд╛-рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓, рднрд╛рдЧ 7: рдпреВрдирд┐рдЯ рдкрд░реАрдХреНрд╖рдг

рдпрд╣ рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рд╕рд╛рддрд╡рд╛рдБ рд▓реЗрдЦ рд╣реИ рдЬрд╣рд╛рдБ рдореИрдВ рдлреНрд▓рд╛рд╕реНрдХ рдорд╛рдЗрдХреНрд░реЛрдлрд╝реНрд░рд╛рдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдкрд╛рдпрдерди рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦрдиреЗ рдХреЗ рдЕрдкрдиреЗ рдЕрдиреБрднрд╡ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реВрдБред



рдЗрд╕ рдЧрд╛рдЗрдб рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдПрдХ рдХрд╛рдлреА рдХрд╛рд░реНрдпрд╛рддреНрдордХ рдорд╛рдЗрдХреНрд░реЛрдмреНрд▓реЙрдЧрд┐рдВрдЧ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдореМрд▓рд┐рдХрддрд╛ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдореЗрдВ рдорд╛рдЗрдХреНрд░реЛрдмреНрд▓реЙрдЧ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред



рд╕рд╛рдордЧреНрд░реА рдХреА рддрд╛рд▓рд┐рдХрд╛
рднрд╛рдЧ 2: рдЯреЗрдореНрдкрд▓реЗрдЯ

рднрд╛рдЧ 3: рдкреНрд░рдкрддреНрд░

рднрд╛рдЧ 4: рдбреЗрдЯрд╛рдмреЗрд╕

рднрд╛рдЧ 5: рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓реЙрдЧрд┐рди

рднрд╛рдЧ 6: рдкреНрд░реЛрдлрд╛рдЗрд▓ рдкреЗрдЬ рдФрд░ рдЕрд╡рддрд╛рд░

рднрд╛рдЧ 7: рдпреВрдирд┐рдЯ рдкрд░реАрдХреНрд╖рдг (рдпрд╣ рд▓реЗрдЦ)

рднрд╛рдЧ 8: рдЕрдиреБрдпрд╛рдпреА, рд╕рдВрдкрд░реНрдХ рдФрд░ рдорд┐рддреНрд░

рднрд╛рдЧ 9: рдЕрдВрдХреБрд░рдг

рднрд╛рдЧ 10: рдкреВрд░реНрдг рдкрд╛рда рдЦреЛрдЬ

рднрд╛рдЧ 11: рдИрдореЗрд▓ рд╕рдорд░реНрдерди

рднрд╛рдЧ 12: рдкреБрдирд░реНрдирд┐рд░реНрдорд╛рдг

рднрд╛рдЧ 13: рддрд┐рдерд┐ рдФрд░ рд╕рдордп

рднрд╛рдЧ 14: I18n рдФрд░ L10n

рднрд╛рдЧ 15: рдЕрдЬрд╛рдХреНрд╕

рднрд╛рдЧ 16: рдбрд┐рдмрдЧрд┐рдВрдЧ, рдкрд░реАрдХреНрд╖рдг рдФрд░ рдкреНрд░реЛрдлрд╛рдЗрд▓рд┐рдВрдЧ

рднрд╛рдЧ 17: рд▓рд┐рдирдХреНрд╕ рдкрд░ рддреИрдирд╛рддреА (рдФрд░ рд░рд╛рд╕реНрдкрдмреЗрд░реА рдкрд╛рдИ рдкрд░ рднреА!)

рднрд╛рдЧ 18: рд╣рд░реЛрдХреВ рдХреНрд▓рд╛рдЙрдб рдкрд░ рддреИрдирд╛рддреА





рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐



рдЗрд╕ рдЧрд╛рдЗрдб рдХреЗ рдкрд┐рдЫрд▓реЗ рд╣рд┐рд╕реНрд╕реЛрдВ рдореЗрдВ, рд╣рдордиреЗ рдзреАрд░реЗ-рдзреАрд░реЗ рдЕрдкрдиреЗ рдорд╛рдЗрдХреНрд░реЛрдмреНрд▓реЙрдЧрд┐рдВрдЧ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛, рдЪрд░рдг рджрд░ рдЪрд░рдг рдирдИ рд╕реБрд╡рд┐рдзрд╛рдПрдБ рдЬреЛрдбрд╝рддреЗ рд╣реБрдПред рдЗрд╕ рд╕рдордп рддрдХ, рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдкрдВрдЬреАрдХреГрдд рдФрд░ рдЕрдзрд┐рдХреГрдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЙрдиреНрд╣реЗрдВ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдореЗрдВ рдЕрдкрдирд╛ рдбреЗрдЯрд╛ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рднреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред



рдЖрдЬ рд╣рдо рдирдИ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рдирд╣реАрдВ рдЬреЛрдбрд╝реЗрдВрдЧреЗред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреЛ рдФрд░ рдЕрдзрд┐рдХ рд╕реНрдерд┐рд░ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдврд╛рдВрдЪрд╛ рднреА рдмрдирд╛рдПрдВрдЧреЗ, рдЬреЛ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╣рдореЗрдВ рд╕рдВрднрд╛рд╡рд┐рдд рджреБрд░реНрдШрдЯрдирд╛рдУрдВ рдХреЛ рд░реЛрдХрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред





рдмрдЧ рдЦреЛрдЬ



рдкрд┐рдЫрд▓реЗ рдЕрдзреНрдпрд╛рдп рдХреЗ рдЕрдВрдд рдореЗрдВ, рдореИрдВрдиреЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдХрд┐ рдХреЛрдб рдореЗрдВ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реИред рдЕрдм рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рд╣реИ рдФрд░ рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рд╣рдорд╛рд░рд╛ рдЖрд╡реЗрджрди рдЗрд╕ рддрд░рд╣ рдХреА рдЪреАрдЬреЛрдВ рдкрд░ рдХреИрд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реИред



рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЙрдкрдирд╛рдореЛрдВ рдХреА рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЙрдкрдирд╛рдо рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЪреБрдирд╛ рдЧрдпрд╛ рд╣реИред рдпрджрд┐ OpenID рдкреНрд░рджрд╛рддрд╛ рд╣рдореЗрдВ рдЙрдкрдирд╛рдо рдмрддрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдЕрдиреНрдпрдерд╛, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдИрдореЗрд▓ рдХреЗ рдкрд╣рд▓реЗ рднрд╛рдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрдкрдирд╛рдо рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрджрд┐ рдПрдХ рд╣реА рдЙрдкрдирд╛рдо рд╡рд╛рд▓реЗ рджреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрдВрдЬреАрдХрд░рдг рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдХреЗрд╡рд▓ рдкрд╣рд▓рд╛ рд╣реА рд╕рдлрд▓ рд╣реЛрдЧрд╛ред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдбреЗрдЯрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдХрд░, рд╣рдордиреЗ рдЗрд╕реЗ рдХреЗрд╡рд▓ рдмрджрддрд░ рдмрдирд╛ рджрд┐рдпрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣рд╛рдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЯрдХрд░рд╛рд╡ рд╕реЗ рдмрдЪрдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред



рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдЗрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░реЗрдВ, рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ рдХрд┐ рдЬрдм рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ, рддреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреИрд╕реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИред



рдлреНрд▓рд╛рд╕реНрдХ рдореЗрдВ рдбрд┐рдмрдЧрд┐рдВрдЧ



рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдирдпрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдмрдирд╛рдПрдВред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рд▓рд┐рдирдХреНрд╕ рд╣реИ:

rm app.db ./db_create.py
      
      





рд╡рд┐рдВрдбреЛрдЬ:

 del app.db flask/Scripts/python db_create.py
      
      





рдмрдЧ рдЦреЗрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рджреЛ OpenID рдЦрд╛рддреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдпрд╣ рдмреЗрд╣рддрд░ рд╣реИ рдпрджрд┐ рдпреЗ рдЦрд╛рддреЗ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рджрд╛рддрд╛рдУрдВ рд╕реЗ рд╣реИрдВ, рдЕрдиреНрдпрдерд╛ рдХреБрдХреАрдЬрд╝ рдХреЗ рд╕рд╛рде рдХреБрдЫ рдХрдард┐рдирд╛рдЗрдпрд╛рдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред рддреЛ, рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:



рдКрдкреНрд╕! рд╣рдореЗрдВ sqlalchemy рдХреЗ рдХрд╛рд░рдг рдЕрдкрд╡рд╛рдж рдорд┐рд▓рд╛ред рддреНрд░реБрдЯрд┐ рдкрд╛рда рдкрдврд╝рддрд╛ рд╣реИ:

 sqlalchemy.exc.IntegrityError IntegrityError: (IntegrityError) UNIQUE constraint failed: user.nickname u'UPDATE user SET nickname=?, about_me=? WHERE user.id = ?' (u'dup', u'', 2)
      
      





рдиреАрдЪреЗ рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХрд╛ рдПрдХ рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рд╣реИ , рдЬрд┐рд╕рдореЗрдВ рдЖрдк рди рдХреЗрд╡рд▓ рдкреНрд░рддреНрдпреЗрдХ рдлреНрд░реЗрдо рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рдЕрдкрдиреЗ рдХреЛрдб рдХреЛ рд╕реАрдзреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рднреА рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ!



рддреНрд░реБрдЯрд┐ рд╡рд┐рд╡рд░рдг рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдЙрдкрдирд╛рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ User



рдореЙрдбрд▓ рдореЗрдВ, nickname



рдлрд╝реАрд▓реНрдб unique=True



рд░реВрдк рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдпрд╣реА рд╡рдЬрд╣ рд╣реИ рдХрд┐ рдпрд╣ рд╕реНрдерд┐рддрд┐ рдЙрддреНрдкрдиреНрди рд╣реБрдИред



рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдФрд░ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рддреНрд░реБрдЯрд┐ (рдпрд╣ рдпрд╛ рдХреЛрдИ рдЕрдиреНрдп) рд╣реЛрддреА рд╣реИ, рддреЛ рдЙрд╕реЗ рддреНрд░реБрдЯрд┐ рдХрд╛ рд╡рд┐рд╡рд░рдг рдФрд░ рд╕рдВрдкреВрд░реНрдг рдЯреНрд░реЗрд╕рдмреИрдХ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред рд╡рд┐рдХрд╛рд╕ рдХреЗ рджреМрд░рд╛рди рдпрд╣ рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рдФрд░ рдХреЛ рдирд╣реАрдВ рдЪрд╛рд╣реЗрдВрдЧреЗред



рдЗрд╕ рд╕рдордп, рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдиреЗ рд░рд┐рд▓реАрдЬрд╝ рдореЛрдб рдореЗрдВ рдХрд╛рдо рдХрд┐рдпрд╛ред рдпрд╣ рдореЛрдб рд╕реНрдЯрд╛рд░реНрдЯрдЕрдк рдкрд░ debug=True



run



рдкрджреНрдзрддрд┐ рдХреЗ рд▓рд┐рдП рджрд┐рдпрд╛ рдЧрдпрд╛ debug=True



рддрд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдХреНрд░рд┐рдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЬрдм рд╣рдо рд▓рдбрд╝рд╛рдИ рд╕рд░реНрд╡рд░ рдкрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдЧрд╛ рдХрд┐ рдбрд┐рдмрдЧрд┐рдВрдЧ рдореЛрдб рдмрдВрдж рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдФрд░ рд╕реНрдХреНрд░рд┐рдкреНрдЯ ( runp.py



file) рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
:



 #!flask/bin/python from app import app app.run(debug = False)
      
      







рдЕрдм рдЗрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЪрд▓рд╛рдПрдВ

 ./runp.py
      
      







рджреВрд╕рд░реЗ рдЦрд╛рддреЗ рдХреЗ рдЙрдкрдирд╛рдо рдХреЛ рдлрд┐рд░ рд╕реЗ 'рдбрд┐рдк' рдореЗрдВ рдмрджрд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдЗрд╕ рдмрд╛рд░ рд╣рдо рдПрдХ рд╡рд┐рд╕реНрддреГрдд рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдирд╣реАрдВ рджреЗрдЦреЗрдВрдЧреЗред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдореЗрдВ 500 Internal Server Error



рдХреЛрдб рдХреЗ рд╕рд╛рде рдПрдХ HTTP рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИред рдпрд╣ рдлреНрд▓рд╛рд╕реНрдХ рдкреЗрдЬ рддрдм рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдбрд┐рдмрдЧрд┐рдВрдЧ рдореЛрдб рдмрдВрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдЕрдкрд╡рд╛рдж рд╣реЛрддрд╛ рд╣реИред рдкреГрд╖реНрда рдРрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрдо рд╕реЗ рдХрдо рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╡рд┐рд╡рд░рдг рдкреНрд░рдХрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред



рдлрд┐рд░ рднреА, рд╣рдо рджреЛ рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, 500 рддреНрд░реБрдЯрд┐ рдкреГрд╖реНрда рдмрджрд╕реВрд░рдд рджрд┐рдЦрддрд╛ рд╣реИред рджреВрд╕рд░реА рд╕рдорд╕реНрдпрд╛ рдЬреНрдпрд╛рджрд╛ рдЧрдВрднреАрд░ рд╣реИред рдпрджрд┐ рд╕рдм рдХреБрдЫ рд╡реИрд╕рд╛ рд╣реА рд░рд╣ рдЧрдпрд╛ рд╣реИ, рддреЛ рд╣рдо рдХрднреА рдирд╣реАрдВ рдЬрд╛рди рдкрд╛рдПрдВрдЧреЗ рдХрд┐ рдХреИрд╕реЗ рдФрд░ рдХрдм рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реЛрддреА рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╕рднреА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдЕрдм рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдИ рд╣реИрдВред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдЗрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рдмрд╣реБрдд рд╕рд░рд▓ рд╕рдорд╛рдзрд╛рди рд╣реИрдВред



рдореВрд▓ HTTP рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░



рдлреНрд▓рд╛рд╕реНрдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдкреГрд╖реНрдареЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рдЕрдкрдиреЗ рдкреГрд╖реНрдареЛрдВ рдХреЛ рекрежрек рдФрд░ релрежреж рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рд╛рдордирд╛ рдХрд░рддреЗ рд╣реИрдВред рдЕрдиреНрдп рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЗ рдЕрдкрдиреЗ рдкреГрд╖реНрда рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдареАрдХ рдЙрд╕реА рддрд░рд╣ рд╣реЛрдЧреАред



рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ errorhandler



рдбреЗрдХреЛрд░реЗрдЯрд░ (рдлрд╝рд╛рдЗрд▓ app/views.py



errorhandler



) рдХреА app/views.py



:

 @app.errorhandler(404) def not_found_error(error): return render_template('404.html'), 404 @app.errorhandler(500) def internal_error(error): db.session.rollback() return render_template('500.html'), 500
      
      







рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдЗрд╕ рдХреЛрдб рдХреЛ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдХреЗрд╡рд▓ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдпрд╣рд╛рдБ db.session.rollback()



ред рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЕрдкрд╡рд╛рдж рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред рдпрджрд┐ рдЕрдкрд╡рд╛рдж рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЗ рдХрд╛рд░рдг рд╣реБрдЖ рдерд╛, рддреЛ рд╣рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕рддреНрд░ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред



404 рддреНрд░реБрдЯрд┐ рдХреЗ рд▓рд┐рдП рдЯреЗрдореНрдкреНрд▓реЗрдЯ:

 <!-- extend base layout --> {% extends "base.html" %} {% block content %} <h1>File Not Found</h1> <p><a href="{{url_for('index')}}">Back</a></p> {% endblock %}
      
      







рдФрд░ рддреНрд░реБрдЯрд┐ 500 тАЛтАЛрдХреЗ рд▓рд┐рдП рдПрдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рднреА:

 <!-- extend base layout --> {% extends "base.html" %} {% block content %} <h1>An unexpected error has occurred</h1> <p>The administrator has been notified. Sorry for the inconvenience!</p> <p><a href="{{url_for('index')}}">Back</a></p> {% endblock %}
      
      







рджреЛрдиреЛрдВ рд╣реА рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╣рдо рдЕрднреА рднреА рдореВрд▓ рдкреЗрдЬ рдХреЗ рд░реВрдк рдореЗрдВ base.html



рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рджреЛрдиреЛрдВ HTTP рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рд╣рдорд╛рд░реЗ рдорд╛рдЗрдХреНрд░реЛрдмреНрд▓реЙрдЧ рдХреЗ рдмрд╛рдХреА рдкреГрд╖реНрдареЛрдВ рдХреЗ рд╕рдорд╛рди рд╢реИрд▓реА рдореЗрдВ рджрд┐рдЦрддреЗ рд╣реИрдВред



рдореЗрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рднреЗрдЬрдирд╛



рджреВрд╕рд░реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рджреЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдПрд░рд░ рд░рд┐рдкреЛрд░реНрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рд╕реЗрдЯ рдХрд░реЗрдВрдЧреЗред рд╣рд░ рдмрд╛рд░ рддреНрд░реБрдЯрд┐ рд╣реЛрдиреЗ рдкрд░ рдкрд╣рд▓рд╛ рдИрдореЗрд▓ рд╣рдореЗрдВ рднреЗрдЬреЗрдЧрд╛ред



рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдореЗрд▓ рд╕рд░реНрд╡рд░ рдФрд░ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рдкреНрд░рд╢рд╛рд╕рдХреЛрдВ рдХреА рд╕реВрдЪреА рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред ( config.py



)
:



 # mail server settings MAIL_SERVER = 'localhost' MAIL_PORT = 25 MAIL_USERNAME = None MAIL_PASSWORD = None # administrator list ADMINS = ['you@example.com']
      
      







рдмреЗрд╢рдХ, рдЖрдкрдХреЛ рдЗрди рдореВрд▓реНрдпреЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред



рдлреНрд▓рд╛рд╕реНрдХ рдкрд╛рдпрдерди рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реЗ logging



рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдИрдореЗрд▓ рдкрд░ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ рдХреА рд╕реНрдерд╛рдкрдирд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реЛрдЧреА ( app/__init__.py



)
:



 from config import basedir, ADMINS, MAIL_SERVER, MAIL_PORT, MAIL_USERNAME, MAIL_PASSWORD if not app.debug: import logging from logging.handlers import SMTPHandler credentials = None if MAIL_USERNAME or MAIL_PASSWORD: credentials = (MAIL_USERNAME, MAIL_PASSWORD) mail_handler = SMTPHandler((MAIL_SERVER, MAIL_PORT), 'no-reply@' + MAIL_SERVER, ADMINS, 'microblog failure', credentials) mail_handler.setLevel(logging.ERROR) app.logger.addHandler(mail_handler)
      
      







рдпрджрд┐ рдбрд┐рдмрдЧрд┐рдВрдЧ рдореЛрдб рдмрдВрдж рд╣реИ рддреЛ рд╣рдо рдХреЗрд╡рд▓ рдпреЗ рдИрдореЗрд▓ рднреЗрдЬреЗрдВрдЧреЗред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдореЗрд▓ рд╕рд░реНрд╡рд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдирд╣реАрдВ рд╣реИ рддреЛ рдпрд╣ рдареАрдХ рд╣реИред рд╣рдорд╛рд░реЗ рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП, SMTP рдбрд┐рдмрдЧ рд╕рд░реНрд╡рд░, рдЬреЛ рдкрд╛рдпрдерди рд╣рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдХрд╛рдлреА рдЙрдкрдпреБрдХреНрдд рд╣реИред рдЗрд╕реЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрдВрд╕реЛрд▓ рдореЗрдВ рдЯрд╛рдЗрдк рдХрд░реЗрдВ (рдпрд╛ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдкрд░ рдпрджрд┐ рдЖрдк рдПрдХ Windows рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣реИрдВ):

 python -m smtpd -n -c DebuggingServer localhost:25
      
      





рдЙрд╕рдХреЗ рдмрд╛рдж, рдПрдкреНрд▓рд┐рдХреЗрд╢рди рджреНрд╡рд╛рд░рд╛ рднреЗрдЬреЗ рдЧрдП рд╕рднреА рдкрддреНрд░реЛрдВ рдХреЛ рд╕реАрдзреЗ рдХрдВрд╕реЛрд▓ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред (рдиреЛрдЯред рдЖрдк рдПрдХ рдмреЗрд╣рдж рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ SMTP рд╕рд░реНрд╡рд░ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рдЬреНрдЮрд╛рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ - рдореЗрд▓рдХреИрдЪрд░ ред рдпрд╣ рд╡рд┐рдзрд┐ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд▓рд┐рдП рд░реВрдмреА рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред)



рдХрд┐рд╕реА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд▓реЙрдЧ рдЗрди рдХрд░рдирд╛



рдореЗрд▓ рдореЗрдВ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрднреА-рдХрднреА рдпрд╣ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рд╣рдореЗрдВ рдЯреНрд░реЗрд╕реЗрдХрдмреИрдХ рдореЗрдВ рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдФрд░ рдлрд┐рд░ рд▓реЙрдЧ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧреАред



рд╕реЗрдЯрдЕрдк рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдмрд╣реБрдд рдХреБрдЫ рд╡реИрд╕рд╛ рд╣реА рд╣реИ рдЬреИрд╕рд╛ рд╣рдордиреЗ рд╕рд┐рд░реНрдл рдореЗрд▓ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдерд╛ (рдлрд╝рд╛рдЗрд▓ app/__init__.py



)




 if not app.debug: import logging from logging.handlers import RotatingFileHandler file_handler = RotatingFileHandler('tmp/microblog.log', 'a', 1 * 1024 * 1024, 10) file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]')) app.logger.setLevel(logging.INFO) file_handler.setLevel(logging.INFO) app.logger.addHandler(file_handler) app.logger.info('microblog startup')
      
      







рд▓реЙрдЧ рдХреЛ tmp



рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ microblog.log



рдирд╛рдо рд╕реЗ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рдордиреЗ RotatingFileHandler



рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдЬреЛ рдЖрдкрдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдбреЗрдЯрд╛ рдХреА рдорд╛рддреНрд░рд╛ рдкрд░ рдПрдХ рд╕реАрдорд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЖрдХрд╛рд░ рдПрдХ рдореЗрдЧрд╛рдмрд╛рдЗрдЯ рддрдХ рд╕реАрдорд┐рдд рд╣реИ, рдФрд░ рдЕрдВрддрд┐рдо рджрд╕ рдлрд╛рдЗрд▓реЗрдВ рд╕рд╣реЗрдЬреА рдЧрдИ рд╣реИрдВред



logging.Formatter



рдХреНрд▓рд╛рд╕ рд▓реЙрдЧ рдПрдВрдЯреНрд░реАрдЬ рдХреЗ рд▓рд┐рдП рдПрдХ рдордирдорд╛рдирд╛ рдкреНрд░рд╛рд░реВрдк рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рд╣рдо рд╕рдВрднрд╡ рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд┐рд╕реНрддреГрдд рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╣рдо рд╕рдВрджреЗрд╢ рдХреЛ рдЦреБрдж рд╣реА рд╕рд╣реЗрдЬ рд▓реЗрдВрдЧреЗ, рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк , рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдХреА рд╕реНрдерд┐рддрд┐, рд╕рд╛рде рд╣реА рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдФрд░ рд▓рд╛рдЗрди рдирдВрдмрд░ рдЬрд╣рд╛рдВ рд╕реЗ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рд╢реБрд░реВ рдХреА рдЧрдИ рдереАред



рд▓реЙрдЧ рдХреЛ рдЕрдзрд┐рдХ рдЙрдкрдпреЛрдЧреА рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рджреЛрдиреЛрдВ app.logger



рдФрд░ file_handler



рдореЗрдВ рд▓реЙрдЧрд┐рдВрдЧ рдХреЗ рд╕реНрддрд░ рдХреЛ рдХрдо рдХрд░рддреЗ рд╣реИрдВ, рдпрд╣ рд╣рдореЗрдВ рди рдХреЗрд╡рд▓ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд░рд┐рдХреЙрд░реНрдб рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рдмрд▓реНрдХрд┐ рдЕрдиреНрдп рдЬрд╛рдирдХрд╛рд░реА рднреА рдЬреЛ рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдЖрд╡реЗрджрди рдХреЗ рдкреНрд░рд╛рд░рдВрдн рд╕рдордп рдХреЛ рд░рд┐рдХреЙрд░реНрдб рдХрд░реЗрдВрдЧреЗред рдЕрдм, рд╣рд░ рдмрд╛рд░ рдорд╛рдЗрдХреНрд░реЛрдмреНрд▓реЙрдЧ рдХреЛ рдбрд┐рдмрдЧрд┐рдВрдЧ рдореЛрдб рдХреЗ рдмрд┐рдирд╛ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕ рдИрд╡реЗрдВрдЯ рдХреЛ рд▓реЙрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред



рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╣рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрджрд┐ рд╣рдорд╛рд░рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд░рд┐рдореЛрдЯ рд╡реЗрдм рд╕рд░реНрд╡рд░ рдкрд░ рдЪрд▓рддрд╛ рд╣реИ, рддреЛ рдирд┐рджрд╛рди рдФрд░ рдбреАрдмрдЧрд┐рдВрдЧ рдореБрд╢реНрдХрд┐рд▓ рд╣реЛрдЧрд╛ред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рд╕рд░реНрд╡рд░ рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рдмрд┐рдирд╛ рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЧреНрд░рд┐рдо рд░реВрдк рд╕реЗ рдзреНрдпрд╛рди рд░рдЦрдиреЗ рдпреЛрдЧреНрдп рд╣реИред



рдмрдЧ рдареАрдХ рдХрд░рдирд╛



рддреЛ, рдЪрд▓реЛ рдЕрдВрдд рдореЗрдВ рдмрдЧ рдХреЛ рдЙрд╕реА рдЙрдкрдирд╛рдо рд╕реЗ рдареАрдХ рдХрд░реЗрдВред



рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рджреЛ рд╕рдорд╕реНрдпрд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИрдВ рдЬрд╣рд╛рдВ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдЪреЗрдХрд┐рдВрдЧ рдЧрд╛рдпрдм рд╣реИред рдкрд╣рд▓рд╛ after_login



рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рд╣реИ, рдЬрд┐рд╕реЗ рддрдм рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд▓реЙрдЧ рдЗрди рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╣рдореЗрдВ рдПрдХ рдирдпрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:



 if user is None: nickname = resp.nickname if nickname is None or nickname == "": nickname = resp.email.split('@')[0] nickname = User.make_unique_nickname(nickname) user = User(nickname = nickname, email = resp.email, role = ROLE_USER) db.session.add(user) db.session.commit()
      
      







рд╣рдорд╛рд░рд╛ рд╕рдорд╛рдзрд╛рди рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдЙрдкрдирд╛рдо рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд░реНрдЧ рдХреЛ рдирд┐рд░реНрджреЗрд╢ рджреЗрдирд╛ рд╣реИред рдЗрд╕реЗ рдЗрд╕реА рддрд░рд╣ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдлрд╝рд╛рдЗрд▓ app/models.py



)
:

 class User(db.Model): # ... @staticmethod def make_unique_nickname(nickname): if User.query.filter_by(nickname = nickname).first() == None: return nickname version = 2 while True: new_nickname = nickname + str(version) if User.query.filter_by(nickname = new_nickname).first() == None: break version += 1 return new_nickname # ...
      
      







рдпрд╣ рд╡рд┐рдзрд┐ рдХреЗрд╡рд▓ рддрдм рддрдХ рдЙрдкрдирд╛рдо рдореЗрдВ рдПрдХ рдХрд╛рдЙрдВрдЯрд░ рдЬреЛрдбрд╝рддреА рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдпрд╣ рдЕрджреНрд╡рд┐рддреАрдп рди рд╣реЛ рдЬрд╛рдПред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ "рдорд┐рдЧреБрдПрд▓" рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж рд╣реИ, рддреЛ рд╡рд┐рдХрд▓реНрдк "рдорд┐рдЧреБрдПрд▓ 2" рд╡рд┐рдзрд┐ рдореЗрдВ рдкреЗрд╢ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдлрд┐рд░, рдЕрдЧрд░ рдРрд╕рд╛ рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣реИ, рддреЛ "рдорд┐рдЧреБрдПрд▓ 3" рдФрд░ рдЗрд╕реА рддрд░рд╣ред рд╕реНрдЯреЗрдЯрдорд┐рдереЛрдб рдбреЗрдХреЛрд░реЗрдЯрд░ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ , рд╣рдордиреЗ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдСрдкрд░реЗрд╢рди рд╡рд░реНрдЧ рдХреЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рдмрдВрдзрд╛ рдирд╣реАрдВ рд╣реИред



рджреВрд╕рд░рд╛ рд╕реНрдерд╛рди рдЬрд╣рд╛рдВ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреА рд╕рдорд╕реНрдпрд╛ рдЕрднреА рднреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИ рд╡рд╣ рд╣реИ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдПрдбрд┐рдЯрд┐рдВрдЧ рдкреЗрдЬред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдЗрд╕ рддрдереНрдп рд╕реЗ рдЬрдЯрд┐рд▓ рд╣реИ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдкрдиреЗ рдЙрдкрдирд╛рдо рдХрд╛ рдЪрдпрди рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рдЬрд╛рдВрдЪ рдХрд░рдирд╛ рд╣реИ рдФрд░, рд╡рд┐рдлрд▓рддрд╛ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдПрдХ рдЕрдиреНрдп рдЙрдкрдирд╛рдо рдЪреБрдирдиреЗ рдХреА рдкреЗрд╢рдХрд╢ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдлрд╝реАрд▓реНрдб рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред рдпрджрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд┐рд╕реА рдореМрдЬреВрджрд╛ рдЙрдкрдирд╛рдо рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдлрд╝реЙрд░реНрдо рдХреЗрд╡рд▓ рд╕рддреНрдпрд╛рдкрди рдкрд╛рд╕ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред рдЕрдкрдиреЗ рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ validate



рд╡рд┐рдзрд┐ ( app/forms.py



)
рдХреЛ рдУрд╡рд░рд▓реЛрдб рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

 from app.models import User class EditForm(Form): nickname = TextField('nickname', validators = [Required()]) about_me = TextAreaField('about_me', validators = [Length(min = 0, max = 140)]) def __init__(self, original_nickname, *args, **kwargs): Form.__init__(self, *args, **kwargs) self.original_nickname = original_nickname def validate(self): if not Form.validate(self): return False if self.nickname.data == self.original_nickname: return True user = User.query.filter_by(nickname = self.nickname.data).first() if user != None: self.nickname.errors.append('This nickname is already in use. Please choose another one.') return False return True
      
      







рдкреНрд░рдкрддреНрд░ рдирд┐рд░реНрдорд╛рддрд╛ рдЕрдм рдПрдХ рдирдпрд╛ рддрд░реНрдХ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ - original_nickname



ред validate



рд╡рд┐рдзрд┐ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИ рдХрд┐ рдЙрдкрдирд╛рдо рдмрджрд▓ рдЧрдпрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред рдЕрдЧрд░ рдмрджрд▓рд╛ рд╣реИ, рддреЛ рд╣рдо рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХрд░реЗрдВрдЧреЗред



рд╣рдо рдПрдХ рдирдП рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдлрд╝реЙрд░реНрдо рдХреЛ рдЖрд░рдВрдн рдХрд░рддреЗ рд╣реИрдВ:

 @app.route('/edit', methods = ['GET', 'POST']) @login_required def edit(): form = EditForm(g.user.nickname) # ...
      
      







рд╣рдореЗрдВ рдЙрди рд╕рднреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рднреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рдкреНрд░рдкрддреНрд░ рд╕рддреНрдпрд╛рдкрди рдХреЗ рджреМрд░рд╛рди рд╣реЛрддреА рд╣реИрдВ, рдЬрд┐рд╕ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрд╕рдХреЗ рдмрдЧрд▓ рдореЗрдВред (рдлрд╝рд╛рдЗрд▓ app/templates/edit.html



)
:



 <td>Your nickname:</td> <td> {{form.nickname(size = 24)}} {% for error in form.errors.nickname %} <br><span style="color: red;">[{{error}}]</span> {% endfor %} </td>
      
      







рдпрд╣ рд╕рдм, рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛ рд╣рд▓ рд╣реЛ рдЧрдИ рд╣реИ! рдпрд╣ рд╕рдЪ рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрднреА рднреА рдХрдИ рдереНрд░реЗрдбреНрд╕ рдпрд╛ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рд╕реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рддрдХ рдПрдХ рд╕рд╛рде рдкрд╣реБрдВрдЪрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдорд╕реНрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рд╡рд┐рд╖рдп рднрд╡рд┐рд╖реНрдп рдХреЗ рд▓реЗрдЦ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред



рдЕрдм рдЖрдк рдлрд┐рд░ рд╕реЗ рдЙрдкрдирд╛рдо рдХреЛ рдореМрдЬреВрджрд╛ рдПрдХ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреЛрдИ рдФрд░ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИред



рдкрд░реАрдХреНрд╖рдг рд░реВрдкрд░реЗрдЦрд╛



рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рд╕рд╛рде, рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдирд╛ рдХрдард┐рди рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдореМрдЬреВрджрд╛ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдирд╣реАрдВ рддреЛрдбрд╝реЗрдВрдЧреЗред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдирд╛ рдЗрддрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред



рдкрд╛рд░рдВрдкрд░рд┐рдХ рдкрд░реАрдХреНрд╖рдг рджреГрд╖реНрдЯрд┐рдХреЛрдг рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИред рдЖрдк рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рд╕рднреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрддреЗ рд╣реИрдВред рд╕рдордп-рд╕рдордп рдкрд░ рд╡рд┐рдХрд╛рд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рджреМрд░рд╛рди, рдЖрдкрдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдХрд┐ рд╕рдм рдХреБрдЫ рдЕрднреА рднреА рд╕реНрдерд┐рд░ рд╣реИред рдкрд░реАрдХреНрд╖рдг рдХрд╡рд░реЗрдЬ рдЬрд┐рддрдирд╛ рд╡реНрдпрд╛рдкрдХ рд╣реЛрдЧрд╛, рдЙрддрдирд╛ рд╣реА рдЖрдк рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рд╣реИред



рдЖрдЗрдП, рд╕рдмрд╕реЗ рдЫреЛрдЯреЗ рдореЙрдбреНрдпреВрд▓ (рдлрд╝рд╛рдЗрд▓ app/tests.py



)
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЫреЛрдЯрд╛ рдкрд░реАрдХреНрд╖рдг рдврд╛рдБрдЪрд╛ рд▓рд┐рдЦреЗрдВ:



 #!flask/bin/python import os import unittest from config import basedir from app import app, db from app.models import User class TestCase(unittest.TestCase): def setUp(self): app.config['TESTING'] = True app.config['CSRF_ENABLED'] = False app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'test.db') self.app = app.test_client() db.create_all() def tearDown(self): db.session.remove() db.drop_all() def test_avatar(self): u = User(nickname = 'john', email = 'john@example.com') avatar = u.avatar(128) expected = 'http://www.gravatar.com/avatar/d4c74594d841139328695756648b6bd6' assert avatar[0:len(expected)] == expected def test_make_unique_nickname(self): u = User(nickname = 'john', email = 'john@example.com') db.session.add(u) db.session.commit() nickname = User.make_unique_nickname('john') assert nickname != 'john' u = User(nickname = nickname, email = 'susan@example.com') db.session.add(u) db.session.commit() nickname2 = User.make_unique_nickname('john') assert nickname2 != 'john' assert nickname2 != nickname if __name__ == '__main__': unittest.main()
      
      







рдЗрд╕ рд▓реЗрдЦ рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдкрд░реЗ unittest



рдЪрд░реНрдЪрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдЗрд╕ рдореЙрдбреНрдпреВрд▓ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдирд╣реАрдВ рд╣реИрдВ, рддреЛ рдЖрдк рдмрд╕ рдорд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг TestCase



рдХреНрд▓рд╛рд╕ рдореЗрдВ рд╣реИрдВред setUp



рдФрд░ tearDown



рд╡рд┐рд╢реЗрд╖ рдорд╣рддреНрд╡ рдХреЗ рд╣реИрдВ, рдЗрдиреНрд╣реЗрдВ рдХреНрд░рдорд╢рдГ рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рдкрд╣рд▓реЗ рдФрд░ рдмрд╛рдж рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдХрдИ рдкрд░реАрдХреНрд╖рдг рд╕рдореВрд╣реЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд╣рд╛рдВ рдкреНрд░рддреНрдпреЗрдХ рд╕рдореВрд╣ unittest.TestCase



рдХрд╛ рдПрдХ рдЙрдкрд╡рд░реНрдЧ рд╣реИ, рдлрд┐рд░ рдкреНрд░рддреНрдпреЗрдХ рд╕рдореВрд╣ рдХрд╛ рдЕрдкрдирд╛ setUp



рдФрд░ tearDown



ред



рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдкрд░реАрдХреНрд╖рдг рд╕реЗ рдкрд╣рд▓реЗ рдФрд░ рдмрд╛рдж рдореЗрдВ рдХрд┐рд╕реА рднреА рдЬрдЯрд┐рд▓ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред setUp



, рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдереЛрдбрд╝рд╛ рдмрджрд▓рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рдбреЗрдЯрд╛рдмреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред tearDown



рд╡рд┐рдзрд┐ рдореЗрдВ tearDown



рд╣рдо рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рд╕рд╛рдл рдХрд░рддреЗ рд╣реИрдВред



рдкрд░реАрдХреНрд╖рдг рдЙрди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рдХреБрдЫ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЗрд╕рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреА рддреБрд▓рдирд╛ рдЙрджреНрджреЗрд╢реНрдп рд╕реЗ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рдкрд░рд┐рдгрд╛рдо рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддреЗ рд╣реИрдВ, рддреЛ рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдлрд▓ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред



рдЗрд╕рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдврд╛рдВрдЪреЗ рдореЗрдВ рджреЛ рдкрд░реАрдХреНрд╖рдг рд╣реИрдВред рдкрд╣рд▓реЗ рдЕрд╡рддрд╛рд░ URL рдХреА рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдкрд┐рдЫрд▓реЗ рдЕрдзреНрдпрд╛рдп рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдерд╛ред рджреВрд╕рд░рд╛ рдкрд░реАрдХреНрд╖рдг make_unique_nickname



рд╡рд┐рдзрд┐ рдХреА рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╣рдордиреЗ рдЕрднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦрд╛ рдерд╛ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ 'рдЬреЙрди' рдирд╛рдо рд╕реЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдзрд┐ рдХреЛ 'рдЬреЙрди' рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдПрдХ рдЙрдкрдирд╛рдо рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдлрд┐рд░ рд╣рдо рд╕реБрдЭрд╛рдП рдЧрдП рдЙрдкрдирд╛рдо рдХреЗ рд╕рд╛рде рджреВрд╕рд░рд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдирд╛рддреЗ рдФрд░ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВ рдФрд░ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ make_unique_nickname



рд▓рд┐рдП рдПрдХ рдФрд░ рдХреЙрд▓ рджреЛрдиреЛрдВ рдирд┐рд░реНрдорд┐рдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рдирд╛рдореЛрдВ рд╕реЗ рдЕрд▓рдЧ рдирд╛рдо рд▓реМрдЯрд╛рдПрдЧрд╛ред



рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдПрдБ:



 ./tests.py
      
      







рдпрджрд┐ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ, рддреЛ рдЙрдиреНрд╣реЗрдВ рдХрдВрд╕реЛрд▓ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред



рдЕрдВрддрд┐рдо рд╢рдмреНрдж



рдпрд╣ рдбрд┐рдмрдЧрд┐рдВрдЧ, рддреНрд░реБрдЯрд┐рдпреЛрдВ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХреА рд╣рдорд╛рд░реА рдЪрд░реНрдЪрд╛ рдХрд╛ рд╕рдорд╛рдкрди рдХрд░рддрд╛ рд╣реИред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рдпрд╣ рд▓реЗрдЦ рдЕрдЪреНрдЫрд╛ рд▓рдЧрд╛ рд╣реЛрдЧрд╛ред рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣, рдпрджрд┐ рдЖрдкрдХреЗ рдХреЛрдИ рдкреНрд░рд╢реНрди рд╣реИрдВ, рддреЛ рдЙрдиреНрд╣реЗрдВ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдкреВрдЫреЗрдВред



рдирд╡реАрдирддрдо рдорд╛рдЗрдХреНрд░реЛрдмреНрд▓реЙрдЧрд┐рдВрдЧ рдХреЛрдб рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рд┐рдВрдХ рдкрд░ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

рдорд╛рдЗрдХреНрд░реЛрдмреНрд▓реЙрдЧ-0.7.zip рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ



рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣, рдХреЛрдИ рдЖрднрд╛рд╕реА рд╡рд╛рддрд╛рд╡рд░рдг рдпрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рдирд╣реАрдВ рд╣реИред рдЙрдирдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦреЛрдВ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИред



рдЬрд▓реНрдж рдорд┐рд▓рддреЗ рд╣реИрдВ!



рдорд┐рдЧреБрдПрд▓



All Articles