Django рдореЗрдВ "рд╣рдЯрд╛рдирд╛" рдСрдмреНрдЬреЗрдХреНрдЯ



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

рдкреНрд░рд╛рдЧрд┐рддрд┐рд╣рд╛рд╕


рдЕрдзрд┐рдХрд╛рдВрд╢ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХреЗ рд▓рд┐рдП, Mail.ru Group рдФрд░ VKontakte рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреА рдПрдХ рд╕реЗрд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ - рдирд┐рдЧрд░рд╛рдиреА ред 2012 рдХреЗ рдЕрдВрдд рд╕реЗ рдЕрдкрдиреЗ рдЗрддрд┐рд╣рд╛рд╕ рдХреЛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реБрдП, 6 рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рдпрд╣ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдПрдХ рд╡рд┐рд╢рд╛рд▓ рдкреНрд░рдгрд╛рд▓реА рдореЗрдВ рд╡рд┐рдХрд╕рд┐рдд рд╣реБрдИ рд╣реИ, рдЬрд┐рд╕рдиреЗ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдкреНрд░рд╛рдкреНрдд рдХреА рд╣реИред рдореЙрдирд┐рдЯрд░рд┐рдВрдЧ рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рд╕рд░реНрд╡рд░реЛрдВ рдХреА рдЙрдкрд▓рдмреНрдзрддрд╛ рдФрд░ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреА рд╢реБрджреНрдзрддрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреА рд╣реИ, рдЙрдкрдпреЛрдЧ рдХреА рдЧрдИ рдореЗрдореЛрд░реА, рд╕реАрдкреАрдпреВ рдЙрдкрдпреЛрдЧ рдЖрджрд┐ рдкрд░ рдЖрдВрдХрдбрд╝реЗ рдПрдХрддреНрд░ рдХрд░рддреА рд╣реИред рдЬрдм рдореЙрдирд┐рдЯрд░ рдХрд┐рдП рдЧрдП рд╕рд░реНрд╡рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдЕрдиреБрдореЗрдп рдореВрд▓реНрдпреЛрдВ рд╕реЗ рдЕрдзрд┐рдХ рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд▓реЛрдЧ рд╕рд┐рд╕реНрдЯрдо рдФрд░ рдПрд╕рдПрдордПрд╕ рджреНрд╡рд╛рд░рд╛ рд╕реВрдЪрдирд╛рдПрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред

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

рдирд┐рд╖реНрдХрд╛рд╕рди


рдореИрдВ рдЬрд╛рдирдмреВрдЭрдХрд░ рд▓реЗрдЦ рдХреЗ рд╢реАрд░реНрд╖рдХ рдореЗрдВ "рдЪрд┐рд╣реНрди" рд╢рдмреНрдж рдХреЛ рдЙрджреНрдзрд░рдг рдЪрд┐рд╣реНрдиреЛрдВ рдореЗрдВ рд▓рд┐рдЦрд╛ рдерд╛ред рдХрд┐рд╕реА рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╕рд┐рд╕реНрдЯрдо рд╕реЗ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рдХрдИ рддрд░реАрдХреЗ рд╣реИрдВ:

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

Iteration # 1


рдкреНрд░рд╛рд░рдВрдн рдореЗрдВ, рдкрд╣рд▓реЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬрдм рд╣рдордиреЗ рдмрд╕ object.delete() рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдерд╛ рдФрд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╕рднреА рдирд┐рд░реНрднрд░рддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рд▓реЗрдХрд┐рди рд╕рдордп рдХреЗ рд╕рд╛рде, рд╣рдореЗрдВ рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдЫреЛрдбрд╝рдирд╛ рдкрдбрд╝рд╛, рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рд╡рд╕реНрддреБ рдореЗрдВ рд▓рд╛рдЦреЛрдВ рдЕрдиреНрдп рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕рд╛рде рдирд┐рд░реНрднрд░рддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдФрд░ рд╡рд┐рд▓реЛрдкрди рд╣рдЯрд╛рдХрд░ рдХрдареЛрд░ рд░реВрдк рд╕реЗ рдЕрд╡рд░реБрджреНрдз рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЗ рд╕рд╛рдеред рдФрд░ рдЪреВрдВрдХрд┐ рд╕реЗрд╡рд╛ рдкреНрд░рддреНрдпреЗрдХ рд╕реЗрдХрдВрдб рдореЗрдВ рд╣рдЬрд╛рд░реЛрдВ рдЪреЗрдХ рдХрд░рддреА рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд▓реЙрдЧ рдХрд░рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд░рдиреЗ рд╕реЗ рд╕реЗрд╡рд╛ рдореЗрдВ рдПрдХ рдЧрдВрднреАрд░ рдордВрджреА рдЖрдИ, рдЬреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЕрд╕реНрд╡реАрдХрд╛рд░реНрдп рдереАред

Iteration # 2


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

 from django.contrib.admin.util import NestedObjects from django.db import DEFAULT_DB_ALIAS collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([obj]) objects_to_delete = collector.nested() # Recursive delete objects 

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

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

Iteration # 3


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

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

 def exclude_objects_for_deleted_hosts(*fields): """ Decorator that adds .exclude({field__}is_deleted=True) for model_class.objects.get_queryset :param fields: fields for exclude condition """ def wrapper(model_class): def apply_filters(qs): for field in filter_fields: qs = qs.exclude(**{ '{}is_deleted'.format('{}__'.format(field) if field else ''): True, }) return qs model_class.all_objects = copy.deepcopy(model_class.objects) filter_fields = set(fields) get_queryset = model_class.objects.get_queryset model_class.objects.get_queryset = lambda: apply_filters(get_queryset()) # save info about model decorator setattr(model_class, DECORATOR_DEL_HOST_ATTRIBUTE, filter_fields) return model_class return wrapper 

рдлрд╝реАрд▓реНрдб рдореЙрдбрд▓ рдХреЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП exclude_objects_for_deleted_hosts(fields) рдбреЗрдХреЛрд░реЗрдЯрд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ exclude рдлрд╝рд┐рд▓реНрдЯрд░ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдЬреЛ рдХреЗрд╡рд▓ рдЙрди рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЛ рд╣рдЯрд╛рддрд╛ рд╣реИ рдЬрд┐рдиреНрд╣реЗрдВ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

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

 @exclude_objects_for_deleted_hosts('host') class Alias(models.Model): host = models.ForeignKey(to=Host, verbose_name='Host', related_name='alias') 

рдЕрдм, Host рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ is_deleted рд╡рд┐рд╢реЗрд╖рддрд╛ рдмрджрд▓реЗрдВ:

 host.is_deleted = True # after this save the host and all related objects will be inaccessible host.save() 

рд╕рднреА рдкреНрд░рд╢реНрди рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЙрди рд░рд┐рдХреЙрд░реНрдб рдХреЛ рдмрд╛рд╣рд░ рдХрд░ рджреЗрдВрдЧреЗ рдЬреЛ рджреВрд░рд╕реНрде рд╡рд╕реНрддреБрдУрдВ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддреЗ рд╣реИрдВ:

 # model decorator @exclude_objects_for_deleted_hosts('checker__monhost', 'alias__host') CheckerToAlias.objects.filter( alias__hostname__in=['cloud.spb.s', 'cloud.msk.s'] ).values('id') 

рдпрд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдПрд╕рдХреНрдпреВрдПрд▓ рдХреНрд╡реЗрд░реА рдХреЛ рдкреВрд░рд╛ рдХрд░рддрд╛ рд╣реИ:

 SELECT monitoring_checkertoalias.id FROM monitoring_checkertoalias INNER JOIN monitoring_checker ON (`monitoring_checkertoalias`.`checker_id` = monitoring_checker.`id`) INNER JOIN Hosts ON (`monitoring_checker`.`monhost_id` = Hosts.`id`) INNER JOIN dcmap_alias ON (`monitoring_checkertoalias`.`alias_id` = dcmap_alias.`id`) INNER JOIN Hosts T5 ON (`dcmap_alias`.`host_id` = T5.`id`) WHERE ( NOT (`Hosts`.`is_deleted` = TRUE) -- ,   monitoring_checker AND NOT (T5.`is_deleted` = TRUE) -- ,   dcmap_alias AND dcmap_alias.name IN ('dir1.server.p', 'dir2.server.p') ); 

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдбреЗрдХреЛрд░реЗрдЯрд░ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд `is_deleted` = TRUE рдФрд░ `is_deleted` = TRUE рдЪреЗрдХ рдХреЛ рдЕрдиреБрд░реЛрдз `is_deleted` = TRUE рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред

рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛


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

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

рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛


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

 host.hostname = '{}_{}'.format(host.hostname, uuid.uuid4()) host.is_deleted = True host.save() 

рд╢реЛрд╖рдг


рдкреНрд░рддреНрдпреЗрдХ рдирдП рдореЙрдбрд▓ рдпрд╛ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрд╢реНрд░рд┐рдд рдореЙрдбрд▓ рдХреА рдЦреЛрдЬ рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдордиреЗ "рд╕реНрдорд╛рд░реНрдЯ" рдЯреЗрд╕реНрдЯ рд▓рд┐рдЦрд╛:

 def test_deleted_host_decorator_for_models(self): def recursive_host_finder(model, cache, path, filters): # cache for skipping looked models cache.add(model) # process all related models for field in (f for f in model._meta.fields if isinstance(f, ForeignKey)): if field.related_model == Host: filters.add(path + field.name) elif field.related_model not in cache: recursive_host_finder(field.related_model, cache.copy(), path + field.name + '__', filters) # check all models for current_model in apps.get_models(): model_filters = getattr(current_model, DECORATOR_DEL_HOST_ATTRIBUTE, set()) found_filters = set() if current_model == Host: found_filters.add('') else: recursive_host_finder(current_model, set(), '', found_filters) if found_filters or model_filters: try: self.assertSetEqual(model_filters, found_filters) except AssertionError as err: err.args = ( '{}\n !!! Fix decorator "exclude_objects_for_deleted_hosts" ' 'for model {}'.format(err.args[0], current_model), ) raise err 

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

рдЙрдкрд╕рдВрд╣рд╛рд░


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

Source: https://habr.com/ru/post/hi438280/


All Articles