jacek

Initial commit

Showing 69 changed files with 1373 additions and 0 deletions
DEBUG=1
SECRET_KEY=change_me
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]
\ No newline at end of file
... ...
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# CUSTOM
*.pyc
__pycache
.DS_Store
.idea/
.vscode/
\ No newline at end of file
... ...
# Django On Docker
### Quickstart:
- Local
* docker-compose.yml
* http://localhost:8001
```sh
$ docker-compose up -d
```
--------------------------------------------------
### Comandos:
- Comandos:
```sh
# Local (docker-compose.yml)
$ docker-compose exec web python manage.py createsuperuser
$ docker-compose exec web python manage.py makemigrations
$ docker-compose exec web python manage.py migrate
```
Más info
- https://docs.docker.com/compose/reference/
- Testing:
```sh
$ docker-compose exec web python manage.py test
$ docker-compose exec web python manage.py test apps.welcome
$ docker-compose exec web python manage.py test apps.welcome.tests
$ docker-compose exec web python manage.py test apps.welcome.tests.test_views
$ docker-compose exec web python manage.py test apps.welcome.tests.test_views.WelcomeIndexTest
$ docker-compose exec web python manage.py test apps.welcome.tests.test_views.WelcomeIndexTest.test_view_url_accessible_by_name
$ docker-compose exec web python manage.py test --verbosity 2
# Los niveles de detalle permitidos son 0, 1, 2 y 3, siendo el valor predeterminado "1".
```
Más info
- https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Testing
\ No newline at end of file
... ...
# pull official base image
FROM python:3.9.1
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install dependencies
RUN apt-get update && apt-get install -y \
gettext \
netcat \
&& rm -rf /var/lib/apt/lists/*
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
# copy entrypoint.sh
COPY ./entrypoint.sh .
# copy project
COPY . .
# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
... ...
from django.apps import AppConfig
class CoreConfig(AppConfig):
name = 'apps.core'
... ...
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Welcome!</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://getbootstrap.com/docs/4.0/examples/dashboard/dashboard.css">
<!-- BEGIN: Page CSS -->
{% block css %}{% endblock %}
<!-- END: Page CSS -->
</head>
<body>
<!-- BEGIN: Navbar -->
{% include 'core/navbar.html' %}
<!-- END: Navbar -->
<div class="container-fluid">
<div class="row">
<!-- BEGIN: Sidebar -->
{% include 'core/sidebar.html' %}
<!-- END: Sidebar -->
<main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
<!-- BEGIN: Content -->
{% block content %}{% endblock %}
<!-- END: Content -->
</main>
</div>
</div>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<!-- BEGIN: Page JS -->
{% block javascript %}{% endblock %}
<!-- END: Page JS -->
</body>
</html>
... ...
{% load static i18n %}
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
<a class="navbar-brand col-sm-3 col-md-2 mr-0" href="/">{% trans 'Django2React' %}</a>
<ul class="navbar-nav px-3">
<li class="nav-item text-nowrap">
<a class="nav-link" href="/admin">{% trans 'Admin' %}</a>
</li>
</ul>
</nav>
\ No newline at end of file
... ...
{% load static i18n %}
{% load startswith %}
<nav class="col-md-2 d-none d-md-block bg-light sidebar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item">
{% url 'djangoapp:index' as url_djangoapp %}
<a class="nav-link {% if request.path|startswith:url_djangoapp %} active {% endif %}"
href="{% url 'djangoapp:index' %}">
{% trans 'App django' %}
</a>
</li>
<li class="nav-item">
{% url 'reactapp:index' as url_reactapp %}
<a class="nav-link {% if request.path|startswith:url_reactapp %} active {% endif %}"
href="{% url 'reactapp:index' %}">
{% trans 'App react' %}
</a>
</li>
</ul>
</div>
</nav>
\ No newline at end of file
... ...
from django import template
register = template.Library()
@register.filter('startswith')
def startswith(text, starts):
if isinstance(text, str):
return text.startswith(starts)
return False
... ...
from django.shortcuts import render
# Create your views here.
... ...
from django.contrib import admin
from .models import Book
admin.site.register([Book])
\ No newline at end of file
... ...
from django.apps import AppConfig
class DjangoappConfig(AppConfig):
name = 'apps.djangoapp'
... ...
from django.utils.translation import ugettext_lazy as _
from django import forms
from .models import Book
class BookForm(forms.ModelForm):
title = forms.CharField(
label=_('Titulo'),
max_length=250,
required=False,
widget=forms.TextInput(
attrs={'class': 'form-control', 'placeholder': _('Titulo')}
)
)
class Meta:
model = Book
fields = ('title',)
def clean_title(self):
"""
Validación de titulo.
:return:
"""
title = self.cleaned_data.get('title', None)
if not title:
raise forms.ValidationError(_('Este campo es obligatorio.'))
if title[0].islower():
raise forms.ValidationError(_('El título debe empezar por una mayúscula.'))
return title
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
... ...
# Generated by Django 3.1.6 on 2022-03-18 10:37
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Book',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Created')),
('modified', models.DateTimeField(auto_now=True, null=True, verbose_name='Modified')),
('title', models.CharField(blank=True, max_length=250, null=True)),
],
options={
'verbose_name': 'Book',
'verbose_name_plural': 'Books',
},
),
]
... ...
from django.utils.translation import ugettext_lazy as _
from django.db import models
class Book(models.Model):
created = models.DateTimeField(verbose_name=_('Created'), null=True, blank=True, auto_now_add=True)
modified = models.DateTimeField(verbose_name=_('Modified'), null=True, blank=True, auto_now=True)
title = models.CharField(max_length=250, null=True, blank=True)
class Meta:
verbose_name = _('Book')
verbose_name_plural = _('Books')
def __str__(self):
return self.title
... ...
{% extends 'core/base.html' %}
{% load static i18n %}
{% block css %}
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">{% trans 'DjangoApp!' %}</h1>
</div>
<div class="col">
<form method="POST">
{% csrf_token %}
<!-- title -->
<div class="form-group {% if form.title.errors %} has-error {% endif %}">
{{ form.title.label_tag }}
{{ form.title }}
{% if form.title.help_text %}
<span class="help-block">{{ form.title.help_text }}</span>
{% endif %}
{% for error in form.title.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
<div class="d-flex justify-content-between">
<a href="{%url 'djangoapp:index' %}" class="btn btn-outline-danger">{% trans 'Volver' %} </a>
<button type="submit" class="btn btn-primary">{% trans "Crear" %}</button>
</div>
</form>
</div>
{% endblock %}
{% block javascript %}
{% endblock %}
\ No newline at end of file
... ...
{% extends 'core/base.html' %}
{% load static i18n %}
{% block css %}
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">{% trans 'DjangoApp!' %}</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<a href="{% url 'djangoapp:create' %}" class="btn btn-sm btn-outline-secondary">
{% trans 'Crear' %}
</a>
</div>
</div>
<div class="col">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>{% trans "ID" %}</th>
<th>{% trans "Titulo" %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>{{ book.id }}</td>
<td>{{ book.title }}</td>
<td class="text-right text-nowrap">
<a href="{% url 'djangoapp:read' book.id %}"
class="btn btn-outline-info">
{% trans 'Ver' %}
</a>
<a href="{% url 'djangoapp:update' book.id %}"
class="btn btn-outline-primary">
{% trans 'Editar' %}
</a>
<a href="{% url 'djangoapp:delete' book.id %}"
class="btn btn-outline-secondary">
{% trans 'Borrar' %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
{% block javascript %}
{% endblock %}
\ No newline at end of file
... ...
{% extends 'core/base.html' %}
{% load static i18n %}
{% block css %}
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">{% trans 'DjangoApp!' %}</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group mr-2">
<a href="{% url 'djangoapp:update' book.id %}" class="btn btn-sm btn-outline-secondary">{% trans 'Editar' %}</a>
<a href="{% url 'djangoapp:delete' book.id %}" class="btn btn-sm btn-outline-secondary">{% trans 'Borrar' %}</a>
</div>
<a href="{% url 'djangoapp:index' %}" class="btn btn-sm btn-outline-secondary">
{% trans 'Listar' %}
</a>
</div>
</div>
<div class="col">
<p>#{{ book.id }} {{ book.title }}</p>
</div>
{% endblock %}
{% block javascript %}
{% endblock %}
\ No newline at end of file
... ...
{% extends 'core/base.html' %}
{% load static i18n %}
{% block css %}
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">{% trans 'DjangoApp!' %}</h1>
</div>
<div class="col">
<form method="POST">
{% csrf_token %}
<!-- title -->
<div class="form-group {% if form.title.errors %} has-error {% endif %}">
{{ form.title.label_tag }}
{{ form.title }}
{% if form.title.help_text %}
<span class="help-block">{{ form.title.help_text }}</span>
{% endif %}
{% for error in form.title.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
<div class="d-flex justify-content-between">
<a href="{%url 'djangoapp:index' %}" class="btn btn-outline-danger">{% trans 'Volver' %} </a>
<button type="submit" class="btn btn-primary">{% trans "Actualizar" %}</button>
</div>
</form>
</div>
{% endblock %}
{% block javascript %}
{% endblock %}
\ No newline at end of file
... ...
from django.test import TestCase
# Create your tests here.
... ...
from django.urls import path, include
from . import views
app_name = 'djangoapp'
urlpatterns = [
path('djangoapp/', include(([
path('', views.index, name='index'),
path('create', views.create, name='create'),
path('read/<book_id>', views.read, name='read'),
path('update/<book_id>', views.update, name='update'),
path('delete/<book_id>', views.delete, name='delete'),
])))
]
... ...
from django.shortcuts import render, redirect
from .forms import BookForm
from .models import Book
def index(request):
"""
-- INDEX --
:param request:
:return:
"""
books = Book.objects.all()
return render(request, 'djangoapp/index.html', {
'books': books
})
def create(request):
"""
-- CREATE --
:param request:
:return:
"""
form = BookForm()
if request.method == 'POST':
form = BookForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return redirect('djangoapp:index')
return render(request, 'djangoapp/create.html', {
'form': form
})
def read(request, book_id):
"""
-- READ --
:param request:
:param id:
:return:
"""
book = Book.objects.get(pk=book_id)
return render(request, 'djangoapp/read.html', {
'book': book
})
def update(request, book_id):
"""
-- CREATE --
:param request:
:return:
"""
book = Book.objects.get(pk=book_id)
form = BookForm(instance=book)
if request.method == 'POST':
form = BookForm(request.POST, instance=book)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return redirect('djangoapp:index')
return render(request, 'djangoapp/update.html', {
'form': form
})
def delete(request, book_id):
"""
-- DELETE --
:param request:
:param book_id:
:return:
"""
Book.objects.get(pk=book_id).delete()
return redirect('djangoapp:index')
... ...
from django.contrib import admin
from .models import Book
admin.site.register([Book])
\ No newline at end of file
... ...
from django.apps import AppConfig
class ReactappConfig(AppConfig):
name = 'apps.reactapp'
... ...
from django.utils.translation import ugettext_lazy as _
from django import forms
from .models import Book
class BookForm(forms.ModelForm):
title = forms.CharField(
label=_('Titulo'),
max_length=250,
required=False,
widget=forms.TextInput(
attrs={'class': 'form-control', 'placeholder': _('Titulo')}
)
)
class Meta:
model = Book
fields = ('title',)
def clean_title(self):
"""
Validación de titulo.
:return:
"""
title = self.cleaned_data.get('title', None)
if not title:
raise forms.ValidationError(_('Este campo es obligatorio.'))
if title[0].islower():
raise forms.ValidationError(_('El título debe empezar por una mayúscula.'))
return title
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
... ...
# Generated by Django 3.1.6 on 2022-03-18 10:37
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Book',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Created')),
('modified', models.DateTimeField(auto_now=True, null=True, verbose_name='Modified')),
('title', models.CharField(blank=True, max_length=250, null=True)),
],
options={
'verbose_name': 'Book',
'verbose_name_plural': 'Books',
},
),
]
... ...
from django.utils.translation import ugettext_lazy as _
from django.db import models
class Book(models.Model):
created = models.DateTimeField(verbose_name=_('Created'), null=True, blank=True, auto_now_add=True)
modified = models.DateTimeField(verbose_name=_('Modified'), null=True, blank=True, auto_now=True)
title = models.CharField(max_length=250, null=True, blank=True)
class Meta:
verbose_name = _('Book')
verbose_name_plural = _('Books')
def __str__(self):
return self.title
... ...
{% extends 'core/base.html' %}
{% load static i18n %}
{% block css %}
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">{% trans 'ReactApp!' %}</h1>
</div>
<div class="col">
<form method="POST">
{% csrf_token %}
<!-- title -->
<div class="form-group {% if form.title.errors %} has-error {% endif %}">
{{ form.title.label_tag }}
{{ form.title }}
{% if form.title.help_text %}
<span class="help-block">{{ form.title.help_text }}</span>
{% endif %}
{% for error in form.title.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
<div class="d-flex justify-content-between">
<a href="{%url 'reactapp:index' %}" class="btn btn-outline-danger">{% trans 'Volver' %} </a>
<button type="submit" class="btn btn-primary">{% trans "Crear" %}</button>
</div>
</form>
</div>
{% endblock %}
{% block javascript %}
{% endblock %}
\ No newline at end of file
... ...
{% extends 'core/base.html' %}
{% load static i18n %}
{% block css %}
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">{% trans 'ReactApp!' %}</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<a href="{% url 'reactapp:create' %}" class="btn btn-sm btn-outline-secondary">
{% trans 'Crear' %}
</a>
</div>
</div>
<div class="col">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>{% trans "ID" %}</th>
<th>{% trans "Titulo" %}</th>
<th></th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>{{ book.id }}</td>
<td>{{ book.title }}</td>
<td class="text-right text-nowrap">
<a href="{% url 'reactapp:read' book.id %}"
class="btn btn-outline-info">
{% trans 'Ver' %}
</a>
<a href="{% url 'reactapp:update' book.id %}"
class="btn btn-outline-primary">
{% trans 'Editar' %}
</a>
<a href="{% url 'reactapp:delete' book.id %}"
class="btn btn-outline-secondary">
{% trans 'Borrar' %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
{% block javascript %}
{% endblock %}
\ No newline at end of file
... ...
{% extends 'core/base.html' %}
{% load static i18n %}
{% block css %}
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">{% trans 'ReactApp!' %}</h1>
<div class="btn-toolbar mb-2 mb-md-0">
<div class="btn-group mr-2">
<a href="{% url 'reactapp:update' book.id %}" class="btn btn-sm btn-outline-secondary">{% trans 'Editar' %}</a>
<a href="{% url 'reactapp:delete' book.id %}" class="btn btn-sm btn-outline-secondary">{% trans 'Borrar' %}</a>
</div>
<a href="{% url 'reactapp:index' %}" class="btn btn-sm btn-outline-secondary">
{% trans 'Listar' %}
</a>
</div>
</div>
<div class="col">
<p>#{{ book.id }} {{ book.title }}</p>
</div>
{% endblock %}
{% block javascript %}
{% endblock %}
\ No newline at end of file
... ...
{% extends 'core/base.html' %}
{% load static i18n %}
{% block css %}
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">{% trans 'ReactApp!' %}</h1>
</div>
<div class="col">
<form method="POST">
{% csrf_token %}
<!-- title -->
<div class="form-group {% if form.title.errors %} has-error {% endif %}">
{{ form.title.label_tag }}
{{ form.title }}
{% if form.title.help_text %}
<span class="help-block">{{ form.title.help_text }}</span>
{% endif %}
{% for error in form.title.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
<div class="d-flex justify-content-between">
<a href="{%url 'reactapp:index' %}" class="btn btn-outline-danger">{% trans 'Volver' %} </a>
<button type="submit" class="btn btn-primary">{% trans "Actualizar" %}</button>
</div>
</form>
</div>
{% endblock %}
{% block javascript %}
{% endblock %}
\ No newline at end of file
... ...
from django.test import TestCase
# Create your tests here.
... ...
from django.urls import path, include
from . import views
app_name = 'reactapp'
urlpatterns = [
path('reactapp/', include(([
path('', views.index, name='index'),
path('create', views.create, name='create'),
path('read/<book_id>', views.read, name='read'),
path('update/<book_id>', views.update, name='update'),
path('delete/<book_id>', views.delete, name='delete'),
])))
]
... ...
from django.shortcuts import render, redirect
from .forms import BookForm
from .models import Book
def index(request):
"""
-- INDEX --
:param request:
:return:
"""
books = Book.objects.all()
return render(request, 'reactapp/index.html', {
'books': books
})
def create(request):
"""
-- CREATE --
:param request:
:return:
"""
form = BookForm()
if request.method == 'POST':
form = BookForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return redirect('reactapp:index')
return render(request, 'reactapp/create.html', {
'form': form
})
def read(request, book_id):
"""
-- READ --
:param request:
:param book_id:
:return:
"""
book = Book.objects.get(pk=book_id)
return render(request, 'reactapp/read.html', {
'book': book
})
def update(request, book_id):
"""
-- CREATE --
:param request:
:param book_id:
:return:
"""
book = Book.objects.get(pk=book_id)
form = BookForm(instance=book)
if request.method == 'POST':
form = BookForm(request.POST, instance=book)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return redirect('reactapp:index')
return render(request, 'reactapp/update.html', {
'form': form
})
def delete(request, book_id):
"""
-- DELETE --
:param request:
:param book_id:
:return:
"""
Book.objects.get(pk=book_id).delete()
return redirect('reactapp:index')
... ...
from django.contrib import admin
# Register your models here.
... ...
from django.apps import AppConfig
class WelcomeConfig(AppConfig):
name = 'apps.welcome'
... ...
from django.db import models
# Create your models here.
... ...
{% extends 'core/base.html' %}
{% load static i18n %}
{% block css %}
{% endblock %}
{% block content %}
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
<h1 class="h2">{% trans 'Welcome!' %}</h1>
</div>
<div class="d-flex justify-content-center">
<a href="/admin"><img src="{% static 'welcome/images/pulpo.png' %}" class="img-fluid"></a>
</div>
{% endblock %}
{% block javascript %}
{% endblock %}
\ No newline at end of file
... ...
from django.test import TestCase
class WelcomeFormTest(TestCase):
pass
... ...
from django.test import TestCase
class WelcomeModelTest(TestCase):
@classmethod
def setUpTestData(cls):
"""Set up non-modified objects used by all test methods."""
# User.objects.create(first_name='Big', last_name='Bob')
pass
... ...
from django.test import TestCase
# Create your tests here.
from django.urls import reverse
class WelcomeIndexTest(TestCase):
@classmethod
def setUpTestData(cls):
# print("setUpTestData: Run once to set up non-modified data for all class methods.")
pass
def setUp(self):
# print("setUp: Run once for every test method to setup clean data.")
pass
def test_view_url_exists_at_desired_location(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
def test_view_url_accessible_by_name(self):
response = self.client.get(reverse('welcome:index'))
self.assertEqual(response.status_code, 200)
def test_view_uses_correct_template(self):
response = self.client.get(reverse('welcome:index'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'welcome/index.html')
... ...
from django.urls import path
from . import views
app_name = 'welcome'
urlpatterns = [
path('', views.index, name='index'),
]
... ...
from django.shortcuts import render
def index(request):
return render(request, 'welcome/index.html')
... ...
"""
ASGI config.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conf.settings')
application = get_asgi_application()
... ...
"""
Django settings.
Generated by 'django-admin startproject' using Django 3.0.5.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.0/ref/settings/
"""
from django.utils.translation import ugettext_lazy as _
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
SECRET_KEY = os.environ.get("SECRET_KEY")
DEBUG = int(os.environ.get("DEBUG", default=0))
# 'DJANGO_ALLOWED_HOSTS' should be a single string of hosts with a space between each.
# For example: 'DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]'
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# external apps
'rosetta',
"apps.core.apps.CoreConfig",
"apps.welcome.apps.WelcomeConfig",
"apps.djangoapp.apps.DjangoappConfig",
"apps.reactapp.apps.ReactappConfig",
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'conf.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'conf.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": os.environ.get("SQL_ENGINE", "django.db.backends.sqlite3"),
"NAME": os.environ.get("SQL_DATABASE", os.path.join(BASE_DIR, "db.sqlite3")),
# "USER": os.environ.get("SQL_USER", "user"),
# "PASSWORD": os.environ.get("SQL_PASSWORD", "password"),
# "HOST": os.environ.get("SQL_HOST", "localhost"),
# "PORT": os.environ.get("SQL_PORT", "5432"),
# "OPTIONS": {
# 'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
# }
}
}
# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
# {
# 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
# },
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
'OPTIONS': {
'min_length': 4,
}
},
# {
# 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
# },
]
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
PREFIX_DEFAULT_LANGUAGE = False
LANGUAGE_CODE = 'es'
TIME_ZONE = 'Europe/Madrid'
USE_I18N = True
USE_L10N = True
USE_TZ = False
USE_THOUSAND_SEPARATOR = True
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'),
)
LANGUAGES = (
('en', _('English')),
('es', _('Español')),
)
# Rosetta
ROSETTA_WSGI_AUTO_RELOAD = True
ROSETTA_SHOW_AT_ADMIN_PANEL = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
... ...
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('i18n/', include('django.conf.urls.i18n')),
]
if bool(settings.DEBUG):
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# Rosetta Plugin Translate
if 'rosetta' in settings.INSTALLED_APPS:
urlpatterns += [
path('rosetta/', include('rosetta.urls'))
]
urlpatterns += i18n_patterns(
# Apps:
# Welcome
path('', include('apps.welcome.urls', namespace='welcome')),
# DjangoApp
path('', include('apps.djangoapp.urls', namespace='djangoapp')),
# ReactApp
path('', include('apps.reactapp.urls', namespace='reactapp')),
# Show hide LANGUAGE_CODE in URL
prefix_default_language=settings.PREFIX_DEFAULT_LANGUAGE
)
... ...
"""
WSGI config.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conf.settings')
application = get_wsgi_application()
... ...
#!/bin/sh
if [ "$DATABASE" = "postgres" ]
then
echo "Waiting for postgres..."
while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 0.1
done
echo "PostgreSQL started"
fi
if [ "$DATABASE" = "mysql" ]
then
echo "Waiting for mysql..."
while ! nc -z $SQL_HOST $SQL_PORT; do
sleep 0.1
done
echo "MySQL started"
fi
#python manage.py flush --no-input
python manage.py migrate
exec "$@"
... ...
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conf.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
... ...
Django==3.1.6
gunicorn==20.0.4
django-rosetta==0.9.5
... ...
version: '3.8'
services:
web:
build: ./app
command: python manage.py runserver 0.0.0.0:8001
volumes:
- ./app/:/usr/src/app/
ports:
- 8001:8001
env_file:
- ./.env
\ No newline at end of file
... ...