Fecha de publicación: 2024-09-21
La cli de django se llama django-admin instalacion
Para generar un nuevo proyecto se utiliza el comando:
django-admin startproject <mysite>
Esto generara la siguiente estructura de archivos:
mysite/
es el propio paquete de Python para su proyecto.
Su nombre es el nombre del paquete de Python que usted tendrá que utilizar para importar
todo dentro de este (por ejemplo, mysite.urls).mysite/__init__.py
:
Un archivo vacío que le indica a Python que este directorio debería ser considerado como un
paquete Python.mysite/settings.py
:
Ajustes/configuración para este proyecto Django.
Django settings le indicará todo sobre cómo funciona la configuración.mysite/urls.py
:
Las declaraciones URL para este proyecto Django; una «tabla de contenidos» de su sitio
basado en Django.mysite/asgi.py
:
An entry-point for ASGI-compatible web servers to serve your project.mysite/wsgi.py
:
Un punto de entrada para que los servidores web compatibles con WSGI puedan servir su
proyecto.El archivo manage.py
contiene todos los comandos necesarios para nuestro proyecto con django.
Ahora, cada proyecto puede contar con distintas apps, para crear mas apps se cuenta con el comando:
python manage.py startapp <name>
Esto creara otro directorio nuevo que contiene nuestra nueva app. Este directorio contiene:
migrations
que contiene las migraciones de la base de datos para nuestros
modelosadmin.py
donde se encuentra los modelos para las cuentas de administradorapps.py
con la configuracion de la appmodels.py
con los modelos para la base de datosviews.py
con las vistastests.py
con los tests para nuestra appPara crear la vista podemos simplemente anadir una nueva vista en views.py
e importarla en
urls.py
(ubicada en el directorio de la nueva app, si no existe, crearlo).
La función include()
permite hacer referencia a otros URLconfs.
Cada vez que Django encuentra include()
corta cualquier parte de la URL que coincide hasta
ese punto y envía la cadena restante a la URLconf incluida para seguir el proceso.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("project.apps.todoApp.urls"))
]
La configuracion de la base de datos y el resto de la aplicacion se encuentra dentro del
archivo settings.py
.
Aqui podemos observar la configuracion del motor de bases de datos (por defecto sqlite3):
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
Django ya viene con distintas configuraciones por defecto que necesitan de realizar las migraciones.
Filosofía A model is the single, definitive source of information about your data. It contains the essential fields and behaviors of the data you’re storing. Django follows the DRY Principle. The goal is to define your data model in one place and automatically derive things from it.
This includes the migrations - unlike in Ruby On Rails, for example,
migrations are entirely derived from your models file
, and are essentially a history that Django can roll through to update your database schema to match your current models.
Example models:
# polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
def __str__(self):
return self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
Para indicar a django que nuestra aplicacion polls
esta instalada, asi podremos correr
nuestras migraciones y generar los modelos:
# poc/settings.py
INSTALLED_APPS = [
"polls.apps.PollsConfig",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
Ahora podemos generar las migraciones con:
python manage.py makemigrations polls
Luego podemos aplicar las migraciones con:
python manage.py migrate
Si queremos inspeccionar el sql generador por las migraciones:
$ python manage.py sqlmigrate polls 0001
Filosofía
Django automatiza completamente la creación de interfaces de sitios administrativos para los modelos.
Django fue escrito en un entorno de sala de redacción, con una separación muy clara entre «los editores de contenido» y el sitio «público». Los administradores del sitio utilizan el sistema para agregar noticias, eventos, resultados deportivos, etc., y ese contenido se muestra en el sitio público. Django resuelve el problema de crear una interfaz unificada para los administradores del sitio para editar el contenido.
Para crear una cuenta de administrador:
python manage.py createsuperuser
Para decirle django que un modelo cuenta con una interfaz dentro de la pantalla de administrador podemos usar lo siguiente:
# polls/admin.py
from django.contrib import admin
from .models import Question
admin.site.register(Question)
NOTA: para customizar el sitio de administrador visitar: https://docs.djangoproject.com/es/5.0/intro/tutorial07/
Para crear nuevas plantillas de las creamos en una carpeta templates/<app>
:
{% block content %}
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
{% endblock %}
Namespace de plantillas
Now we might be able to get away with putting our templates directly in polls/templates (rather than creating another polls subdirectory), but it would actually be a bad idea. Django will choose the first template it finds whose name matches, and if you had a template with the same name in a different application, Django would be unable to distinguish between them.
We need to be able to point Django at the right one, and the best way to ensure this is by namespacing them. That is, by putting those templates inside another directory named for the application itself.
Para utilizarla dentro de nuestra vista:
from django.template import loader
def index(request):
latest_question_list = Question.objects.order_by("-pub_date")[:5]
template = loader.get_template("polls/index.html")
context = {
"latest_question_list": latest_question_list,
}
return HttpResponse(template.render(context, request))
Un ejemplo de como estructurar un formulario en django (no olvidar el method
):
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
<legend><h1>{{ question.question_text }}</h1></legend>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>
Para Utilizar el form en nuestra vista:
from django.db.models import F
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from .models import Choice, Question
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST["choice"])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(
request,
"polls/detail.html",
{
"question": question,
"error_message": "You didn't select a choice.",
},
)
else:
selected_choice.votes = F("votes") + 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))
Ahora podemos crear la vista para la respuesta de redireccion luego de realizar el POST:
from django.shortcuts import get_object_or_404, render
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, "polls/results.html", {"question": question})
NOTA:
como forma de seguridad para evitar las peticiones de sitios cruzados Django utiliza el token
{% csrf_token %}
para determinar la validez de la peticion.
NOTA 2:
El metodo F()
es parte de las llamadas a base de datos de django, para mas detalles ver
aqui
NOTA 3:
Django cuenta con muchos
shorcuts para las peticiones
http, tales como get_object_or_404()
#Para las operaciones CRUD comunes es mas conveniente utilizar las vistas genericas, las cuales son autogeneradas por django mediante el modelo, por lo cual no hace falta escribir formularios repetitivos para realizar dichas operaciones.
Podemos modificar estas vistas de modo que utilizamos las vistas genericas:
from django.db.models import F
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from .models import Choice, Question
class IndexView(generic.ListView):
template_name = "polls/index.html"
context_object_name = "latest_question_list"
def get_queryset(self):
"""Return the last five published questions."""
return Question.objects.order_by("-pub_date")[:5]
class DetailView(generic.DetailView):
model = Question
template_name = "polls/detail.html"
class ResultsView(generic.DetailView):
model = Question
template_name = "polls/results.html"
def vote(request, question_id):
# same as above, no changes needed.
...
Solo debemos heredar de las vistas genericas, las cuales pueden ser:
View
Clase base para todas las vistas.TemplateView
Renderiza una plantilla.RedirectView
Redirige a una URL específica.ListView
Muestra una lista de objetos.DetailView
Muestra un detalle de un objeto específico.CreateView
Maneja la creación de un nuevo objeto.UpdateView
Maneja la actualización de un objeto existente.DeleteView
Maneja la eliminación de un objeto.FormView
Maneja la presentación y procesamiento de formularios.Para mas informacion https://docs.djangoproject.com/es/5.0/topics/class-based-views/
Dentro del archivo tests.py
podemos colocar nuestros tests:
import datetime
from django.test import TestCase
from django.utils import timezone
from .models import Question
class QuestionModelTests(TestCase):
def test_was_published_recently_with_future_question(self):
"""
was_published_recently() returns False for questions whose pub_date
is in the future.
"""
time = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=time)
self.assertIs(future_question.was_published_recently(), False)
Para correr nuestros tests:
python manage.py test polls
Django viene por defecto con la aplicacion django.contrib.staticfiles
la cual permite listar
los archivos estaticos, los cuales los definimos en la carpeta static/
, de la misma manera
que se hace con las templates.
Por ejemplo, creamos un archivo static/polls/style.css
y agregamos un archivo
static/polls/images/background.png
:
li a {
color: green;
}
body {
background: white url("images/background.png") no-repeat;
}
Para utilizar nuestro estilo:
{% load static %}
{% extends "base.html" %}
<link rel="stylesheet" href="{% static 'polls/style.css' %}">
La etiqueta de plantilla {% static %}
genera la URL absoluta de los archivos estáticos.
Advertencia
The {% static %} template tag is not available for use in static files which aren’t generated by Django, like your stylesheet. You should always use relative paths to link your static files between each other, because then you can change STATIC_URL (used by the static template tag to generate its URLs) without having to modify a bunch of paths in your static files as well.
Como nota final DJango es tremendamente extensible, lo cual se puede realizar facilmente para agregar aplicaciones de terceros, del mismo modo se puede empaquetar aplicaciones para reutilizarlas y realizar aplicaciones genericas. Para mas informacion ver:
Django Compressor es una herramienta para gestionar y optimizar archivos estáticos en proyectos Django.
Sus principales funciones son:
{% load compress %}
{% compress css %}
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
{% endcompress %}
{% compress js %}
<script src="{% static 'js/script.js' %}"></script>
{% endcompress %}
Para extender el sistema de autenticacion de Django, se puede utilizar:
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
Luego se modifica el archivo settings.py
y ya podemos utilizar el mecanismo de Django de
autenticacion:
AUTH_USER_MODEL = 'core.User'