├── .gitignore ├── build.sh ├── manage.py ├── myapp ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_task.py │ ├── 0003_task_done.py │ └── __init__.py ├── models.py ├── static │ ├── fazt.png │ └── styles │ │ └── main.css ├── templates │ ├── about.html │ ├── index.html │ ├── layouts │ │ ├── base.html │ │ └── base2.html │ ├── projects │ │ ├── create_project.html │ │ ├── detail.html │ │ └── projects.html │ └── tasks │ │ ├── create_task.html │ │ └── tasks.html ├── tests.py ├── urls.py └── views.py ├── mysite ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | db.sqlite3 3 | __pycache__ 4 | staticfiles -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # exit on error 3 | set -o errexit 4 | 5 | pip install -r requirements.txt 6 | 7 | python manage.py collectstatic --no-input 8 | python manage.py migrate -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /myapp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fazt/django_course/a83c2825a77afb46829785268b3c37541c72608c/myapp/__init__.py -------------------------------------------------------------------------------- /myapp/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import Project, Task 3 | 4 | # Register your models here. 5 | admin.site.register(Project) 6 | admin.site.register(Task) -------------------------------------------------------------------------------- /myapp/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class MyappConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'myapp' 7 | -------------------------------------------------------------------------------- /myapp/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | class CreateNewTask(forms.Form): 4 | title = forms.CharField(label="Titulo de tarea", max_length=200, widget=forms.TextInput(attrs={'class': 'input'})) 5 | description=forms.CharField(label="descripcion de la tarea", widget=forms.Textarea(attrs={'class': 'input'})) 6 | 7 | 8 | class CreateNewProject(forms.Form): 9 | name = forms.CharField(label="Nombre del Proyect", max_length=200, widget=forms.TextInput(attrs={'class': 'input'})) -------------------------------------------------------------------------------- /myapp/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-31 01:37 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Project', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=200)), 19 | ], 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /myapp/migrations/0002_task.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-31 01:45 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('myapp', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Task', 16 | fields=[ 17 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('title', models.CharField(max_length=200)), 19 | ('description', models.TextField()), 20 | ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='myapp.project')), 21 | ], 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /myapp/migrations/0003_task_done.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-31 04:12 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('myapp', '0002_task'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='task', 15 | name='done', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /myapp/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fazt/django_course/a83c2825a77afb46829785268b3c37541c72608c/myapp/migrations/__init__.py -------------------------------------------------------------------------------- /myapp/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | class Project(models.Model): 5 | name = models.CharField(max_length=200) 6 | 7 | def __str__(self): 8 | return self.name 9 | 10 | 11 | class Task(models.Model): 12 | title = models.CharField(max_length=200) 13 | description = models.TextField() 14 | project = models.ForeignKey(Project, on_delete=models.CASCADE) 15 | done = models.BooleanField(default=False) 16 | 17 | def __str__(self): 18 | return self.title + ' - ' + self.project.name -------------------------------------------------------------------------------- /myapp/static/fazt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fazt/django_course/a83c2825a77afb46829785268b3c37541c72608c/myapp/static/fazt.png -------------------------------------------------------------------------------- /myapp/static/styles/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #202020; 3 | color: whitesmoke; 4 | } 5 | 6 | .navbar { 7 | background: #404040; 8 | padding: 5px 0; 9 | } 10 | 11 | .navbar ul { 12 | display: flex; 13 | justify-content: space-between; 14 | } 15 | 16 | .navbar ul li { 17 | list-style: none; 18 | } 19 | 20 | .navbar ul li a { 21 | color: white; 22 | text-decoration: none; 23 | } 24 | 25 | .navbar ul li a:hover { 26 | color: aquamarine; 27 | } 28 | 29 | .container { 30 | max-width: 1200px; 31 | margin: auto; 32 | padding: 20px 10px; 33 | } 34 | 35 | .card { 36 | background: whitesmoke; 37 | color: black; 38 | padding: 10px; 39 | margin-bottom: 2px; 40 | } 41 | 42 | .input { 43 | background: wheat; 44 | padding: 10px; 45 | text-align: center; 46 | display: block; 47 | } -------------------------------------------------------------------------------- /myapp/templates/about.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% block content %} 4 | 5 |

About

6 | 7 |

Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fugiat, hic possimus! Veritatis blanditiis enim corporis recusandae repellat nihil architecto modi eveniet pariatur expedita ipsa numquam sunt, libero vero quaerat eius hic. Voluptas veniam atque fuga at cum ea nesciunt dolore, nemo perspiciatis nisi, possimus quaerat, accusamus fugit facilis optio eaque maiores aperiam sunt quisquam repellendus ratione commodi inventore itaque vero? Magni asperiores sequi laborum doloribus quaerat minus natus molestiae, nulla quisquam, ratione enim quos, dolorem corrupti modi earum dicta error numquam totam sit corporis dolore! Sint libero dolor obcaecati ipsa molestias. Consequatur voluptates eligendi iusto debitis possimus adipisci quidem natus.

8 | 9 |

Website created by {{ username }}

10 | 11 | {% endblock %} -------------------------------------------------------------------------------- /myapp/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | 4 | {% block content %} 5 | 6 | {% load static %} 7 | 8 |

{{ title }}

9 | 10 | 11 | 12 |

Lorem ipsum dolor sit amet consectetur adipisicing elit. Sint, dolor? Aperiam, deserunt quidem nam sunt est quaerat nesciunt non repellat sit alias dolore nobis animi molestias ducimus qui eligendi itaque.

13 | 14 | {% endblock %} -------------------------------------------------------------------------------- /myapp/templates/layouts/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Django Projects 10 | 11 | 12 | 13 | 14 | 36 | 37 |
38 | {% block content %} 39 | {% endblock %} 40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /myapp/templates/layouts/base2.html: -------------------------------------------------------------------------------- 1 |

Dashboard

2 | 3 |

Navegaciones especiales

4 | 5 | {% block content %} 6 | {% endblock %} -------------------------------------------------------------------------------- /myapp/templates/projects/create_project.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Create Project

6 | 7 |
8 | {% csrf_token %} 9 | {{form}} 10 | 13 |
14 | 15 | {% endblock %} -------------------------------------------------------------------------------- /myapp/templates/projects/detail.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% block content %} 4 |

{{project}}

5 | 6 | {% for task in tasks %} 7 | 8 |
9 |

{{task.title}}

10 |
11 | 12 | {% endfor %} 13 | 14 | {% endblock %} -------------------------------------------------------------------------------- /myapp/templates/projects/projects.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Projects

6 | 7 | {% for project in projects %} 8 | 9 |
10 | 11 |

{{project.name}}

12 |
13 |
14 | 15 | {% endfor %} 16 | 17 | {% endblock %} -------------------------------------------------------------------------------- /myapp/templates/tasks/create_task.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% block content %} 4 |

Create a new task

5 | 6 |
7 | {% csrf_token %} 8 | {{form.as_p}} 9 | 12 |
13 | 14 | {% endblock %} -------------------------------------------------------------------------------- /myapp/templates/tasks/tasks.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% block content %} 4 | 5 |

Tasks

6 | 7 | {% for task in tasks %} 8 | 9 |
10 |

{% if task.done == False %} ⏱ {% else %} ✅ {% endif %} {{task.title}}

11 | 12 |

{{task.description}}

13 |

Project: {{task.project.name}}

14 | 17 | 20 |
21 | 22 | {% endfor %} 23 | 24 | {% endblock %} -------------------------------------------------------------------------------- /myapp/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /myapp/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | urlpatterns = [ 5 | path('', views.index, name="index"), 6 | path('about/', views.about, name="about"), 7 | path('hello/', views.hello, name="hello"), 8 | path('projects/', views.projects, name="projects"), 9 | path('projects/', views.project_detail, name="project_detail"), 10 | path('tasks/', views.tasks, name="tasks"), 11 | path('create_task/', views.create_task, name="create_task"), 12 | path('create_project/', views.create_project, name="create_project"), 13 | ] -------------------------------------------------------------------------------- /myapp/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from .models import Project, Task 3 | from django.shortcuts import render, redirect, get_object_or_404 4 | from .forms import CreateNewTask, CreateNewProject 5 | 6 | # Create your views here. 7 | 8 | 9 | def index(request): 10 | title = 'Django Course!!' 11 | return render(request, 'index.html', { 12 | 'title': title 13 | }) 14 | 15 | 16 | def about(request): 17 | username = 'fazt' 18 | return render(request, 'about.html', { 19 | 'username': username 20 | }) 21 | 22 | 23 | def hello(request, username): 24 | return HttpResponse("

Hello %s

" % username) 25 | 26 | 27 | def projects(request): 28 | # projects = list(Project.objects.values()) 29 | projects = Project.objects.all() 30 | return render(request, 'projects/projects.html', { 31 | 'projects': projects 32 | }) 33 | 34 | 35 | def tasks(request): 36 | # task = Task.objects.get(title=tile) 37 | tasks = Task.objects.all() 38 | return render(request, 'tasks/tasks.html', { 39 | 'tasks': tasks 40 | }) 41 | 42 | 43 | def create_task(request): 44 | if request.method == 'GET': 45 | return render(request, 'tasks/create_task.html', { 46 | 'form': CreateNewTask() 47 | }) 48 | else: 49 | Task.objects.create( 50 | title=request.POST['title'], description=request.POST['description'], project_id=2) 51 | return redirect('tasks') 52 | 53 | 54 | def create_project(request): 55 | if request.method == 'GET': 56 | return render(request, 'projects/create_project.html', { 57 | 'form': CreateNewProject() 58 | }) 59 | else: 60 | Project.objects.create(name=request.POST["name"]) 61 | return redirect('projects') 62 | 63 | def project_detail(request, id): 64 | project = get_object_or_404(Project, id=id) 65 | tasks = Task.objects.filter(project_id=id) 66 | return render(request, 'projects/detail.html', { 67 | 'project': project, 68 | 'tasks': tasks 69 | }) -------------------------------------------------------------------------------- /mysite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fazt/django_course/a83c2825a77afb46829785268b3c37541c72608c/mysite/__init__.py -------------------------------------------------------------------------------- /mysite/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for mysite project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /mysite/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for mysite project. 3 | 4 | Generated by 'django-admin startproject' using Django 4.1. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/4.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | import os 15 | import dj_database_url 16 | 17 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 18 | BASE_DIR = Path(__file__).resolve().parent.parent 19 | 20 | 21 | # Quick-start development settings - unsuitable for production 22 | # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ 23 | 24 | # SECURITY WARNING: keep the secret key used in production secret! 25 | SECRET_KEY = os.environ.get('SECRET_KEY', default='your secret key') 26 | 27 | 28 | # SECURITY WARNING: don't run with debug turned on in production! 29 | DEBUG = 'RENDER' not in os.environ 30 | 31 | ALLOWED_HOSTS = [] 32 | 33 | RENDER_EXTERNAL_HOSTNAME = os.environ.get('RENDER_EXTERNAL_HOSTNAME') 34 | 35 | if RENDER_EXTERNAL_HOSTNAME: 36 | ALLOWED_HOSTS.append(RENDER_EXTERNAL_HOSTNAME) 37 | 38 | 39 | # Application definition 40 | 41 | INSTALLED_APPS = [ 42 | 'django.contrib.admin', 43 | 'django.contrib.auth', 44 | 'django.contrib.contenttypes', 45 | 'django.contrib.sessions', 46 | 'django.contrib.messages', 47 | 'django.contrib.staticfiles', 48 | 'myapp' 49 | ] 50 | 51 | MIDDLEWARE = [ 52 | 'django.middleware.security.SecurityMiddleware', 53 | 'whitenoise.middleware.WhiteNoiseMiddleware', 54 | 'django.contrib.sessions.middleware.SessionMiddleware', 55 | 'django.middleware.common.CommonMiddleware', 56 | 'django.middleware.csrf.CsrfViewMiddleware', 57 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 58 | 'django.contrib.messages.middleware.MessageMiddleware', 59 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 60 | ] 61 | 62 | ROOT_URLCONF = 'mysite.urls' 63 | 64 | TEMPLATES = [ 65 | { 66 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 67 | 'DIRS': [], 68 | 'APP_DIRS': True, 69 | 'OPTIONS': { 70 | 'context_processors': [ 71 | 'django.template.context_processors.debug', 72 | 'django.template.context_processors.request', 73 | 'django.contrib.auth.context_processors.auth', 74 | 'django.contrib.messages.context_processors.messages', 75 | ], 76 | }, 77 | }, 78 | ] 79 | 80 | WSGI_APPLICATION = 'mysite.wsgi.application' 81 | 82 | 83 | # Database 84 | # https://docs.djangoproject.com/en/4.1/ref/settings/#databases 85 | 86 | # DATABASE_URL 87 | 88 | DATABASES = { 89 | 'default': dj_database_url.config(default='sqlite:///db.sqlite3') 90 | } 91 | 92 | 93 | # Password validation 94 | # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators 95 | 96 | AUTH_PASSWORD_VALIDATORS = [ 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 99 | }, 100 | { 101 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 102 | }, 103 | { 104 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 105 | }, 106 | { 107 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 108 | }, 109 | ] 110 | 111 | 112 | # Internationalization 113 | # https://docs.djangoproject.com/en/4.1/topics/i18n/ 114 | 115 | LANGUAGE_CODE = 'en-us' 116 | 117 | TIME_ZONE = 'UTC' 118 | 119 | USE_I18N = True 120 | 121 | USE_TZ = True 122 | 123 | 124 | # Static files (CSS, JavaScript, Images) 125 | # https://docs.djangoproject.com/en/4.1/howto/static-files/ 126 | 127 | STATIC_URL = '/static/' 128 | 129 | if not DEBUG: 130 | STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') 131 | STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' 132 | 133 | # Default primary key field type 134 | # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field 135 | 136 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' 137 | -------------------------------------------------------------------------------- /mysite/urls.py: -------------------------------------------------------------------------------- 1 | """mysite URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/4.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | 19 | 20 | urlpatterns = [ 21 | path('admin/', admin.site.urls), 22 | path('', include('myapp.urls')) 23 | ] 24 | -------------------------------------------------------------------------------- /mysite/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for mysite project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.5.2 2 | autopep8==1.7.0 3 | Brotli==1.0.9 4 | dj-database-url==1.0.0 5 | Django==4.1.7 6 | gunicorn==20.1.0 7 | psycopg2-binary==2.9.3 8 | pycodestyle==2.9.1 9 | sqlparse==0.4.2 10 | toml==0.10.2 11 | tzdata==2022.2 12 | whitenoise==6.2.0 13 | --------------------------------------------------------------------------------