¿Que es Django?
Django es un framework web de alto nivel en Python que fomenta el desarrollo rapido y el diseno limpio y pragmatico. A menudo llamado el framework con "baterias incluidas", Django proporciona un ORM, panel de administracion, autenticacion, enrutamiento de URLs, motor de plantillas, manejo de formularios y caracteristicas de seguridad listos para usar. Impulsa sitios como Instagram, Pinterest y Mozilla.
Django vs FastAPI
- Django: Full-stack, baterias incluidas, excelente para aplicaciones web tradicionales con HTML renderizado en servidor, paneles de admin y modelos de datos complejos
- FastAPI: Enfocado en APIs, ligero, mejor para construir APIs REST/GraphQL consumidas por frameworks frontend o aplicaciones moviles
Primeros pasos
# Install Django
# pip install django
# Create a new project
# django-admin startproject myproject
# cd myproject
# Create an app within the project
# python manage.py startapp blog
# Project structure:
# myproject/
# manage.py # CLI tool
# myproject/
# __init__.py
# settings.py # Configuration
# urls.py # Root URL config
# wsgi.py # WSGI entry point
# blog/
# __init__.py
# admin.py # Admin panel config
# apps.py # App config
# models.py # Database models
# views.py # Request handlers
# urls.py # App URL config (create this)
# templates/ # HTML templates (create this)
# tests.py # Tests
# Run development server
# python manage.py runserver
Modelos (ORM)
# blog/models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100, unique=True)
slug = models.SlugField(unique=True)
description = models.TextField(blank=True)
class Meta:
verbose_name_plural = "categories"
ordering = ["name"]
def __str__(self):
return self.name
class Post(models.Model):
class Status(models.TextChoices):
DRAFT = "draft", "Draft"
PUBLISHED = "published", "Published"
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="posts")
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
body = models.TextField()
status = models.CharField(max_length=10, choices=Status.choices, default=Status.DRAFT)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
published_at = models.DateTimeField(null=True, blank=True)
class Meta:
ordering = ["-created_at"]
def __str__(self):
return self.title
def publish(self):
self.status = self.Status.PUBLISHED
self.published_at = timezone.now()
self.save()
# Apply migrations
# python manage.py makemigrations
# python manage.py migrate
Vistas y URLs
# blog/views.py
from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView, CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Post, Category
# Function-based view
def post_list(request):
posts = Post.objects.filter(status="published").select_related("author", "category")
categories = Category.objects.all()
context = {"posts": posts, "categories": categories}
return render(request, "blog/post_list.html", context)
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug, status="published")
return render(request, "blog/post_detail.html", {"post": post})
# Class-based views (more reusable)
class PostListView(ListView):
model = Post
template_name = "blog/post_list.html"
context_object_name = "posts"
paginate_by = 10
def get_queryset(self):
return Post.objects.filter(status="published").select_related("author")
class PostDetailView(DetailView):
model = Post
template_name = "blog/post_detail.html"
context_object_name = "post"
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ["title", "slug", "category", "body"]
template_name = "blog/post_form.html"
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
# blog/urls.py
from django.urls import path
from . import views
app_name = "blog"
urlpatterns = [
path("", views.PostListView.as_view(), name="post_list"),
path("/", views.PostDetailView.as_view(), name="post_detail"),
path("new/", views.PostCreateView.as_view(), name="post_create"),
]
# myproject/urls.py
# from django.urls import path, include
# urlpatterns = [
# path("admin/", admin.site.urls),
# path("blog/", include("blog.urls")),
# ]
Panel de administracion
# blog/admin.py
from django.contrib import admin
from .models import Post, Category
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ["name", "slug"]
prepopulated_fields = {"slug": ("name",)}
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ["title", "author", "category", "status", "created_at"]
list_filter = ["status", "category", "created_at"]
search_fields = ["title", "body"]
prepopulated_fields = {"slug": ("title",)}
date_hierarchy = "created_at"
ordering = ["-created_at"]
actions = ["make_published"]
@admin.action(description="Mark selected posts as published")
def make_published(self, request, queryset):
queryset.update(status="published")
# Create superuser: python manage.py createsuperuser
# Admin panel at: http://localhost:8000/admin/
Puntos clave
- Baterias incluidas: Django te da ORM, admin, auth y mas listos para usar
- ORM poderoso: Define modelos como clases Python, Django maneja el SQL
- CBVs para reutilizacion: Usa vistas basadas en clases para patrones comunes
- Panel de administracion: Obtén una interfaz de admin gratuita registrando tus modelos