Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

888
Views
¿Por qué Django no sirve correctamente mis archivos estáticos de SPA?

Estoy construyendo un sitio web usando un backend de Django y un frontend de Vuejs . En el desarrollo comencé el backend y el frontend por separado con python manage.py runserver e yarn serve respectivamente. Esto funcionó muy bien y ahora quiero implementar el sitio web. Para hacer esto, ejecuté yarn build , que creó una carpeta dist/ en mi carpeta frontend. Así que mi estructura era así:

 cockpit ├── backend/ │ ├── cockpit/ │ │ ├── views.py │ │ ├── css/ │ │ └── etc.. │ ├── settings/ │ │ └── settings.py │ └── manage.py └── frontend/ └── dist/ ├── index.html ├── css/ └── js/

Ahora quiero servir las fuentes en frontend/dist/ desde mi proyecto django para poder ejecutar todo usando uwsgi. Para hacer esto, estoy tratando de seguir esta descripción . Tengo la siguiente settings/urls.py

 from django.contrib import admin from django.urls import include, path, re_path from django.views.generic import TemplateView urlpatterns = [ path('admin/', admin.site.urls), path('cockpit/', include("cockpit.urls")), re_path('', TemplateView.as_view(template_name='index.html')), ]

y establezca la siguiente configuración en my settings.py:

 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': ['static'], # <== ADDED THIS 'APP_DIRS': True, 'OPTIONS': { # removed to keep this example small }, }, ] BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, '../frontend/dist'), ] STATIC_ROOT = os.path.join(BASE_DIR, "static/") print("BASE_DIR:", BASE_DIR) print("STATIC_ROOT:", STATIC_ROOT) print("STATICFILES_DIRS:", STATICFILES_DIRS)

Y las huellas me muestran esto:

 BASE_DIR: /home/kramer65/repos/cockpit/backend STATIC_ROOT: /home/kramer65/repos/cockpit/backend/static/ STATICFILES_DIRS: ['/home/kramer65/repos/cockpit/backend/../frontend/dist']

Luego ejecuté `python manage.py collectstatic:

 $ python manage.py collectstatic 150 static files copied to '/home/kramer65/repos/cockpit/backend/static'.

Así que ahora se ve así:

 cockpit ├── backend/ │ ├── cockpit/ │ │ ├── views.py │ │ ├── css/ │ │ └── etc.. │ ├── settings/ │ │ └── settings.py │ └── manage.py │ └── static/ │ ├── index.html │ ├── css/ │ └── js/ └── frontend/ └── dist/ ├── index.html ├── css/ └── js/

Lo probé ejecutando el http-server (nodo) desde la carpeta backend/static/ . En el navegador la web carga y funciona perfecto. A continuación se muestra la salida de la línea de comando:

 $ http-server Starting up http-server, serving ./ Available on: http://127.0.0.1:8080 http://192.168.0.104:8080 Hit CTRL-C to stop the server [2020-05-18T13:50:58.487Z] "GET /" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0" (node:5928) [DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated [2020-05-18T13:50:58.671Z] "GET /css/chunk-vendors.2c7f3eba.css" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0" [2020-05-18T13:50:58.679Z] "GET /css/app.e15f06d0.css" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0" [2020-05-18T13:50:58.681Z] "GET /js/chunk-vendors.9c409057.js" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0" [2020-05-18T13:50:58.687Z] "GET /js/app.c930fce5.js" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0"

Detuve este http-server , inicié el servidor de desarrollo Django y abrí el navegador. La terminal me muestra esto:

 $ python manage.py runserver Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). May 18, 2020 - 17:57:00 Django version 3.0.6, using settings 'settings.settings' Starting ASGI/Channels version 2.4.0 development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. HTTP GET / 200 [0.22, 127.0.0.1:33224] HTTP GET /static/debug_toolbar/css/print.css 200 [0.04, 127.0.0.1:33232] HTTP GET /static/debug_toolbar/css/toolbar.css 200 [0.05, 127.0.0.1:33234] HTTP GET /static/debug_toolbar/js/toolbar.js 200 [0.02, 127.0.0.1:33232] HTTP GET /static/debug_toolbar/js/toolbar.timer.js 200 [0.04, 127.0.0.1:33234] HTTP GET /js/chunk-vendors.9c409057.js 200 [0.80, 127.0.0.1:33228] HTTP GET /css/chunk-vendors.2c7f3eba.css 200 [0.94, 127.0.0.1:33224] HTTP GET /js/app.c930fce5.js 200 [0.98, 127.0.0.1:33230] HTTP GET /css/app.e15f06d0.css 200 [0.99, 127.0.0.1:33226] HTTP GET /favicon.ico 200 [0.09, 127.0.0.1:33226]

En la consola del navegador veo que las fuentes parecen estar cargadas, pero algunas parecen estar vacías (0 bytes) y la pantalla no muestra nada. A continuación se muestra una captura de pantalla de los resultados y una captura de pantalla de la pestaña Archivos estáticos en la barra de depuración de Django.

¿Alguien sabe por qué no sirve esos archivos correctamente en Django?

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

[EDITAR]

Acabo de encontrar que si cambio

 STATIC_URL = '/static/'

para

 STATIC_URL = '/'

funciona correctamente cuando voy a http://127.0.0.1:8000/index.html , pero ahora http://127.0.0.1:8000/ me da este error:

ingrese la descripción de la imagen aquí

[EDITAR 2]

Ok, siguiendo el consejo de @geek_life, cambié los valores en mi archivo de configuración a:

 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PROJECT_NAME = 'cockpit' STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, PROJECT_NAME, "static/") STATICFILES_DIRS = [os.path.join(BASE_DIR, '../frontend/dist')] print("## BASE_DIR:", BASE_DIR) print("## STATIC_ROOT:", STATIC_ROOT) print("## STATICFILES_DIRS:", STATICFILES_DIRS) TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': ['cockpit/static/'], # <= THIS IS WHAT I CHANGED 'APP_DIRS': True, 'OPTIONS': {} # And here some options }, ]

que imprime

 ## BASE_DIR: /home/kramer65/repos/cockpit/backend ## STATIC_ROOT: /home/kramer65/repos/cockpit/backend/cockpit/static/ ## STATICFILES_DIRS: ['/home/kramer65/repos/cockpit/backend/../frontend/dist']

Y en el archivo settings/urls.py (todavía) obtuve esto:

 urlpatterns = [ path('admin/', admin.site.urls), path('cockpit/', include("cockpit.urls")), re_path('', TemplateView.as_view(template_name='index.html')), ]

Luego copié la carpeta static/ con el vuejs-ap integrado de cockpit/backend/ a cockpit/backend/cockpit/ .

Desafortunadamente sigo obteniendo el mismo resultado. El index.html se carga, pero los archivos js y css aún no. ¿Alguna otra idea?

over 4 years ago · Santiago Trujillo
6 answers
Answer question

0

Uso de STATIC_URL

En primer lugar, STATIC_URL será la url donde se servirán los archivos estáticos. Entonces, si configura STATIC_URL='/' y luego navega a http://127.0.0.1:8000/index.html , esencialmente servirá index.html desde dentro de la carpeta estática de su aplicación Django. Si va a http://127.0.0.1:8000/ está en su 'raíz de carpeta estática' y, como puede ver, un índice de directorio está prohibido. Así que no uses STATIC_URL='/'

Ubicación de los archivos

El tutorial que siguió agrega la carpeta de compilación del SPA a las plantillas en su archivo Django settings.py .

Entonces deberías probar y agregar:

 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(os.path.dirname(BASE_DIR), 'frontend', 'dist')], # <== ADDED THIS 'APP_DIRS': True, 'OPTIONS': { # removed to keep this example small }, ]

o si desea señalar sus archivos estáticos como directorio de plantillas:

 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'static')], 'APP_DIRS': True, 'OPTIONS': { # removed to keep this example small }, ]

Sin embargo, no creo que sea una buena práctica, ya que los archivos estáticos (imágenes, JS, CSS) tienen su propia calificación en Django .

Nota sobre os.path

Además, para su STATICFILES_DIRS , no es así como funciona os.path.join() . El primer argumento debe ser una ruta que desea unir con uno o más componentes de ruta, los componentes luego se pasan como los siguientes argumentos. Además, BASE_DIR no está en el nivel de directorio correcto, como puede ver cuando imprimió la ruta BASE_DIR . Necesita el padre del directorio BASE_DIR . Para obtener la ruta del directorio principal , puede hacer os.path.dirname(BASE_DIR) , porque BASE_DIR es una ruta. Entonces aplicando esto obtenemos:

 STATICFILES_DIRS = [ os.path.join(os.path.dirname(BASE_DIR), frontend, dist), ]

nota final

Siento que podría ser un patrón anti tener su SPA servido por Django sin que sea completamente autónomo en Django BASE_DIR (de ahí el nombre, directorio base). Pero no sé la fuente para ello, o exactamente cuál es la mejor práctica para esto.

over 4 years ago · Santiago Trujillo Report

0

Causa de errores

Para el primer caso

 STATIC_URL = '/static/'

Django intenta buscar archivos estáticos en la carpeta backend/static/ solo en el caso de que se mencione algo con url con /static/ por ejemplo /static/css/* o /static/js/* en su index.html , pero ese no es el caso aquí index.html tiene referencias de archivo como /css/* y /js/* , por lo tanto, no se encuentran.

La razón por la que este caso funciona en el ejemplo del blog es por la misma razón, es decir, sus archivos de plantilla se mantienen en un directorio '../frontend/build y los archivos estáticos están en '../frontend/build/static', por lo tanto, el index.html buscará static/js/* en lugar de /js/* , por lo tanto, se accede a la ubicación de /static/ url en Django, que luego busca los archivos en backend/static correctamente

Es por eso que, en su código, configurándolo en el segundo caso, es decir

 STATIC_URL = '/'

obtiene las URL de los archivos estáticos correctamente en /css/* y /js/* e incluso su /index.html puede considerarse como un archivo estático, es decir, todas estas URL se consideran estáticas y se buscan en la carpeta backend/static/ y por lo tanto, aparece correctamente en el navegador.

Pero ahora las URL están desordenadas, es decir, esto:

 re_path('', TemplateView.as_view(template_name='index.html')),

puede tratarse como Django buscando esta ubicación: / , pero ya está reservado para buscar archivos estáticos y no incluir ningún nombre de archivo después de / significa que no está buscando ningún archivo.

Solución posible

Django permite patrones de URL personalizados, es decir, puede crear 2 nuevas variables en settings.py, es decir

 STATIC_URL = "/static/" STATIC_ROOT = os.path.join(BASE_DIR, "static/") STATIC_JS_URL = "/js/" STATIC_JS_ROOT = os.path.join(STATIC_ROOT, "js/") STATIC_CSS_URL = "/css/" STATIC_CSS_ROOT = os.path.join(STATIC_ROOT, "css/")

y luego configure su urls.py

 from django.contrib import admin from django.urls import include, path, re_path from django.views.generic import TemplateView from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('cockpit/', include("cockpit.urls")), re_path('', TemplateView.as_view(template_name='index.html')), ] urlpatterns += static(settings.STATIC_JS_URL, document_root=settings.STATIC_JS_ROOT) urlpatterns += static(settings.STATIC_CSS_URL, document_root=settings.STATIC_CSS_ROOT)
over 4 years ago · Santiago Trujillo Report

0

¡Lo primero es lo primero! Si desea servir su interfaz de usuario de Django como archivos estáticos para la producción, ¡es una mala idea! Debe considerar usar nginx o un servidor web similar para servirle archivos estáticos.

El TemplateView en su urls.py es un poco problemático. Dado que sus archivos estáticos se publican en STATIC_URL = '/static/' en su primer escenario, las direcciones URL de los archivos js y css no coinciden. Puede editar los archivos y colocar etiquetas de plantillas static dentro de index.hml , pero tampoco es una buena idea. Cuando realiza cambios en el lado de vuejs, debe compilar y reemplazar el paquete directamente y su sitio se actualiza. Entonces, esta línea debe eliminarse para siempre, index.html debe tratarse como un archivo estático:

 re_path('', TemplateView.as_view(template_name='index.html')),

Cuando cambió STATIC_URL = '/' , puede acceder a todos sus archivos estáticos. Si ejecuta django en debug = True , sirve archivos estáticos automáticamente. De lo contrario, debe agregar url conf estática al archivo. (¡NO LO OLVIDES, esto no es bueno para la producción!)

 from django.contrib import admin from django.urls import include, path, re_path from django.views.generic import TemplateView from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('admin/', admin.site.urls), path('cockpit/', include("cockpit.urls")), ] urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Con esta configuración, debe tener cuidado con las direcciones URL y los nombres de archivos estáticos. Podrían anularse entre sí.

PD: Gracias por una pregunta tan detallada.

over 4 years ago · Santiago Trujillo Report

0

Hay una forma tonta de solucionar este problema.

Este problema se trata de que el html creado por VueJS obtendrá js y css de rutas como estas /js/app.12312sd.js y /css/app.dsfeewj.css .

html construido por vueJS

La configuración predeterminada de la ruta raíz del archivo estático es /static/ , por lo que solo necesita cambiar cada /js/... y /css/... en index.html manualmente o usar sed u otra cosa para reemplazarlos a /static/js/.../ y /static/css/.../ .

No puede reemplazar STATIC_URL a / porque es la URL raíz de su sitio web.

Después de editarlo, se verá así, y luego servidor su servidor django funcionará bien.

ingrese la descripción de la imagen aquí

over 4 years ago · Santiago Trujillo Report

0

Antes de construir su interfaz, coloque css/ y js/ en un directorio llamado 'static' y deje index.html como está. Luego, cuando ejecutes yarn build , la estructura de tu directorio sería la siguiente:

 cockpit ├── backend/ │ ├── cockpit/ │ │ ├── views.py │ │ ├── css/ │ │ └── etc.. │ ├── settings/ │ │ └── settings.py │ └── manage.py └── frontend/ └── dist/ ├── static/ │ ├── css/ │ └── js/ └── index.html

Configure su BASE_DIR y un FRONTEND_DIR para que apunten hacia 'cockpit/frontend/dist' para un uso rápido más adelante.

 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) FRONTEND_DIR = os.path.join(os.path.dirname(BASE_DIR),'frontend','dist')

Ahora copie los archivos estáticos de frontend en su directorio de backend como lo hizo anteriormente:

 STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(FRONTEND_DIR,'static/'), ] STATIC_ROOT = os.path.join(BASE_DIR, "static/")

O puede apuntar directamente su backend para servir desde el directorio frontend construido en lugar de copiarlo nuevamente. (De alguna manera siempre hago esto)

 STATIC_URL = '/static/' STATIC_ROOT = os.path.join(FRONTEND_DIR,'static/')

Incluya su directorio frontend construido en sus directorios de plantilla para que django pueda servir index.html

 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [FRONTEND_DIR], 'APP_DIRS': True, 'OPTIONS': { # removed to keep this example small }, }, ]

Ahora ejecuta tu servidor

 $ python manage.py collectstatic $ python manage.py runserver

Si luego decide implementar esto en línea, puede hacerlo fácilmente usando esta configuración configurando Nginx para servir archivos estáticos desde su directorio estático. Espero que esto ayude :)

Aclarando tu confusión en tu [EDITAR]

STATIC_ROOT apunta al directorio de su sistema. STATIC_URL se refiere a la URL en la que se accedería a sus archivos estáticos que están presentes en su STATIC_ROOT mientras usa su sitio web.

Digamos que tiene un archivo script.js en su directorio como se muestra

 cockpit ├── backend/ │ ├── cockpit/ │ │ ├── views.py │ │ ├── css/ │ │ └── etc.. │ ├── settings/ │ │ └── settings.py │ └── manage.py └── frontend/ └── dist/ ├── static/ │ ├── css/ │ └── js/ │ └── script.js └── index.html

y ha configurado su STATIC_ROOT para que apunte hacia 'cockpit/frontend/dist/static/'.

Ahora, si configura su STATIC_URL como 'static/' podrá acceder a ese script en http://127.0.0.1:8000/static/js/script.js

Alternativamente, si configura su STATIC_URL en 'xcsdf/' accederá a su archivo js en http://127.0.0.1:8000/xcsdf/js/script.js

over 4 years ago · Santiago Trujillo Report

0

Tuve este problema hace mucho tiempo y lo resolví con una solución simple. Es demasiado simple. Como veo, su carpeta estática no está en la raíz de su aplicación y está en el lugar equivocado. Póngalo en la raíz de su aplicación... porque Django está buscando la carpeta estática dentro de la raíz principal de su aplicación, donde se encuentra views.py. Tal vez tengas 5 aplicaciones o más. Django no se preocupa por la cantidad de aplicaciones que tiene, Django solo busca su carpeta estática en la raíz de su aplicación. Pero su carpeta de plantillas puede estar en la raíz de su proyecto. Entonces, coloque su carpeta estática en la raíz de su aplicación. En este caso me refiero al interior de la raíz de la cabina.

Y luego tienes que agregar estos cambios en settings.py

 PROJECT_NAME = '---Your projects name---' STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, PROJECT_NAME, 'static/') EXTERNAL_APPS = [ 'django.contrib.staticfiles', ]

Buena suerte.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!