如何在芹菜任务中从Django settings.py检索动态值?

如何在芹菜任务中从Django settings.py检索动态值?,django,celery,systemd,Django,Celery,Systemd,我的Django依靠芹菜和芹菜来繁殖任务。我有3个systemd服务/单元: myapp.service(gunicorn守护进程) 芹菜-myapp.service(芹菜工人) celerybeat-myapp.service(celerybeat守护进程) 我在我的主“myapp.service”服务(systemd unit)中定义了一个环境变量MY_SECRET 我无法从settings.py或直接从任务(tasks.py)中的环境变量获取此值,但我可以直接使用settings.py或环

我的Django依靠芹菜和芹菜来繁殖任务。我有3个systemd服务/单元:

  • myapp.service(gunicorn守护进程)
  • 芹菜-myapp.service(芹菜工人)
  • celerybeat-myapp.service(celerybeat守护进程)
  • 我在我的主“myapp.service”服务(systemd unit)中定义了一个环境变量MY_SECRET

    我无法从settings.py或直接从任务(tasks.py)中的环境变量获取此值,但我可以直接使用settings.py或环境变量从视图(views.py)中顺利检索此值

    我是否需要将myapp.service中定义的环境变量MY_SECRET复制到celery-myapp.service和celerybeat-myapp.service,以便从芹菜任务中获取此值?如何检索我的_秘密值I,我的芹菜任务

    myapp.service

    [Unit]
    Description=My App
    After=network.target
    Wants=celery-myapp.service
    Wants=celerybeat-myapp.service
    
    [Service]
    User=myapp
    Group=nginx
    Environment=MY_SECRET=1234
    WorkingDirectory=/opt/myproject/
    ExecStart=/opt/myproject/env/bin/gunicorn --workers 3 --log-level debug --bind unix://opt/myproject/myapp.sock myaproject.wsgi:application
    
    [Install]
    WantedBy=multi-user.target
    
    我的Django项目“settings.py”中引用了环境变量以及我打算在应用程序中使用的其他设置:

    设置.py

    # Populated with environment variable defined by systemd unit
    MY_SECRET = os.environ.get('MY_SECRET')
    # Static value
    MY_URL= 'http://127.0.0.1'
    
    def my_view(request):
        from django.conf import settings as project_settings
    
        my_secret_env = os.environ.get('MY_SECRET')
        my_secret_setting = project_settings.MY_SECRET
        my_url_setting = project_settings.MY_URL
    
       return render(request,'mypage.html',{
           'my_secret_env': my_secret_env,
           'my_secret_setting': my_secret_setting,
           'my_url_setting': my_url_setting,
       )
    
    @shared_task
    def task_mytask():
        from django.conf import settings as project_settings
    
        my_secret_env = os.environ.get('MY_SECRET')
        my_secret_setting = project_settings.MY_SECRET
        my_url_setting = project_settings.MY_URL
    
        # No value displayed
        print(my_secret_env)
        # No value displayed
        print(my_secret_setting)
        # Value displayed properly
        print(my_url_setting)
    
    @periodic_task(run_every=timedelta(seconds=60))
    def task_myperiodictask():
        task_mytask.delay()
    
    @shared_task()
    def task_mytask(my_secret_env, my_secret_setting):
        ...
    
    task_mytask.apply_async(args=[my_secret_env, my_secret_setting])
    
    从我的视图中,我可以从settings.py和直接从environment获取定义为环境变量my_SECRET的值:

    视图.py

    # Populated with environment variable defined by systemd unit
    MY_SECRET = os.environ.get('MY_SECRET')
    # Static value
    MY_URL= 'http://127.0.0.1'
    
    def my_view(request):
        from django.conf import settings as project_settings
    
        my_secret_env = os.environ.get('MY_SECRET')
        my_secret_setting = project_settings.MY_SECRET
        my_url_setting = project_settings.MY_URL
    
       return render(request,'mypage.html',{
           'my_secret_env': my_secret_env,
           'my_secret_setting': my_secret_setting,
           'my_url_setting': my_url_setting,
       )
    
    @shared_task
    def task_mytask():
        from django.conf import settings as project_settings
    
        my_secret_env = os.environ.get('MY_SECRET')
        my_secret_setting = project_settings.MY_SECRET
        my_url_setting = project_settings.MY_URL
    
        # No value displayed
        print(my_secret_env)
        # No value displayed
        print(my_secret_setting)
        # Value displayed properly
        print(my_url_setting)
    
    @periodic_task(run_every=timedelta(seconds=60))
    def task_myperiodictask():
        task_mytask.delay()
    
    @shared_task()
    def task_mytask(my_secret_env, my_secret_setting):
        ...
    
    task_mytask.apply_async(args=[my_secret_env, my_secret_setting])
    
    mypage.html

        {% block page_content %}
        <!-- Value displayed properly -->
        <p><strong>my_secret_env:</strong> {{ my_secret_env }}</p>
        <!-- Value displayed properly -->
        <p><strong>my_secret_setting:</strong> {{ my_secret_setting }}</p>
        <!-- Value displayed properly -->
        <p><strong>my_url_setting:</strong> {{ my_url_setting }}</p>
        {% endblock %}
    

    不确定你的目标是什么,但你永远不应该随意地传递你的秘密。但是,如果您愿意,您可能必须从调用任务的位置将它们作为参数传递。像这样:

    task.py

    # Populated with environment variable defined by systemd unit
    MY_SECRET = os.environ.get('MY_SECRET')
    # Static value
    MY_URL= 'http://127.0.0.1'
    
    def my_view(request):
        from django.conf import settings as project_settings
    
        my_secret_env = os.environ.get('MY_SECRET')
        my_secret_setting = project_settings.MY_SECRET
        my_url_setting = project_settings.MY_URL
    
       return render(request,'mypage.html',{
           'my_secret_env': my_secret_env,
           'my_secret_setting': my_secret_setting,
           'my_url_setting': my_url_setting,
       )
    
    @shared_task
    def task_mytask():
        from django.conf import settings as project_settings
    
        my_secret_env = os.environ.get('MY_SECRET')
        my_secret_setting = project_settings.MY_SECRET
        my_url_setting = project_settings.MY_URL
    
        # No value displayed
        print(my_secret_env)
        # No value displayed
        print(my_secret_setting)
        # Value displayed properly
        print(my_url_setting)
    
    @periodic_task(run_every=timedelta(seconds=60))
    def task_myperiodictask():
        task_mytask.delay()
    
    @shared_task()
    def task_mytask(my_secret_env, my_secret_setting):
        ...
    
    task_mytask.apply_async(args=[my_secret_env, my_secret_setting])
    
    视图.py

    # Populated with environment variable defined by systemd unit
    MY_SECRET = os.environ.get('MY_SECRET')
    # Static value
    MY_URL= 'http://127.0.0.1'
    
    def my_view(request):
        from django.conf import settings as project_settings
    
        my_secret_env = os.environ.get('MY_SECRET')
        my_secret_setting = project_settings.MY_SECRET
        my_url_setting = project_settings.MY_URL
    
       return render(request,'mypage.html',{
           'my_secret_env': my_secret_env,
           'my_secret_setting': my_secret_setting,
           'my_url_setting': my_url_setting,
       )
    
    @shared_task
    def task_mytask():
        from django.conf import settings as project_settings
    
        my_secret_env = os.environ.get('MY_SECRET')
        my_secret_setting = project_settings.MY_SECRET
        my_url_setting = project_settings.MY_URL
    
        # No value displayed
        print(my_secret_env)
        # No value displayed
        print(my_secret_setting)
        # Value displayed properly
        print(my_url_setting)
    
    @periodic_task(run_every=timedelta(seconds=60))
    def task_myperiodictask():
        task_mytask.delay()
    
    @shared_task()
    def task_mytask(my_secret_env, my_secret_setting):
        ...
    
    task_mytask.apply_async(args=[my_secret_env, my_secret_setting])
    
    另外,您可以尝试设置一个环境变量并尝试调用它

    export MY_SETTING = 1234
    

    我需要直接从环境变量中检索secret,或者使用settings.py作为中介(将配置值集中在一个位置)。我的共享任务不是从视图调用的,而是由基于数据库设置的定期任务触发的。哦,对了,我现在明白了。您是否尝试导出希望传递的环境变量?导出MY_SECRET=1234最后,我在celery.service和celerybeat.service中复制了Environment=MY_SECRET=1234,现在我可以在celery定期任务或celery共享任务中直接使用os.Environment.get('MY_SECRET')获取此环境变量的值,但这有点难看。