DjangoQuilla es una comunidad de desarrolladores de django, emprendedores y estudiantes y entusiastas de Python y Django.
Nos reunimos 1 vez al mes en ÁreaDos.
10. ORM de Django
11. Datos dinámicos en las plantillas
12. Plantillas
13. CSS
14. Extendiendo las plantillas
15. Extendiendo la app
16. Formularios
Imagen tomada de la presentación de David Whitton
Imágen tomada de devcode
mkdir tutorial-blog
cd tutorial-blog
# Para los que tienen instalado virtualenvwrapper
mkvirtualenv env-blog
workon env-blog
pip install django==1.9.7
django-admin startproject blogproject
# En el archivo settings.py
TIME_ZONE = 'America/Colombia'
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Correr en consola
python manage.py migrate
python manage.py runserver
La programación orientada a objetos consiste que en lugar de escribir todo como una aburrida secuencia de instrucciones de programación podemos modelar cosas y definir cómo interactúan con las demás.
Entonces ¿Qué es un objeto? Es un conjunto de propiedades y acciones.
Imagen tomada de wikibooks
Imagen tomada de csit
Gato
---------
color
edad
humor
dueño
ronronear()
rasguñar()
alimentarse(comida_de_gato)
ComidaDeGato
----------
sabor
python manage.py startapp blog
blogproject
├── blogproject
| __init__.py
| settings.py
| urls.py
| wsgi.py
├── manage.py
└── blog
├── migrations
| __init__.py
├── __init__.py
├── admin.py
├── models.py
├── tests.py
└── views.py
# Agrega la linea 'blog',
# En INSTALLED_APPS dentro del archivo settings.py
from django.db import models
from django.utils import timezone
class Post(models.Model):
author = models.ForeignKey('auth.User')
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(
default=timezone.now)
published_date = models.DateTimeField(
blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
# Luego creamos las tablas para el modelo
# Vamos a consola y corremos
python manage.py makemigrations blog
python manage.py migrate blog
# Vamos a abrir el archivo blog/admin.py
# y reemplazar su contenido con esto:
from django.contrib import admin
from .models import Post
admin.site.register(Post)
# Luego corremos en consola
python manage.py runserver
# Vamos a esta direccion en el navegador
# http://127.0.0.1:8000/admin/
Si quieres saber más información del administrador ve a la documentación de Django
# Para no repetir URLs creamos patrones de ellas usando
# expresiones regulares
^ denota el principio del texto
$ denota el final del texto
\d representa un dígito
+ indica que el ítem anterior debería ser repetido por lo menos una vez
() para encerrar una parte del patrón
# Ejemplo
http://www.mysite.com/post/12345/
# Su expresión regular sería
^post/(\d+)/$
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'', include('blog.urls')),
]
# Crea un nuevo archivo vacío en blog/urls.py
# y agrega estas 2 líneas
from django.conf.urls import include, url
from . import views
urlpatterns = [
url(r'^$', views.post_list),
]
# Abre la consola y ve a la carpeta del blogproject, luego escribe
git init
# Registra tu nombre y tu correo con los siguientes comandos
git config --global user.name "Tu Nombre"
git config --global user.email tu@correo.com
# Creamos un archivo llamado .gitignore con el sgte contenido
*.pyc
__pycache__
myvenv
db.sqlite3
/static
.DS_Store
# Luego
git status
git add --all .
git commit -m "Primer commit del taller con Django Barranquilla
# Vamos a github, creamos el repositorio y añadimos el remoto
git remote add origin https://github.com/<tu-usuario-github>/blogproject.git
git push -u origin master
# Abre el archivo blog/views.py
from django.shortcuts import render
def post_list(request):
return render(request, 'blog/post_list.html', {})
# Dentro de blog, crea una carpeta que se llame templates
# Dentro de templates, crea otra carpeta llamada blog
# Por ultimo crea un archivo llamado post_list.html
Aprende más de vistas con la documentación de django
HyperText significa que es un tipo de texto que soporta hipervínculos entre páginas. Markup significa que hemos tomado un documento y lo hemos marcado con código para decirle a algo (en este caso, un navegador) cómo interpretar la página. El código HTML está construido con etiquetas, cada una comenzando con < y terminando con >. Estas etiquetas de marcado son elementos.
<h1>Un título</h1> - para tu título más importante
<h2>Un subtítulo</h2> - para el título del siguiente nivel
<h3>Un subsubtítulo</h3> - ... y así hasta <h6>
<em>texto</em> - pone en cursiva tu texto
<strong>texto</strong> - pone en negrita tu texto
<br /> - un salto de línea (no puedes colocar nada dentro de br)
<a href="https://djangoquilla.com">link</a> - crea un vínculo
<ul><li>primer elemento</li><li>segundo elemento</li></ul> - crea una lista
<div></div> - define una sección de la página
<!DOCTYPE html>
<html>
<head>
<title>Django blog</title>
</head>
<body>
<div>
<h1><a href="">Django Blog</a></h1>
</div>
<div>
<p>publicado el: 14.06.2014, 12:14</p>
<h2><a href="">Mi primer artículo</a></h2>
<p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis
vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus,
tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa
justo sit amet risus.</p>
</div>
<div>
<p>publicado el: 14.06.2014, 12:14</p>
<h2><a href="">Mi segundo artículo</a></h2>
<p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis
vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus,
tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.</p>
</div>
</body>
</html>
# Recuerda hacer commit de los cambios importantes que hayas hecho
git status
git add --all .
git status
git commit -m "Cambie el HTML del sitio web"
git push
Curso sugerido de GIT básico
python manage.py shell
# Todos los objetos
Post.objects.all()
from blog.models import Post
# Crear objetos
Post.objects.create(author=me, title='Sample title', text='Test')
from django.contrib.auth.models import User
User.objects.all()
me = User.objects.get(username='Bruce')
Post.objects.create(author=me, title='Sample title', text='Test')
Post.objects.all()
# Añade 2 ó 3 posts más y avanza a la siguiente parte.
# Filtrar objetos
Post.objects.filter(author=me)
Post.objects.filter(title__contains='title')
# Publicando un post
from django.utils import timezone
Post.objects.filter(published_date__lte=timezone.now())
post = Post.objects.get(id=1)
post.publish()
# Finalmente nuestro archivo blog/views.py debería verse así:
from django.shortcuts import render
from django.utils import timezone
from .models import Post
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
Si quieres leer un poco más acerca de QuerySets en Django, puedes darle un vistazo a la documentación
# Variable
{{ posts }}
# Bucle for
{% for post in posts %}
{{ post }}
{% endfor %}
# Así debe quedar la plantilla post_list.html
<div>
<h1><a href="/">Django Blog</a></h1>
</div>
{% for post in posts %}
<div>
<p>publicado el: {{ post.published_date }}</p>
<h1><a href="">{{ post.title }}</a></h1>
<p>{{ post.text|linebreaks }}</p>
</div>
{% endfor %}
git status
git add --all .
git status
git commit -m "Modifiqué las plantillas para mostrar artículos de la base de datos"
git push
CSS (Cascading Style Sheets, que significa 'hojas de estilo en cascada') es un lenguaje utilizado para describir el aspecto y el formato de un sitio web escrito en lenguaje de marcado (como HTML). Trátalo como maquillaje para nuestra página web
# Agrega estas lineas dentro del <head> de tu archivo .html
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
# Crea una carpeta static dentro de la aplicación blog
# Crea una carpeta llamada css dentro de static y dentro de ella
# un archivo que se llave blog.css
# En tu archivo blog/static/css/blog.css deberías añadir el siguiente código
h1 a {
color: #FCA205;
}
# Abre el archivo post_list.html y añade esta linea justo al principio
{% load staticfiles %}
# Luego, entre el <head> y </head>, después de los enlaces a los archivos CSS de Bootstrap
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
# Añande a blog.css
body {
padding-left: 15px;
}
# Nueva tipografía al título. Añade en el head de post_list.html
<link href="http://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css">
# Ahora añadiremos la la familia de la fuente a nuestro CSS
h1 a {
color: #FCA205;
font-family: 'Lobster';
}
# Añadiremos una clase llamada page-header al div del encabezado
<div class="page-header">
<h1><a href="/">Django Girls Blog</a></h1>
</div>
# Añade la clase post al div que contiene una entrada del blog
<div class="post">
<p>published: {{ post.published_date }}</p>
<h1><a href="">{{ post.title }}</a></h1>
<p>{{ post.text|linebreaks }}</p>
</div>
.page-header {
background-color: #ff9400;
margin-top: 0;
padding: 20px 20px 20px 40px;
}
.page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active {
color: #ffffff;
font-size: 36pt;
text-decoration: none;
}
.content {
margin-left: 40px;
}
h1, h2, h3, h4 {
font-family: 'Lobster', cursive;
}
.date {
float: right;
color: #828282;
}
.save {
float: right;
}
.post-form textarea, .post-form input {
width: 100%;
}
.top-menu, .top-menu:hover, .top-menu:visited {
color: #ffffff;
float: right;
font-size: 26pt;
margin-right: 20px;
}
.post {
margin-bottom: 70px;
}
.post h1 a, .post h1 a:visited {
color: #000000;
}
# Agregamos unos div mas rodeando las etiquetas for, así:
<div class="content container">
<div class="row">
<div class="col-md-8">
{% for post in posts %}
<div class="post">
<div class="date">
{{ post.published_date }}
</div>
<h1><a href="">{{ post.title }}</a></h1>
<p>{{ post.text|linebreaks }}</p>
</div>
{% endfor %}
</div>
</div>
</div>
Recomendado el curso de HTMLy CSS de Codecademy
# Vamos a crear un archivo base.html en blog/templates/blog/
blog
└───templates
└───blog
base.html
post_list.html
# Luego ábrelo y copia todo lo que hay en post_list.html al archivo base.html
# Asegurate de pegar esta linea al inicio
{% load staticfiles %}
# Luego, en base.html reemplaza por completo tu <body> con esto:
<body>
<div class="page-header">
<h1><a href="/">Django Girls Blog</a></h1>
</div>
<div class="content container">
<div class="row">
<div class="col-md-8">
{% block content %}
{% endblock %}
</div>
</div>
</div>
</body>
# Abre tu archivo blog/templates/blog/post_list.html
# Elimina todo lo que no esté dentro del body
{% for post in posts %}
<div class="post">
<div class="date">
{{ post.published_date }}
</div>
<h1><a href="">{{ post.title }}</a></h1>
<p>{{ post.text|linebreaks }}</p>
</div>
{% endfor %}
# Agrega esta linea al inicio del archivo
{% extends 'blog/base.html' %}
# Coloca todo entre {% block content %} y {% endblock content %}
# Agregamos una etiqueta <a> alrededor del <h1>
<h1><a href="{% url 'blog.views.post_detail' pk=post.pk %}">{{ post.title }}</a></h1>
# Agregamos esta linea al archivo blog/urls.py
url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail),
# Crea la vista en el archivo blog/views.py
from django.shortcuts import render, get_object_or_404
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
# Crea la plantilla para post_detail.py
{% extends 'blog/base.html' %}
{% block content %}
<div class="post">
{% if post.published_date %}
<div class="date">
{{ post.published_date }}
</div>
{% endif %}
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaks }}</p>
</div>
{% endblock %}
git status
git add --all .
git status
git commit -m "Agregué la vista y la plantilla para el detalle de un artículo, así como el CSS del sitio."
git push
# Creamos el archivo forms.py dentro de la carpeta de blog
# Pega las sgtes lines en el archivo forms.py
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'text',)
# Abre base.html para agregar un enlace en el div llamado page-header
<a href="{% url 'blog.views.post_new' %}" class="top-menu">
<span class="glyphicon glyphicon-plus">
</span>
</a>
# Luego creamos una la nueva URL en urls.py
url(r'^post/new/$', views.post_new, name='post_new'),
# Abre el archivo blog/views.py
from .forms import PostForm
def post_new(request):
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
# Creamos el archivo post_edit.html
{% extends 'blog/base.html' %}
{% block content %}
<h1>New post</h1>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
{% endblock %}
# Abre tu navegador y prueba que aparezca el formulario
# Guardando desde el formulario
from .forms import PostForm
from django.shortcuts import redirect
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('blog.views.post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
# Comprueba que funcione. Debe crear un nuevo post y luego redireccionar
# a la pagina post_detail
# Editando desde el formulario
# Agrega esta url en tu archivo post_detail.html dentro del if post.published_date
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">
<span class="glyphicon glyphicon-pencil">
</span>
</a>
# Agrega la url en blog/urls.py
url(r'^post/(?P<pk>[0-9]+)/edit/$', views.post_edit, name='post_edit'),
#Abramos el archivo blog/views.py y añadamos al final esto
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('blog.views.post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
# Ahora mismo cualquiera puede crear un artículo. Hagamos que el botón de crear solo aparezca para ti
# Busca el enlace que crea nuevos post y coloca este bloque if alrededor de el
{% if user.is_authenticated %}
<a href="{% url 'post_new' %}" class="top-menu">
<span class="glyphicon glyphicon-plus">
</span>
</a>
{% endif %}
# Repite lo mismo para el enlace que permite editarlos
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">
<span class="glyphicon glyphicon-pencil">
</span>
</a>
{% endif %}
git status
git add --all .
git status
git commit -m "Agregué vistas para crear/editar artículos del blog dentro del sitio web."
git push