It looks like a very basic question and I'm confused by the fact that I cannot find any sensible tutorial on that. I'm trying to setup Django + React production build. After running all kinds of transpilation, minification etc. I end up having .js and .css bundles, index.html and several other files like favicon, service-worker.js etc. Now I need to serve this with Django.
All of these files are static files and should probably be served as static files by the http server (nginx in my case). The variant I came up with was to modify index.html to make it a valid Django template: {% load static %} in the beginning, replace all hardcoded links with {% static 'filepath' %} and serve it using TemplateView, other files are served by nginx. This works fine, however, modifying build results looks like a bad idea. Generated bundles contain a unique hash for each build and I would need to replace that hash in the template after each build. I obviously can automate it but it looks weird. I would prefer not to touch build results at all, but how should I serve static files then? nginx is configured to serve static files under /static/ path and cannot serve files like service-worker.js as static files.
So the question is how do I configure Django + React for production so that I don't have to manually modify build results and can serve static files properly using nginx?
The main problem to combine React and Django is that Django wants to render the templates by itself, but React wants also to execute the render, since it has been created for that. That's why there a lot of approximations that use django just as as REST API when working with react.
But, if you want django to Render the templates to avoid having a Single Page Application (as react provides) and to use all the other tools from django, the main flow that we use in our company is:
You create your components, in js files. For example: component.js
You use babel to compile the JSX files to native Javascript, and babels creates, for example, component.build.js. Django will serve this compiled files, so react is going to be used only in develop tasks because all React code will be transformed to JS before moving to production. For django, all the react components will be just JS code already compiled.
You can use Webpack to automatically move component.build.js to a folder where django can serve them, for example your_project/static/your_app/component.buid.js
You create a django template base.html which will be used as the base template that all your templates will extend. Here you put the header and all your common scripts and styles. For example, bootstrap should be here if used. Remember to leave blocks in this base template to use them in the templates that are going to extend the base.html. Here is the base.html that we use:
{% with version="2.0" %}
<!DOCTYPE html>
{% load static %}
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="author" content="">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- base styles goes here -->
<!-- include here bootstrap or styles that are common to all your website -->
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
<!-- custom styles for each app go into this block-->
{% block app_styles %}
<!-- here will go the apps local styles -->
{% endblock %}
</head>
<body>
{% block app %}
<!-- This block will be used by the apps to load their react components -->
{% endblock %}
<!-- base js go here -->
<script src="{% static 'common/pluggins/jquery3.4.1.min.js' %}"></script>
</script>
<script src="{% static 'common/pluggins/fontawesome.js' %}"></script>
<script src="{% static 'common/scripts/base.js' %}?v={{version}}"></script> <!-- File for common utils -->
<!-- custom js for each app go here. You should define your Content() here -->
{% block local_scripts %}
<!-- here will go the app local scripts -->
{% endblock %}
</body>
</html>
{% endwith %}
Create the templates for each of your django apps, by extending the base.html. Remember to include here the <div> that is going to be used by react to render the content. Aslo, remember that this is the place to include the component.build.js compiled JS file that bable created before. Here there is an example that we use to build a dashboard.html in our website:
{% extends 'common/base.html' %}
{% load static %}
{% block app_styles %}
<link rel="stylesheet" href="{% static 'dashboard/styles/dashboard.css' %}?v={{version}}">
{% endblock %}
{% block app %}
<!-- Here is the div used by react -->
<div id="myreact-content"></div>
{% endblock %}
{% block local_scripts %}
<!-- IMPORTANT: Import here the compiled file -->
<script src="{% static 'component.build.js' %}"></script>
{% endblock %}
Set the correct urls.py in your projects and in your app
Set the correct configuration in setting.py to make accesible the static js/css files and the templates
Run your django server and You're done!
In this video you have a small guide on how to configure npm, babel and django. With a correct configuration, everything will be updated automatically when you change some code in your JSX (not compiled) files, so the develop tasks will be more friendly.
https://www.youtube.com/watch?v=Mx3ChaYA0Gw
Related
I already have a Django project with many apps and one of them is demo_app. I have some views and templates added to the demo app but I want to start using tailwind in the demo_app templates. I have seen that to add tailwind I need to create the theme app using tailwind but I want to add it to the already existing demo_app. How can I do that?
You can create the theme app just like the documentation says and add the tags to your existing app. I followed the process in this link. The js config in the app already looks for the tailwind tags in other apps. The tags I used are
{% load static tailwind_tags %} and {% tailwind_css %}. I added them to the html template in my existing app.
{% load static tailwind_tags %} at the top of the template and {% tailwind_css %} in the <head>
What I did that worked for me was install tailwind-cli in the static folder of my Django app, check out the tailwind-cli installation guide Tailwind Documentation. And then load the CSS in the HTML template. Below is how I referenced the tailwind CSS.
{% load static %}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="{% static 'main.css' %}" rel="stylesheet">
</head>
<body>
<h1 class="text-3xl font-bold">
Hello, world!
</h1>
</body>
</html>
If I structure the first two lines of my HTML doc like this:
{% load static %}
<!DOCTYPE html>
It appears that none of the javascript or CSS run properly, and the webpage displays like this:
However, if I put any character after the {% load static %} expression,
For example, if I structure the first two lines of my HTML doc like this:
{% load static %}.
<!DOCTYPE html>
Then the scripts and CSS components run properly and the webpage displays as it should. Why is this?
Figured it out. For some reason, the content security policy that I had implemented was causing this issue. After removing the CSP, the static files began to behave in-line with expectations regardless of the presence/absence of a character after {% load static %}.
{% load static %}
<!DOCTYPE html>
You did it right but you have load the static files too like i did below.
<!-- js -->
<script type="text/javascript" src="{% static 'js/jquery.min.js' %}"></script>
<!-- js -->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/bootstrap-select.js' %}"></script>
You have to use this tag to load static files in template "{% static %}" this is the syntax for load static files.
#And give it the path in settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
And store css and js in static folder in your project too.Than its gonna work.
Make sure that the STATIC_URL of your settings is correct.
This is my index page in django
{% load render_bundle from webpack_loader %}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/MaterialDesign-Webfont/3.8.95/css/materialdesignicons.css">
<meta charset="UTF-8">
<title>My test</title>
</head>
<body>
<div id="app">
<h1>TEST</h1>
</div>
{% render_bundle 'main' %}
</body>
</html>
And this is a standard Vue navbar.
<template>
<v-app id="sandbox">
<v-navigation-drawer
v-model="primaryDrawer.model"
:clipped="primaryDrawer.clipped"
:floating="primaryDrawer.floating"
:mini-variant="primaryDrawer.mini"
:permanent="primaryDrawer.type === 'permanent'"
:temporary="primaryDrawer.type === 'temporary'"
app
overflow
><v-switch
v-model="$vuetify.theme.dark"
primary
label="Dark"
></v-switch></v-navigation-drawer>
<v-app-bar
:clipped-left="primaryDrawer.clipped"
app
>
<v-app-bar-nav-icon
v-if="primaryDrawer.type !== 'permanent'"
#click.stop="primaryDrawer.model = !primaryDrawer.model"
></v-app-bar-nav-icon>
<v-toolbar-title>Vuetify</v-toolbar-title>
</v-app-bar>
</v-app>
</template>
The code is working, and i can see Vue being loaded when i open my Django site.
The problem with this is that i don't know how to get them along. For example, i added a <h1>TEST</h1> but it does not appear when i load Vue, since the Vue part covers it. I also don't understand, if i have a conditional on my Django template, such as {% if user.is_authenticated %} i can't use it on Vue, because it won't be loaded by it.
For example, i have a navbar. Instead of that navbar i want to use the below Vue navbar but i can't, because the current navbar has some links to parts of my site, and since the links are made in Django template language, they won't be loaded by Vue.
You should understand that Vue is a frontend framework that is agnostic to the backend, and Django is, in contrast a backend framework (that can be used in such way to be agnostic to the frontend, I assume this is what you are trying to do).
The way Vue works is that it renders the content inside the div#app tag in index.html, that's why your h1 tag doesn't work. you will have to include that h1 tag inside your vue app in the right component in order to work (don't forget to recompile your components after editing, in case you are using smthng like webpack...etc).
Regarding the Django conditionals part, the point is that now, your Vue app is a seperate application than the Django App (and they will have to communicate through an API using HTTP calls). So in order for authentication to work (or any other logic), you will have to handle that logic both in your Vue app and your Django app
Just started to learn Django and Twitter Bootstrap on some project.
I use external links to connect css and js files of bootstrap, but today I found Django-Bootstrap-Toolkit, so I wonder how to switch my project to it.
project folder:
myproject/
/bootstrap_toolkit/
/myproject/
/templates/
/someapp/
/manage.py
settings.py
INSTALLED_APPS = (
...
'someapp',
'bootstrap_toolkit',
...)
templates/base.html
{% load bootstrap_toolkit %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!--CSS Bootstrap-->
<link rel="stylesheet"
href="//netdna.bootstrapcdn.com/bootstrap/3.0.1/css/bootstrap.min.css">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
...
</body>
</html>
So, if I'm deleting link tag, all the CSS disappears, so, I wonder what I've done wrong, and my toolkit is not connected?
If you're using bootstrap3, according to the documentation you should instead use this package: https://github.com/dyve/django-bootstrap3
Regarding the CSS files: I have never used either of those packages but you definitely have to have a link to the bootstrap static files somewhere. So just don't remove the link tag and you're fine!
I'm new to Django, and i'm having hard time including css styles in a template.
I read this and tried to do the same but it's not working for me.
my Template:
{% load static %}<html><head><link href="{% get_static_prefix %}/style.css" rel='stylesheet' type='text/css' /></head><body>
the HTML i get:
<head><link href="C:/Users/Nayish/workspace/am/src/am/static/style.css"rel='stylesheet'type='text/css' /></head>
Note that this is the folder containing my css.
Thanks, Boris.
Make sure you haven't mixed up the STATIC_ROOT and STATIC_URL settings.
STATIC_ROOT defines where the files are on the storage system (usually your local hard disc for local development), while STATIC_URL defines the URL from where the server serves them. The second one is usually referred to in templates, and it is also the value that the {% get_static_prefix %} template tag returns.
I am guessing you aren't using static css sheets. I always just do:
<html>
<head>
{%block stylesheet %}
<style type="text/css" title="currentStyle">
#import "{{MEDIA_URL}}css/style.css";
</style>
{% endblock stylesheet%}
....
I then set my Media root, and store the files as
MEDIA_ROOT=<fullyquallified patyh>/Media/css/<css files>
MEDIA_URL=http://localhost/mysite/
It should be noted that STATIC_URL defaults to MEDIA_URL if its not defined.