рдкрд╛рдпрдерди рд╡реЗрдм рдбреЗрд╡рд▓рдкрд░ рдкрд╛рдареНрдпрдХреНрд░рдо рдХреА рд╢реБрд░реБрдЖрдд рд╕реЗ рдкрд╣рд▓реЗ рд▓реЗрдЦ рдХрд╛ рдЕрдиреБрд╡рд╛рдж рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред
рдпрджрд┐ рдЖрдкрдХреЗ рдЖрд╡реЗрджрди рдореЗрдВ рдПрдХ рд▓рдВрдмреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╣реИ, рддреЛ рдЖрдк рдЗрд╕реЗ рдорд╛рдирдХ рдЕрдиреБрд░реЛрдз / рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВредрдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЗ рдЖрд╡реЗрджрди рдореЗрдВ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдПрдХ рдердВрдмрдиреЗрд▓ рдЫрд╡рд┐ (рдЬреЛ, рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ, рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА) рдФрд░ рдИрдореЗрд▓ рдкрддреЗ рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рдиреА рд╣реЛрдЧреАред рдпрджрд┐ рдЖрдкрдХрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЫрд╡рд┐ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рдЕрдиреБрд░реЛрдз рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рдкреБрд╖реНрдЯрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ рдИрдореЗрд▓ рднреЗрдЬрддрд╛ рд╣реИ, рддреЛ рдЕрдВрддрд┐рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдкреГрд╖реНрда рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓реЛрдб рдХрд░рдиреЗ рдпрд╛ рдмрдВрдж рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рджреЛрдиреЛрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рдХрд╛рд░рдг рдХрд╛ рдЗрдВрддрдЬрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдЖрдк рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд╛рд░реНрдп рдХрддрд╛рд░ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рддреБрд░рдВрдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд░ рдЫреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЕрдВрддрд┐рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмреИрдХрдЧреНрд░рд╛рдЙрдВрдб рдореЗрдВ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХрд░рддреЗ рд╕рдордп рдХреНрд▓рд╛рдЗрдВрдЯ рдХреА рдУрд░ рд╕реЗ рдЕрдиреНрдп рдХрд╛рдо рдХрд░ рд╕рдХреЗрдЧрд╛ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдкрдХрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЕрдиреНрдп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдореЗрдВ рднреА рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛редрдЖрдЬ рд╣рдо рдРрд╕реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП Django рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдЪрд▓ рд░рд╣реА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реЗрд▓реЗрд░реА рдФрд░ рд░реЗрдбрд┐рд╕ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдФрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ ред рд╣рдо рд╕рднреА рдЯреБрдХрдбрд╝реЛрдВ рдХреЛ рдПрдХ рд╕рд╛рде рдмрд╛рдБрдзрдиреЗ рдХреЗ рд▓рд┐рдП рдбреЙрдХрд░ рдФрд░ рдбреЙрдХрд░ рдХрдВрдкреЛрдЬрд╝ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдФрд░ рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдпреВрдирд┐рдЯ рдФрд░ рдЗрдВрдЯреАрдЧреНрд░реЗрд╢рди рдЯреЗрд╕реНрдЯ рдХреЗ рд╕рд╛рде рд╕реЗрд▓реЗрд░реА рдХреА рдиреМрдХрд░рд┐рдпреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдПредрдЗрд╕ рдЧрд╛рдЗрдб рдХреЗ рдЕрдВрдд рддрдХ, рд╣рдо рд╕реАрдЦреЗрдВрдЧреЗ:- рдкреГрд╖реНрдарднреВрдорд┐ рдХреА рдиреМрдХрд░рд┐рдпреЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Django рдореЗрдВ рдЕрдЬрд╡рд╛рдЗрди рдХреЛ рдПрдХреАрдХреГрдд рдХрд░реЗрдВред
- рдбреЙрдХрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдкреИрдХ Django, рдЕрдЬрд╡рд╛рдЗрди, рдФрд░ рд░реЗрдбрд┐рд╕ред
- рдЕрд▓рдЧ рд╡рд░реНрдХрдлрд╝реНрд▓реЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдПрдБ рдЪрд▓рд╛рдПрдБред
- рдХрд┐рд╕реА рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕реЗрд▓реЗрд░реА рд▓реЙрдЧ рд╕рд╣реЗрдЬреЗрдВред
- рдЕрдЬрд╡рд╛рдЗрди рдХреА рдиреМрдХрд░рд┐рдпреЛрдВ рдФрд░ рд╢реНрд░рдорд┐рдХреЛрдВ рдХреА рдирд┐рдЧрд░рд╛рдиреА рдФрд░ рдкреНрд░рд╢рд╛рд╕рди рдХреЗ рд▓рд┐рдП рдлреВрд▓ рд╕реЗрдЯ рдХрд░реЗрдВ ред
- рдЗрдХрд╛рдИ рдФрд░ рдПрдХреАрдХрд░рдг рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде рдЯреЗрд╕реНрдЯ рд╕реЗрд▓реЗрд░реА рдЬреЙрдмреНрд╕ред
рдиреЗрдкрдереНрдп рдХрд╛рд░реНрдп
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдиреБрднрд╡ рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд▓рдВрдмреА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп HTTP рдЕрдиреБрд░реЛрдз / рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реНрдЯреНрд░реАрдо рдХреЗ рдмрд╛рд╣рд░ рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ рдЪрд▓рдирд╛ рдЪрд╛рд╣рд┐рдПредрдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:- рдкреБрд╖реНрдЯрд┐ рдХреЗ рд▓рд┐рдП рдкрддреНрд░ рднреЗрдЬрдирд╛;
- рд╡реЗрдм рд╕реНрдХреИрдкрд┐рдВрдЧ рдФрд░ рдХреНрд░реЙрд▓рд┐рдВрдЧ;
- рдбреЗрдЯрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг;
- рдЗрдореЗрдЬ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ;
- рд░рд┐рдкреЛрд░реНрдЯ рдкреАрдврд╝реАред
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рддреЗ рд╕рдордп, рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЕрд▓рдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдЬрд┐рдиреНрд╣реЗрдВ рдЕрдиреБрд░реЛрдз / рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рдЬреАрд╡рди рдХреЗ рджреМрд░рд╛рди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реАрдЖрд░рдпреВрдбреА рд╕рдВрдЪрд╛рд▓рди, рдЙрди рдХрд╛рд░реНрдпреЛрдВ рд╕реЗ рдЬрд┐рдиреНрд╣реЗрдВ рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПредрдХрд╛рдо рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛
рд╣рдорд╛рд░рд╛ рд▓рдХреНрд╖реНрдп рдПрдХ Django рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рд╣реИ рдЬреЛ рдЕрдиреБрд░реЛрдз / рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЪрдХреНрд░ рдХреЗ рдмрд╛рд╣рд░ рд▓рдВрдмреА рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЬрд╡рд╛рдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред- рдЕрдВрддрд┐рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ POST рдЕрдиреБрд░реЛрдз рднреЗрдЬрдХрд░ рдПрдХ рдирдИ рдиреМрдХрд░реА рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред
- рдЗрд╕ рджреГрд╢реНрдп рдореЗрдВ, рдиреМрдХрд░реА рдХреЛ рдХрддрд╛рд░ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдиреМрдХрд░реА рдЖрдИрдбреА рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╡рд╛рдкрд╕ рднреЗрдЬ рджреА рдЬрд╛рддреА рд╣реИред
- AJAX рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдХреНрд▓рд╛рдЗрдВрдЯ рдиреМрдХрд░реА рдХреА рд╕реНрдерд┐рддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рдХреЛ рдХреНрд╡реЗрд░реА рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдиреМрдХрд░реА рд╕реНрд╡рдпрдВ рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ рдЪрд▓ рд░рд╣реА рд╣реИред

рдкрд░рд┐рдпреЛрдЬрдирд╛ рдирд┐рд░реНрдорд╛рдг
Django-celery рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА
рд╕реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛ рдХреНрд▓реЛрди рдХрд░реЗрдВ рдФрд░ рдорд╛рд╕реНрдЯрд░ рдмреНрд░рд╛рдВрдЪ рдореЗрдВ v1 рдЯреИрдЧ рдкрд░ рдПрдХ рдЪреЗрдХрдЖрдЙрдЯ рдХрд░реЗрдВ :$ git clone https://github.com/testdrivenio/django-celery --branch v1 --single-branch
$ cd django-celery
$ git checkout v1 -b master
рдЪреВрдВрдХрд┐ рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░ рд╣рдореЗрдВ рддреАрди рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ (Django, Redis, Worker) рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЙрдиреНрд╣реЗрдВ рдХрдиреЗрдХреНрдЯ рдХрд░рдХреЗ рдХрд╛рд░реНрдп рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП Docker рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╣рдо рдПрдХ рдЯрд░реНрдорд┐рдирд▓ рд╡рд┐рдВрдбреЛ рдореЗрдВ рдПрдХ рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рдЪрд▓рд╛ рд╕рдХреЗрдВредрдкреНрд░реЛрдЬреЗрдХреНрдЯ рд░реВрдЯ рд╕реЗ, рдЪрд┐рддреНрд░ рдмрдирд╛рдПрдВ рдФрд░ рдбреЙрдХрдЯрд░ рдХрдВрдЯреЗрдирд░ рд▓реЙрдиреНрдЪ рдХрд░реЗрдВ:$ docker-compose up -d --build
рдЬрдм рдирд┐рд░реНрдорд╛рдг рдкреВрд░рд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ рдкрд░ рдЬрд╛рдПрдВ : 1337:
рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкрд╛рд╕ рд╣реБрдП рд╣реИрдВ:$ docker-compose exec web python -m pytest
======================================== test session starts ========================================
platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
django: settings: core.settings (from ini)
rootdir: /usr/src/app, inifile: pytest.ini
plugins: django-3.8.0
collected 1 item
tests/test_tasks.py . [100%]
========================================= 1 passed in 0.47s =========================================
рдЖрдЧреЗ рдмрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреА рд╕рдВрд░рдЪрдирд╛ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ:тФЬтФАтФА .gitignore
тФЬтФАтФА LICENSE
тФЬтФАтФА README.md
тФЬтФАтФА docker-compose.yml
тФФтФАтФА project
тФЬтФАтФА Dockerfile
тФЬтФАтФА core
тФВ тФЬтФАтФА __init__.py
тФВ тФЬтФАтФА asgi.py
тФВ тФЬтФАтФА settings.py
тФВ тФЬтФАтФА urls.py
тФВ тФФтФАтФА wsgi.py
тФЬтФАтФА entrypoint.sh
тФЬтФАтФА manage.py
тФЬтФАтФА pytest.ini
тФЬтФАтФА requirements.txt
тФЬтФАтФА static
тФВ тФЬтФАтФА bulma.min.css
тФВ тФЬтФАтФА jquery-3.4.1.min.js
тФВ тФЬтФАтФА main.css
тФВ тФФтФАтФА main.js
тФЬтФАтФА tasks
тФВ тФЬтФАтФА __init__.py
тФВ тФЬтФАтФА apps.py
тФВ тФЬтФАтФА migrations
тФВ тФВ тФФтФАтФА __init__.py
тФВ тФЬтФАтФА templates
тФВ тФВ тФФтФАтФА home.html
тФВ тФФтФАтФА views.py
тФФтФАтФА tests
тФЬтФАтФА __init__.py
тФФтФАтФА test_tasks.py
рдиреМрдХрд░реА рдХрд╛ рд╢реБрднрд╛рд░рдВрдн
рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдХреЛ project/static/main.js
рдПрдХ рдмрдЯрди рдХреЗ рдХреНрд▓рд┐рдХ рдкрд░ рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рд░реНрд╡рд░ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реБрдП рдЙрдЪрд┐рдд рдиреМрдХрд░реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рдПрдХ AJAX рдХреЗ рдмрд╛рдж рдЕрдиреБрд░реЛрдз рднреЗрдЬрддрд╛ рд╣реИ: 1
, 2
рдпрд╛ 3
ред$('.button').on('click', function() {
$.ajax({
url: '/tasks/',
data: { type: $(this).data('type') },
method: 'POST',
})
.done((res) => {
getStatus(res.task_id);
})
.fail((err) => {
console.log(err);
});
});
рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░, рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рджреГрд╢реНрдп рдкрд╣рд▓реЗ рд╣реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ project/tasks/views.py
:def run_task(request):
if request.POST:
task_type = request.POST.get("type")
return JsonResponse({"task_type": task_type}, status=202)
рдФрд░ рдЕрдм рдордЬрд╝рд╛ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ: рд╣рдо рдЕрдЬрд╡рд╛рдЗрди рдЯрд╛рдИ!рдЕрдЬрд╡рд╛рдЗрди рд╕реЗрдЯрдЕрдк
рдЖрдЗрдП рдлрд╛рдЗрд▓ рдореЗрдВ рд╕реЗрд▓реЗрд░реА рдФрд░ рд░реЗрдбрд┐рд╕ рдЬреЛрдбрд╝рдХрд░ рд╢реБрд░реВ рдХрд░реЗрдВ project/requirements.txt
:celery==4.4.1
Django==3.0.4
redis==3.4.1
pytest==5.4.1
pytest-django==3.8.0
рдЕрдЬрд╡рд╛рдЗрди рдПрдХ рд╕рдВрджреЗрд╢ рдмреНрд░реЛрдХрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ - RabbitMQ , Redis, рдпрд╛ AWS Simple Queue Service (SQS) тАФрд╕реЗрд▓реЗрд░реА рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдФрд░ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдмреАрдЪ рд╕рдВрдЪрд╛рд░ рдХреЛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИред рд╕рдВрджреЗрд╢ рджрд▓рд╛рд▓ рдХреЛ рднреЗрдЬреЗ рдЬрд╛рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рдкрд░рд┐рдгрд╛рдо рдмреИрдХрдПрдВрдб рдкрд░ рднреЗрдЬреЗ рдЬрд╛рддреЗ рд╣реИрдВредрд░реЗрдбрд┐рд╕ рдмреНрд░реЛрдХрд░ рдФрд░ рдмреИрдХрдПрдВрдб рджреЛрдиреЛрдВ рд╣реЛрдВрдЧреЗред docker-compose.yml
рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ Redis рдФрд░ рдЕрдЬрд╡рд╛рдЗрди рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдЬреЛрдбрд╝реЗрдВ :version: '3.7'
services:
web:
build: ./project
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./project:/usr/src/app/
ports:
- 1337:8000
environment:
- DEBUG=1
- SECRET_KEY=dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m
- DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
- CELERY_BROKER=redis://redis:6379/0
- CELERY_BACKEND=redis://redis:6379/0
depends_on:
- redis
celery:
build: ./project
command: celery worker --app=core --loglevel=info
volumes:
- ./project:/usr/src/app
environment:
- DEBUG=1
- SECRET_KEY=dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m
- DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
- CELERY_BROKER=redis://redis:6379/0
- CELERY_BACKEND=redis://redis:6379/0
depends_on:
- web
- redis
redis:
image: redis:5-alpine
рдЗрд╕ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ celery worker --app=core --loglevel=info
:celery worker
рдЕрдЬрд╡рд╛рдЗрди рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ ;--app=core
рд╕реЗрд▓реЗрд░реА core
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдЬрд┐рд╕реЗ рд╣рдо рд╢реАрдШреНрд░ рд╣реА рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВрдЧреЗ);--loglevel=info
рд╕реВрдЪрдирд╛ рд▓реЙрдЧрд┐рдВрдЧ рдХрд╛ рд╕реНрддрд░ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ ред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ рддрд╛рдХрд┐ рд╕реЗрд▓реЗрд░реА рдмреНрд░реЛрдХрд░ рдФрд░ рдмреИрдХрдПрдВрдб рдХреЗ рд░реВрдк рдореЗрдВ рд░реЗрдбрд┐рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗ:CELERY_BROKER_URL = os.environ.get("CELERY_BROKER", "redis://redis:6379/0")
CELERY_RESULT_BACKEND = os.environ.get("CELERY_BROKER", "redis://redis:6379/0")
рдлрд┐рд░ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдиреЗ sample_tasks.py
рдореЗрдВ project/tasks
: рдпрд╣рд╛рдБ, рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ shared_task рдбреЗрдХреЛрд░реЗрдЯрд░ , рд╣рдо рдПрдХ рдирдП рдЕрдЬрд╡рд╛рдЗрди рдХрд╛рд░реНрдп рдмреБрд▓рд╛рдпрд╛ рд╕рдорд╛рд░реЛрд╣ рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ ред рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдХрд╛рд░реНрдп рд╕реНрд╡рдпрдВ Django рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдпрд╣ Celery рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЕрдм рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП :# project/tasks/sample_tasks.py
import time
from celery import shared_task
@shared_task
def create_task(task_type):
time.sleep(int(task_type) * 10)
return True
create_task
celery.py
"project/core"
import os
from celery import Celery
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")
app = Celery("core")
app.config_from_object("django.conf:settings", namespace="CELERY")
app.autodiscover_tasks()
рдпрд╣рд╛рдБ рдХреНрдпрд╛ рдЪрд▓ рд░рд╣рд╛ рд╣реИ?- рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
DJANGO_SETTINGS_MODULE
рддрд╛рдХрд┐ рд╕реЗрд▓реЗрд░реА рдХреЛ рдкрддрд╛ рдЪрд▓реЗ рдХрд┐ рдХреИрд╕реЗ Django рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛ рдЦреЛрдЬрдирд╛ рд╣реИред - рдлрд┐рд░ рд╣рдордиреЗ рдПрдХ рдирд╛рдо рдХреЗ рд╕рд╛рде рдЕрдЬрд╡рд╛рдЗрди рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдпрд╛
core
рдФрд░ рдЗрд╕реЗ рдПрдХ рдЪрд░ рдореЗрдВ рд░рдЦрд╛ app
ред - рдлрд┐рд░ рд╣рдордиреЗ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рд╕реЗрд▓реЗрд░реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдорд╛рди рд▓реЛрдб рдХрд┐рдП
django.conf
ред рд╣рдордиреЗ рдЕрдиреНрдп Django рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рд╕рд╛рде рд╕рдВрдШрд░реНрд╖ рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдирд╛рдорд╕реНрдерд╛рди = "CELERY" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ ред рдЗрд╕рд▓рд┐рдП, рдЕрдЬрд╡рд╛рдЗрди рдХреЗ рд▓рд┐рдП рд╕рднреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдПрдХ рдЙрдкрд╕рд░реНрдЧ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП CELERY_
ред - рдЕрдВрдд рдореЗрдВ,
app.autodiscover_tasks()
рд╕реЗрд▓реЗрд░реА рдХреЛ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рд╕реЗ рдиреМрдХрд░рд┐рдпреЛрдВ рдХреА рддрд▓рд╛рд╢ рдХрд░реЗрдВ settings.INSTALLED_APPS
ред
рдмрджрд▓реЗрдВ project/core/__init__.py
рддрд╛рдХрд┐ рдЬрдм Django рд╢реБрд░реВ рд╣реЛ рддреЛ рдЕрдЬрд╡рд╛рдЗрди рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЕрдкрдиреЗ рдЖрдк рдЖрдпрд╛рдд рд╣реЛ рдЬрд╛рдП:from .celery import app as celery_app
__all__ = ("celery_app",)
рдиреМрдХрд░реА рдХрд╛ рд╢реБрднрд╛рд░рдВрдн
рдиреМрдХрд░реА рд╢реБрд░реВ рдХрд░рдиреЗ рдФрд░ рдЖрдИрдбреА рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рджреГрд╢реНрдп рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░реЗрдВ:@csrf_exempt
def run_task(request):
if request.POST:
task_type = request.POST.get("type")
task = create_task.delay(int(task_type))
return JsonResponse({"task_id": task.id}, status=202)
рдХрд╛рд░реНрдп рдЖрдпрд╛рдд рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ:from tasks.sample_tasks import create_task
рдЫрд╡рд┐рдпрд╛рдВ рдПрдХрддреНрд░ рдХрд░реЗрдВ рдФрд░ рдирдП рдХрдВрдЯреЗрдирд░ рддреИрдирд╛рдд рдХрд░реЗрдВ:$ docker-compose up -d --build
рдирдпрд╛ рдХрд╛рд░реНрдп рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдХрд░реЗрдВ:$ curl -F type=0 http://localhost:1337/tasks/
рдЖрдк рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджреЗрдЦреЗрдВрдЧреЗ:{
"task_id": "6f025ed9-09be-4cbb-be10-1dce919797de"
}
рдХрд╛рд░реНрдп рд╕реНрдерд┐рддрд┐
рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдИрд╡реЗрдВрдЯ рд╣реИрдВрдбрд▓рд░ рдкрд░ рд▓реМрдЯреЗрдВ:$('.button').on('click', function() {
$.ajax({
url: '/tasks/',
data: { type: $(this).data('type') },
method: 'POST',
})
.done((res) => {
getStatus(res.task_id);
})
.fail((err) => {
console.log(err);
});
});
рдЬрдм AJAX рдЕрдиреБрд░реЛрдз рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╡рд╛рдкрд╕ рдЖрддреА рд╣реИ, рддреЛ рд╣рдо getStatus()
рд╣рд░ рд╕реЗрдХрдВрдб рдиреМрдХрд░реА рдЖрдИрдбреА рд╕реЗ рднреЗрдЬреЗрдВрдЧреЗ :function getStatus(taskID) {
$.ajax({
url: `/tasks/${taskID}/`,
method: 'GET'
})
.done((res) => {
const html = `
<tr>
<td>${res.task_id}</td>
<td>${res.task_status}</td>
<td>${res.task_result}</td>
</tr>`
$('#tasks').prepend(html);
const taskStatus = res.task_status;
if (taskStatus === 'SUCCESS' || taskStatus === 'FAILURE') return false;
setTimeout(function() {
getStatus(res.task_id);
}, 1000);
})
.fail((err) => {
console.log(err)
});
}
рдпрджрд┐ рдЙрддреНрддрд░ рд╣рд╛рдБ рд╣реИ, рддреЛ DOM рдЯреЗрдмрд▓ рдореЗрдВ рдПрдХ рдирдИ рдкрдВрдХреНрддрд┐ рдЬреЛрдбрд╝реА рдЬрд╛рдПрдЧреАред get_status
рд╕реНрдерд┐рддрд┐ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджреГрд╢реНрдп рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░реЗрдВ :@csrf_exempt
def get_status(request, task_id):
task_result = AsyncResult(task_id)
result = {
"task_id": task_id,
"task_status": task_result.status,
"task_result": task_result.result
}
return JsonResponse(result, status=200)
рдЖрдпрд╛рдд AsyncResult :from celery.result import AsyncResult
рдЕрджреНрдпрддрди рдХрдВрдЯреЗрдирд░:$ docker-compose up -d --build
рдирдпрд╛ рдХрд╛рд░реНрдп рдЪрд▓рд╛рдПрдБ:$ curl -F type=1 http://localhost:1337/tasks/
рдлрд┐рд░ task_id
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реЗ рдирд┐рдХрд╛рд▓реЗрдВ рдФрд░ get_status
рд╕реНрдерд┐рддрд┐ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрджреНрдпрддрди рдХреЙрд▓ рдХрд░реЗрдВ :$ curl http://localhost:1337/tasks/25278457-0957-4b0b-b1da-2600525f812f/
{
"task_id": "25278457-0957-4b0b-b1da-2600525f812f",
"task_status": "SUCCESS",
"task_result": true
}
рдЖрдк рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдПрдХ рд╣реА рдЬрд╛рдирдХрд╛рд░реА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:
рдЕрдЬрд╡рд╛рдЗрди рд▓реЙрдЧ
рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╕реЗрд╡рд╛ celery
рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ docker-compose.yml
рдХрд┐ рд╕реЗрд▓реЗрд░реА рдПрдХ рдЕрд▓рдЧ рдлрд╛рдЗрд▓ рдореЗрдВ рдмрдВрдж рд╣реЛ рдЬрд╛рдП:celery:
build: ./project
command: celery worker --app=core --loglevel=info --logfile=logs/celery.log
volumes:
- ./project:/usr/src/app
environment:
- DEBUG=1
- SECRET_KEY=dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m
- DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
- CELERY_BROKER=redis://redis:6379/0
- CELERY_BACKEND=redis://redis:6379/0
depends_on:
- web
- redis
"рдкреНрд░реЛрдЬреЗрдХреНрдЯ" рдХреЗ
рд▓рд┐рдП рдПрдХ рдирдИ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдЗрд╕реЗ "рд▓реЙрдЧ" рдирд╛рдо рджреЗрдВ ред рдлрд┐рд░ рдЗрд╕ рдирдИ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝реЗрдВ celery.log
редрдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ:$ docker-compose up -d --build
рдЖрдкрдХреЛ рдпрд╣ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рд╡реЙрд▓реНрдпреВрдо рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд▓реЙрдЧ рдлрд╛рдЗрд▓ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдХреИрд╕реЗ рдкреЙрдкреБрд▓реЗрдЯ рд╣реЛрддреА рд╣реИ :[2020-03-25 19:42:29,586: INFO/MainProcess] Connected to redis://redis:6379/0
[2020-03-25 19:42:29,599: INFO/MainProcess] mingle: searching for neighbors
[2020-03-25 19:42:30,635: INFO/MainProcess] mingle: all alone
[2020-03-25 19:42:30,664: WARNING/MainProcess]
/usr/local/lib/python3.8/site-packages/celery/fixups/django.py:202:
UserWarning: Using settings.DEBUG leads to a memory
leak, never use this setting in production environments!
warnings.warn('''Using settings.DEBUG leads to a memory
[2020-03-25 19:42:30,667: INFO/MainProcess] celery@6d060151bfeb ready.
[2020-03-25 19:43:07,103: INFO/MainProcess]
Received task: tasks.sample_tasks.create_task[632792bb-5030-4f03-a0d8-e91979279729]
[2020-03-25 19:43:17,099: INFO/ForkPoolWorker-2]
Task tasks.sample_tasks.create_task[632792bb-5030-4f03-a0d8-e91979279729]
succeeded in 10.027462100006233s: True
рдлреНрд▓рд╛рд╡рд░ рдбреИрд╢рдмреЛрд░реНрдб
рдлреВрд▓ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ рдЕрдЬрд╡рд╛рдЗрди рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╣рд▓реНрдХреЗ рд╡реЗрдм-рдЖрдзрд╛рд░рд┐рдд рдЙрдкрдХрд░рдг рд╣реИред рдЖрдк рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд░рдирд┐рдВрдЧ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╢реНрд░рдорд┐рдХреЛрдВ рдХреЗ рдкреВрд▓ рдХреЛ рдмрдврд╝рд╛ рдпрд╛ рдШрдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдкреНрд░рджрд░реНрд╢рди рдЧреНрд░рд╛рдл рдФрд░ рдЖрдБрдХрдбрд╝реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВредрдЗрд╕реЗ рдЗрд╕рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ requirements.txt
:celery==4.4.1
Django==3.0.4
flower==0.9.3
redis==3.4.1
pytest==5.4.1
pytest-django==3.8.0
рдлрд┐рд░ рдЗрд╕рдореЗрдВ рдирдИ рд╕реЗрд╡рд╛ рдЬреЛрдбрд╝реЗрдВ docker-compose.yml
:dashboard:
build: ./project
command: flower -A core --port=5555 --broker=redis://redis:6379/0
ports:
- 5555:5555
environment:
- DEBUG=1
- SECRET_KEY=dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m
- DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
- CELERY_BROKER=redis://redis:6379/0
- CELERY_BACKEND=redis://redis:6379/0
depends_on:
- web
- redis
- celery
рдФрд░ рдкрд░реАрдХреНрд╖рдг:$ docker-compose up -d --build
рдбреИрд╢рдмреЛрд░реНрдб рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ : 5555 рдкрд░ рдЬрд╛рдПрдВ ред рдЖрдкрдХреЛ рдПрдХ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХреЛ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:
рдбреИрд╢рдмреЛрд░реНрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдФрд░ рдХрд╛рд░реНрдп рдЪрд▓рд╛рдПрдВ:
рдЕрдзрд┐рдХ рд╢реНрд░рдорд┐рдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдХреИрд╕реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ:$ docker-compose up -d --build --scale celery=3
рдЯреЗрд╕реНрдЯ
рдЪрд▓реЛ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдкрд░реАрдХреНрд╖рдг рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ:def test_task():
assert sample_tasks.create_task.run(1)
assert sample_tasks.create_task.run(2)
assert sample_tasks.create_task.run(3)
рдКрдкрд░ рджрд┐рдП рдЧрдП рдкрд░реАрдХреНрд╖рдг рдорд╛рдорд▓реЗ рдХреЛ project/tests/test_tasks.py
рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдирд┐рдореНрди рдЖрдпрд╛рдд рдЬреЛрдбрд╝реЗрдВ:from tasks import sample_tasks
рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдПрдВ:$ docker-compose exec web python -m pytest -k "test_task and not test_home"
рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рд▓рдЧрднрдЧ рдПрдХ рдорд┐рдирдЯ рд▓рдЧреЗрдЧрд╛:======================================== test session starts ========================================
platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
django: settings: core.settings (from ini)
rootdir: /usr/src/app, inifile: pytest.ini
plugins: django-3.8.0, celery-4.4.1
collected 2 items / 1 deselected / 1 selected
tests/test_tasks.py . [100%]
============================ 1 passed, 1 deselected in 62.43s (0:01:02) =============================
рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдКрдкрд░ рдХреЗ рдореБрдЦрд░ рдореЗрдВ рд╣рдордиреЗ рд╕реЗрд▓реЗрд░реА рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛, рд╕реАрдзреЗ рд▓реЙрдиреНрдЪ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ .run
рдмрдЬрд╛рдп рд╡рд┐рдзрд┐ .delay
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рдЪреАрдЬреЛрдВ рдХреЛ рдЧрддрд┐рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдирдХрд▓реА рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ?@patch('tasks.sample_tasks.create_task.run')
def test_mock_task(mock_run):
assert sample_tasks.create_task.run(1)
sample_tasks.create_task.run.assert_called_once_with(1)
assert sample_tasks.create_task.run(2)
assert sample_tasks.create_task.run.call_count == 2
assert sample_tasks.create_task.run(3)
assert sample_tasks.create_task.run.call_count == 3
рдЖрдпрд╛рдд:from unittest.mock import patch, call
рдкрд░реАрдХреНрд╖рд╛:$ docker-compose exec web python -m pytest -k "test_mock_task"
======================================== test session starts ========================================
platform linux -- Python 3.8.2, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
django: settings: core.settings (from ini)
rootdir: /usr/src/app, inifile: pytest.ini
plugins: django-3.8.0, celery-4.4.1
collected 3 items / 2 deselected / 1 selected
tests/test_tasks.py . [100%]
================================== 1 passed, 2 deselected in 1.13s ==================================
рджреЗрдЦ? рдЕрдм рдФрд░ рддреЗрдЬ!рдкреВрд░реНрдг рдПрдХреАрдХрд░рдг рдкрд░реАрдХреНрд╖рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛?def test_task_status(client):
response = client.post(reverse("run_task"), {"type": 0})
content = json.loads(response.content)
task_id = content["task_id"]
assert response.status_code == 202
assert task_id
response = client.get(reverse("get_status", args=[task_id]))
content = json.loads(response.content)
assert content == {"task_id": task_id, "task_status": "PENDING", "task_result": None}
assert response.status_code == 200
while content["task_status"] == "PENDING":
response = client.get(reverse("get_status", args=[task_id]))
content = json.loads(response.content)
assert content == {"task_id": task_id, "task_status": "SUCCESS", "task_result": True}
рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдЙрд╕реА рдмреНрд░реЛрдХрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдмреИрдХрдПрдВрдб рдХрд░рддрд╛ рд╣реИред рдЖрдк рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЕрдЬрд╡рд╛рдЗрди рдХрд╛ рдПрдХ рдирдпрд╛ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ:app = celery.Celery('tests', broker=CELERY_TEST_BROKER, backend=CELERY_TEST_BACKEND)
рдЖрдпрд╛рдд рдЬреЛрдбрд╝реЗрдВ:import json
рдФрд░ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╕рдлрд▓ рд╣реИрдВредрдирд┐рд╖реНрдХрд░реНрд╖
рдЖрдЬ рд╣рдордиреЗ Django рдкрд░ рдПрдХ рдЖрд╡реЗрджрди рдореЗрдВ рджреАрд░реНрдШрдХрд╛рд▓рд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реЗрд▓реЗрд░реА рдХреЗ рдореВрд▓ рд╡рд┐рдиреНрдпрд╛рд╕ рдХреА рд╢реБрд░реБрдЖрдд рдХреАред рдЖрдкрдХреЛ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХрддрд╛рд░ рдореЗрдВ рдХреЛрдИ рднреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рднреЗрдЬрдиреА рдЪрд╛рд╣рд┐рдП рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рдУрд░ рд╕реЗ рдХреЛрдб рдХреЛ рдзреАрдорд╛ рдХрд░ рд╕рдХрддреА рд╣реИредрдЕрдЬрд╡рд╛рдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рджреЛрд╣рд░рд╛рд╡ рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдЬрдЯрд┐рд▓ рд╕рдВрд╕рд╛рдзрди-рдЧрд╣рди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╡рд┐рдШрдЯрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдХрдИ рдорд╢реАрдиреЛрдВ рдкрд░ рдХрдореНрдкреНрдпреВрдЯреЗрд╢рдирд▓ рднрд╛рд░ рд╡рд┐рддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ рдФрд░ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд╕рдордп рдФрд░ рдорд╢реАрди рдкрд░ рд▓реЛрдб рдХреЛ рдХрдо рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИредрдЖрдк рдЗрд╕ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╕рднреА рдХреЛрдб рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ ред
тЖТ рдХреЛрд░реНрд╕ рдкрд░ рдЬрд╛рдУ