Mengapa DEBUG = Pengaturan palsu membuat Akses File Statis Django saya gagal?

356

Saya membangun aplikasi menggunakan Django sebagai pekerja keras saya. Semua telah diatur dengan baik sejauh pengaturan db, dikonfigurasi direktori statis, url, pandangan dll. Tapi masalah mulai menyelinap pada saat saya ingin membuat halaman 404.html dan 500.html indah dan kustom saya sendiri.

Saya membaca dokumen tentang penanganan kesalahan khusus, dan mengatur konfigurasi yang diperlukan di UrlsConf, membuat tampilan yang sesuai dan menambahkan 404.html dan 500.html ke direktori templat aplikasi saya (ditentukan dalam pengaturan.py juga).

Tetapi dokumen mengatakan you can actually view custom error views until Debug is Off, jadi saya mematikannya untuk menguji barang-barang saya, dan saat itulah hal mengamuk!

Saya tidak hanya gagal melihat custom 404.html (sebenarnya, ia memuat, tetapi karena masing-masing halaman kesalahan saya berisi pesan kesalahan grafis -sebagai gambar yang bagus), sumber halaman kesalahan dimuat, tetapi tidak ada yang lain dimuat! Bahkan tidak menautkan CSS atau Javascript!

Secara umum, setelah saya atur DEBUG = False, semua tampilan akan dimuat, tetapi konten yang tertaut (CSS, Javascript, Gambar, dll) tidak akan dimuat! Apa yang terjadi? Apakah ada sesuatu yang hilang, mengenai file statis dan DEBUGpengaturannya?

nemesisfixx
sumber
Bagaimana dengan hosting Anda? Mesin lokal dengan server uji?
j_syk
mesin lokal dengan server uji. Saya pada dasarnya ingin melihat bagaimana penanganan kesalahan khusus saya akan bekerja dengan mensimulasikan skenario secara lokal seperti mengakses halaman yang tidak ada dan menyebabkan kesalahan run-time - tetapi konten statis saya tidak dapat dimuat.
nemesisfixx
Entah itu bisa dilakukan di tingkat server seperti di sini atau bisa ditangani di tingkat Django dengan menambahkan urlpattern. Saya menemukan pertanyaan di bawah ini untuk masalah yang sama. stackoverflow.com/questions/6405173/…
Pankaj Anand

Jawaban:

353

Dengan debug dimatikan, Django tidak akan lagi menangani file statis - server web produksi Anda (Apache atau yang lain) harus mengatasi hal itu.

Marek Sapota
sumber
3
Ini sebenarnya menenangkan keingintahuan saya, jadi sekarang ini masuk akal, dan saya memang bisa mengatasinya dengan Apache jika perlu. Saya pikir itu masalah dengan pengaturan saya sendiri. Terima kasih
nemesisfixx
5
Saya menemukan jawaban ini sangat membantu. Untuk berjaga-jaga jika ada orang lain dalam situasi yang sama dengan saya (menggunakan Google App Engine untuk aplikasi dengan Django nonrel): jangan lupa untuk memperbarui app.yaml.
Lyndsey Ferguson
3
penangan: - url: / static static_dir: static
Lyndsey Ferguson
475

Jika Anda masih perlu server statis secara lokal (misalnya untuk pengujian tanpa debug) Anda dapat menjalankan devserver dalam mode tidak aman:

manage.py runserver --insecure
Dmitry Shevchenko
sumber
6
Meskipun flag ini berfungsi, ia tidak menayangkan konten dari folder
collectstatic
5
Itu ajaib. Terima kasih tuan, Anda seorang pahlawan. Jawaban ini harus digabung dengan jawaban yang diterima karena memecahkan masalah tanpa harus melayani statis menggunakan cara lain daripada Django itu sendiri.
Depado
1
Ini yang saya butuhkan. Meskipun praktik terbaik adalah menggunakan variabel lingkungan untuk membedakan antara pengembangan dan lingkungan produksi dan beralih Debug.
Neeraj Gupta
1
Harap dicatat: itu TIDAK akan bekerja dengan ManifestStaticFilesStorage sebagai code.djangoproject.com/ticket/19295
Andrea Rabbaglietti
9
dapatkah seseorang memberi tahu saya apa yang tidak aman tentang ini
Kavi Vaidya
36

Anda dapat menggunakan WhiteNoise untuk menyajikan file statis dalam produksi.

Install:

pip install WhiteNoise

Dan ubah file wsgi.py Anda menjadi ini:

from django.core.wsgi import get_wsgi_application
from whitenoise.django import DjangoWhiteNoise

application = get_wsgi_application()
application = DjangoWhiteNoise(application)

Dan Anda baik untuk pergi!

Kredit ke Blog Kreatif Stang .

TETAPI benar-benar tidak disarankan menyajikan file statis dengan cara ini dalam produksi. Server web produksi Anda (seperti nginx) harus mengatasinya.

Johnny Zhao
sumber
1
Kedengarannya menarik, tetapi tidak berhasil bagi saya dengan hanya menambahkan baris itu ke wgsi.pyfile. Dokumentasi yang Anda tautkan tampaknya memberikan instruksi lain untuk menggunakan WhiteNoise. Akan mencoba cara lain dan memperbarui Anda di sini.
DarkCygnus
+1 karena inilah yang akhirnya membawa saya ke solusi. Saya menambahkan jawaban di mana saya memasukkan langkah-langkah tambahan yang saya ambil untuk benar-benar membuatnya bekerja.
DarkCygnus
manage.py runserver --insecuretidak bekerja untuk saya. Yang ini, sih.
Jee
3
Perhatikan bahwa dengan WhiteNoise rilis 4.0, konfigurasi berubah. Jangan tambahkan baris ini ke wsgi.py. Sebagai gantinya, tambahkan saja 'whitenoise.middleware.WhiteNoiseMiddleware'ke middleware. Lihat catatan rilis dari changelog
Doug Harris
Mengapa * tidak disarankan? Saya telah menggunakannya selama bertahun-tahun di beberapa situs, sangat bagus. Bahkan Heroku menggunakannya dalam template Django mereka.
Omar Gonzalez
33

Di urls.py saya menambahkan baris ini:

from django.views.static import serve 

tambahkan kedua url tersebut di urlpatterns:

url(r'^media/(?P<path>.*)$', serve,{'document_root': settings.MEDIA_ROOT}), 
url(r'^static/(?P<path>.*)$', serve,{'document_root': settings.STATIC_ROOT}), 

dan kedua file statis dan media dapat diakses ketika DEBUG = SALAH.
Semoga bermanfaat :)

stathoula
sumber
Ketika selesai admin panel css tidak memuat ??
Thusitha Deepal
Iya. Satu-satunya yang berfungsi !! Terima kasih.
DrGeneral
LUAR BIASA! Jangan lupa untuk mengatur STATIC_ROOT dan manage.py collectstatic.
DomingoR
2
Sekarang ganti url(denganre_path(
Leopd
19

Jika Anda menggunakan tampilan servis statis dalam pengembangan, Anda harus memiliki DEBUG = True:

Peringatan

Ini hanya akan berfungsi jika DEBUG Benar.

Itu karena pandangan ini sangat tidak efisien dan mungkin tidak aman. Ini hanya dimaksudkan untuk pengembangan lokal, dan tidak boleh digunakan dalam produksi.

Documents: menyajikan file statis dalam pengembangan

EDIT: Anda bisa menambahkan beberapa url hanya untuk menguji 404 dan 500 templat Anda, cukup gunakan generik view direct_to_template di url Anda.

from django.views.generic.simple import direct_to_template

urlpatterns = patterns('',
    ('^404testing/$', direct_to_template, {'template': '404.html'})
)
j_syk
sumber
1
Bagaimana caranya, kemudian melayani file statis pada produksi? NVM, saya baru saja melihatnya. Terima kasih.
Anda akan mengatur server web Anda untuk meng-host direktori tertentu. Paling umum Anda menggunakan Apache atau Nginx. Documents sedikit membahasnya.
j_syk
terima kasih @j_syk, saya sudah mencoba pendekatan ini untuk melihat 404.html dan 500.html melalui beberapa mekanisme non-error lain yang mirip dengan apa yang Anda sarankan. Tetapi saya ingin tahu apakah benar-benar mustahil untuk membuat halaman saya di-render dengan benar seperti yang mereka lakukan dalam produksi, sementara masih hanya berjalan di server pengujian saya - delegasi penanganan file statis ke Apache ketika Debug Tidak Aktif mengaturnya untuk saya. Terima kasih telah berkontribusi.
nemesisfixx
@ mcnemesis Saya tidak yakin persis apa yang akan terjadi - tetapi coba atur TEMPLATE_DEBUG = Salah, dan DEBUG = Benar. Jika Anda mematikan kesalahan-kesalahan cantik, saya tidak yakin apakah ia beralih ke templat
404/500
seperti yang diharapkan, melakukan ini tidak membuahkan hasil yang positif. Tapi terima kasih.
nemesisfixx
17

Jawaban Johnny bagus, tetapi tetap tidak berhasil bagi saya hanya dengan menambahkan baris-baris yang dijelaskan di sana. Berdasarkan jawaban itu, langkah-langkah yang benar-benar bekerja untuk saya di mana:

  1. Instal WhiteNoise seperti yang dijelaskan:

    pip install WhiteNoise
  2. Buat STATIC_ROOTvariabel dan tambahkan WhiteNoise ke MIDDLEWAREvariabel Anda di settings.py:

    #settings.py
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'whitenoise.middleware.WhiteNoiseMiddleware', #add whitenoise
        'django.contrib.sessions.middleware.SessionMiddleware',
        ...
    ]
    
    #...
    
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') ##specify static root
  3. Kemudian, modifikasi wsgi.pyfile Anda seperti dijelaskan dalam jawaban Johnny:

    #wsgi.py
    from django.core.wsgi import get_wsgi_application
    from whitenoise.django import DjangoWhiteNoise
    
    application = get_wsgi_application()
    application = DjangoWhiteNoise(application)
  4. Setelah itu, sebarkan perubahan Anda ke server Anda (dengan git atau apa pun yang Anda gunakan).

  5. Akhirnya, jalankan collectstaticopsi dari Anda manage.pydi server Anda. Ini akan menyalin semua file dari folder statis Anda ke STATIC_ROOTdirektori yang kami tentukan sebelumnya:

    $ python manage.py collectstatic

    Anda sekarang akan melihat folder baru bernama staticfilesyang mengandung elemen tersebut.

Setelah mengikuti langkah-langkah ini Anda sekarang dapat menjalankan server Anda dan akan dapat melihat file statis Anda saat dalam mode Produksi.

Pembaruan: Jika Anda memiliki versi <4 changelog menunjukkan bahwa tidak perlu lagi mendeklarasikan WSGI_APPLICATION = 'projectName.wsgi.application'pada settings.pyfile Anda .

DarkCygnus
sumber
Saya melakukannya dengan benar, dan pada perkembangannya berfungsi dengan baik, tetapi tidak dalam produksi. Masih memiliki masalah yang sama ketika DEBUG == Salah
Anna Huang
@ AnnaHuang Apa yang Anda maksud dengan pengembangan dan produksi? Apakah Anda memiliki lingkungan atau mesin yang terpisah? Apakah mereka dikonfigurasi dengan cara yang sama?
DarkCygnus
13

Anda sebenarnya dapat menyajikan file statis dalam aplikasi Django produksi, dengan aman dan tanpa DEBUG=True.

Daripada menggunakan Django sendiri, gunakan dj_static di file WSGI Anda ( github ):

# requirements.txt:

...
dj-static==0.0.6


# YOURAPP/settings.py:

...
STATIC_ROOT = 'staticdir'
STATIC_URL = '/staticpath/'

# YOURAPP/wsgi.py:

...
from django.core.wsgi import get_wsgi_application
from dj_static import Cling

application = Cling(get_wsgi_application())
Robin Winslow
sumber
2
Sejak itu saya menemukan whitenoise , yang mungkin lebih lengkap.
Robin Winslow
7

Cukup buka urls.py proyek Anda, lalu temukan pernyataan if ini.

if settings.DEBUG:
    urlpatterns += patterns(
        'django.views.static',
        (r'^media/(?P<path>.*)','serve',{'document_root': settings.MEDIA_ROOT}), )

Anda dapat mengubah pengaturan. MENGUNDANG di True dan itu akan selalu berfungsi. Tetapi jika proyek Anda adalah sesuatu yang serius maka Anda harus memikirkan solusi lain yang disebutkan di atas.

if True:
    urlpatterns += patterns(
        'django.views.static',
        (r'^media/(?P<path>.*)','serve',{'document_root': settings.MEDIA_ROOT}), )

Dalam Django 1.10 Anda dapat menulis demikian:

urlpatterns += [ url(r'^media/(?P<path>.*)$', serve, { 'document_root': settings.MEDIA_ROOT, }), url(r'^static/(?P<path>.*)$', serve, { 'document_root': settings.STATIC_ROOT }), ]
Sergey Luchko
sumber
3
Kode Anda benar, tetapi dalam Django 1.10, konfigurasi untuk media dan statis adalah: urlpatterns + = [url (r '^ media / (? P <path>. *) $', Serve, {'document_root': settings .MEDIA_ROOT,}), url (r '^ static / (? P <path>. *) $', Sajikan, {'document_root': settings.STATIC_ROOT}),]
Roberth Solís
6

Anda dapat men-debug ini dengan berbagai cara. Inilah pendekatan saya.

localsettings.py:

DEBUG = False
DEBUG404 = True

urls.py:

from django.conf import settings
import os

if settings.DEBUG404:
    urlpatterns += patterns('',
        (r'^static/(?P<path>.*)$', 'django.views.static.serve',
         {'document_root': os.path.join(os.path.dirname(__file__), 'static')} ),
    )

Pastikan untuk membaca dokumen;)

https://docs.djangoproject.com/en/2.0/howto/static-files/#limiting-use-to-debug-true

Conrado
sumber
0

Dukungan untuk argumen tampilan string ke url () sudah usang dan akan dihapus di Django 1.10

Solusi saya hanyalah koreksi kecil untuk solusi Conrado di atas.

from django.conf import settings
import os
from django.views.static import serve as staticserve

if settings.DEBUG404:
    urlpatterns += patterns('',
        (r'^static/(?P<path>.*)$', staticserve,
            {'document_root': os.path.join(os.path.dirname(__file__), 'static')} ),
        )
be_good_do_good
sumber
0

Meskipun tidak teraman, tetapi Anda dapat mengubah kode sumbernya. navigasi kePython/2.7/site-packages/django/conf/urls/static.py

Kemudian edit seperti berikut:

if settings.DEBUG or (prefix and '://' in prefix):

Jadi jika settings.debug==Falseitu tidak akan berpengaruh pada kode, juga setelah menjalankan coba python manage.py runserver --runserverjalankan file statis.

CATATAN : Informasi hanya boleh digunakan untuk pengujian saja

Natuto
sumber
0

Saya melakukan perubahan berikut pada proyek / urls.py saya dan itu berhasil untuk saya

Tambahkan baris ini: dari django.conf.urls impor url

dan tambahkan: url (r '^ media / (? P. *) $', sajikan, {'document_root': settings.MEDIA_ROOT,}), dalam urlpatterns.

Namrata Sharma
sumber