Entendendo a relação entre o Django e arquivos estáticos

Quem está começando com Django eventualmente tropeça em questões envolvendo arquivos estáticos.

Tudo fica mais simples quando você compreende as diferentes relações que o Django estabelece com os assets do seu projeto.

Por padrão, quando você cria um projeto, a app django.contrib.staticfiles já está no INSTALLED_APPS do seu settings.py. É nela que estão implementados os códigos que ajustam o comportamento do framework de acordo com o contexto:

Em desenvolvimento

Quando você inicia o servidor de desenvolvimento do Django com o comando python manage.py runserver e no seu settings.py você tem DEBUG=True, o framework assume que você está em modo de desenvolvimento e serve os assets de cada app, diretamente pelo Django.

Isso é lento, mas em tempo de desenvolvimento não é problema e acaba agilizando muito, pois você não precisa executar o collectstatic à cada asset novo que adiciona ao projeto.

Vale ressaltar que esse comportamento é atrelado ao comando runserver. Se você usar o gunicorn no desenvolvimento, este recurso não estará disponível e você precisará adicionar as linhas abaixo no seu ROOT_URLCONF.

Em produção

Quando no seu settings.py, o DEBUG=False, ele assume que você está em modo produção e não serve nenhum arquivo estático. Nem das apps e nem do STATIC_ROOT que é o destino do comando collectstatic.

Por padrão, o Django espera que você use um servidor web ou uma CDN para servir seus assets, o que é mais seguro e tem melhor performance.

Collectstatic no meio de campo

Para permitir uma fácil transição do modo de desenvolvimento para o modo de produção, usamos o comando collectstatic.

Esse comando encontra os assets do seu projeto e os copia para o STATIC_ROOT definido no seu settings.py.

Depois de copiar todos os arquivos ele ativa um mecanismo de pós-processamento customizável, que pode desde minificar os seus arquivos até enviá-los para a AmazonS3, por exemplo.

Mas existe um “meio termo”?

Como fazer para o Django servir os arquivos copiados para o STATIC_ROOT mesmo em modo produção, ou seja, com DEBUG=False?

Apesar de não ser ideal, essa é uma necessidade relativamente comum, principalmente para quem está prototipando aplicações utilizando o Heroku.

A solução tradicional é adicionar ao ROOT_URLCONF uma rota para uma view builtin do Django:

A solução mais recomendada, é utilizar a app dj-static que faz a mesma coisa de forma mais segura.

Expliquei ou compliquei? Espero que agora você encare os arquivos estáticos com mais tranquilidade. 😉

[]’s, HB!

  • Silas Vasconcelos

    Sou de bola, parabéns!

  • Bem Explicado, estava com essa duvida jah tinha um tempo, obrigado.

  • HB

    Testando disqus

  • Andreas

    Não estou conseguindo acessar os arquivos de media. Alguem pode me ajudar?

    meu settings.py:

    SETTINGS_DIR = os.path.realpath(os.path.dirname(__file__))

    MEDIA_ROOT = os.path.join(SETTINGS_DIR, ‘media’)

    MEDIA_URL = ‘/media/’

  • Roberto Almeida

    Problema resolvido, faltava fazer esta configuração:
    STATICFILES_DIRS = (
    os.path.join(BASE_DIR, ‘static’),
    )

  • Roberto Almeida

    Problema resolvido, faltava fazer esta configuração:
    STATICFILES_DIRS = (
    os.path.join(BASE_DIR, ‘static’),
    )

  • Roberto Almeida

    No meu caso nem com o dj-static conseguí exibir as imagens, acredito que o problema esteja na localização da pasta dentro do project ou algo parecido.

    As imagens estão fisicamente na pasta “D:webserverwwwgerenciadorgerenciadorstaticimg”

    Meu arquivo settings.py está assim:
    STATIC_ROOT = ‘staticfiles’
    STATIC_URL = ‘/static/’

    Na minha template instancio as imagens assim:
    {% load staticfiles %}

    • O STATIC_ROOT tem que ser o caminho absoluto.

      Se vc adicionou lá no STATICFILES_DIRS, e funcionou, isso aconteceu pq o DEBUG está True.

      Em produção vc vai usar o collectstatic e o DEBUG=False. Com isso vai dar problema devido o valor do seu STATIC_ROOT.

      Faça algo como:

      STATIC_ROOT = os.path.join(BASE_DIR, ‘static’)

      Mas isso vai fazer o local do seus assets colidir com o destino do collectstatic. Então eu sugiro que guarde os assets em um diretório “assets”, fazendo:

      STATICFILES_DIRS = (os.path.join(BASE_DIR, ‘assets’),)

  • Fabiano Góes

    show de bola Henrique, ficou muito bem explicado e eu que já vinha usando as convenções de static dentro das apps pude compreender o que ocorre e como o django trabalho por traz das câmeras, ficou tudo mais claro. valeu!!!

  • Fabiano Góes

    show de bola Henrique, ficou muito bem explicado e eu que já vinha usando as convenções de static dentro das apps pude compreender o que ocorre e como o django trabalho por traz das câmeras, ficou tudo mais claro. valeu!!!

  • Pingback: Entendendo a relação entre o Django e arquivos estáticos | Estude[py]()

  • jonatascd

    boa, HB

    até porque recentemente tenho visto mais e mais perguntas sobre como lidar com statics – no caso mais voltado ao Django 1.5+

  • jonatascd

    boa, HB

    até porque recentemente tenho visto mais e mais perguntas sobre como lidar com statics – no caso mais voltado ao Django 1.5+

  • Gustavo Carvalho

    Cara, post muito bom, parabéns.
    Tem muita gente que sofre quando está aprendendo Django e precisa lidar com arquivos estáticos, eu mesmo, sofri um bocado até entender como django trata esse tipo de arquivos.

    • Valeu @jonatascd:disqus e @disqus_LMvc5nfcLC:disqus! A inspiração veio de uma dúvida do Gilmar Soares nessa última turma do #welcometothedjango.

  • Gustavo Carvalho

    Cara, post muito bom, parabéns.
    Tem muita gente que sofre quando está aprendendo Django e precisa lidar com arquivos estáticos, eu mesmo, sofri um bocado até entender como django trata esse tipo de arquivos.

    • Valeu @jonatascd:disqus e @disqus_LMvc5nfcLC:disqus! A inspiração veio de uma dúvida do Gilmar Soares nessa última turma do #welcometothedjango.

      • Roberto Almeida

        No meu caso nem com o dj-static conseguí exibir as imagens, acredito que o problema esteja na localização da pasta dentro do project ou algo parecido.

        As imagens estão fisicamente na pasta “D:webserverwwwgerenciadorgerenciadorstaticimg”

        Meu arquivo settings.py está assim:
        STATIC_ROOT = ‘staticfiles’
        STATIC_URL = ‘/static/’

        Na minha template instancio as imagens assim:
        {% load staticfiles %}

      • O STATIC_ROOT tem que ser o caminho absoluto.

        Se vc adicionou lá no STATICFILES_DIRS, e funcionou, isso aconteceu pq o DEBUG está True.

        Em produção vc vai usar o collectstatic e o DEBUG=False. Com isso vai dar problema devido o valor do seu STATIC_ROOT.

        Faça algo como:

        STATIC_ROOT = os.path.join(BASE_DIR, ‘static’)

        Mas isso vai fazer o local do seus assets colidir com o destino do collectstatic. Então eu sugiro que guarde os assets em um diretório “assets”, fazendo:

        STATICFILES_DIRS = (os.path.join(BASE_DIR, ‘assets’),)