Créez une application Todo à l'aide de Django. Partie 1

Rebonjour. En prévision du début du cours de développeur Web Python, notre rédacteur indépendant a préparé du matériel intéressant que nous sommes heureux de partager avec vous.




Django est un puissant cadre d'application Web. Initialement, Django a été créé afin de créer rapidement, par exemple, des sites d'actualités (ou d'autres sites qui doivent être créés le plus rapidement possible). Et après PHP natif, le sentiment que vous pilotez une machine de développement très rapide ne disparaît pas. Pour voir toutes ses fonctionnalités pour un développement rapide, nous allons essayer de créer une application Todo simple.



Commençons par le libellé du court t.z. Nous aurons une petite application web avec une mise en page sur Bulma (oui, j'aime vraiment Bulma. Peut-être qu'un jour je désactiverai Bootstrap ou Picnic, mais tout a son heure). Jusqu'à présent, nous n'avons pas d'autorisations et l'utilisateur peut créer, modifier et supprimer la catégorie de tâches ou la carte de tâches, qui est associée à toute catégorie créée par l'utilisateur. Une carte ou une catégorie Todo peut être supprimée en cochant la case et en cliquant sur le bouton Supprimer.

Django Core Concepts


Parlons un peu de Django. Django implémente le modèle architectural MVT (Model View Template), qui est légèrement différent du MVC (Model View Controller) familier qui exécute Ruby on Rails et Laravel.

Modèle Le modèle dans Django décrit le schéma de données dans la base de données. Avec Django ORM, vous pouvez décrire indépendamment des champs et tout autre type de données et effectuer des migrations pour simplifier le développement.

Vue Dans la vue de Django, vous définissez la logique et les algorithmes de base de l'application, récupérez diverses données de la base de données ou les manipulez. La vue est généralement basée sur les fonctions demande \ réponse. La réponse est généralement une redirection HTTP, une erreur HTTP (404), des MimeTypes ou une sorte de modèle.

ModèleLe modèle dans Django est un simple code HTML avec un langage de modèle spécial Django. DTL (Django Template Language) est une langue avec laquelle vous pouvez modifier dynamiquement le contenu d'une page (par exemple, changer le nom d'utilisateur sur une page, selon le nom de l'utilisateur autorisé).

Paramètres Le fichier de paramètres de Django, qui contient tous les paramètres de votre application Web. Il comprend une clé secrète, des dossiers de modèles, des middlewares (qui sont chargés, par exemple, d'empêcher les autres utilisateurs de voir vos albums privés), une connexion à la base de données et bien plus encore.

Url Le fichier de configuration de routage est à peu près le même que dans Angular ou Laravel. Cela associe la vue aux demandes d'URL.

Page Admin Étant donné que Django a été initialement conçu pour le prototypage et le déploiement rapides de sites d'actualités, le panneau d'administration est inclus par défaut.

Installer Python et Django


Retraite créative
( ) . Python . , . , .

Versions Python


Jusqu'à récemment, deux branches principales de Python étaient activement prises en charge et développées: 2.7 et 3.x. J'utiliserai la version 3.7.3 dans cet article, mais en fait ce n'est pas si important. Si vous voulez vraiment connaître la différence entre les deux, il existe un wiki spécial . D'un autre côté, maintenant cela n'a plus de sens d'utiliser Python version 2.7 - la mise à jour du langage s'est arrêtée à 2.7.17 (si je comprends bien la documentation sur le site officiel). Cela signifie qu'il est logique de transférer des projets écrits en Python 2.7.x vers une nouvelle branche, mais en écrire de nouveaux en 2 versions est complètement inutile.

Installation de Python


Si vous travaillez sur Mac ou Ubuntu, vous avez probablement déjà installé Python, mais il existe 2 versions. Python de la troisième version devra être téléchargé séparément, et vous pouvez l'appeler sur la ligne de commande via python3. Dans tous les cas, il est préférable de télécharger la dernière version ici .

Créez votre propre environnement virtuel


En fait, vous pouvez commencer à développer la première application sur Django sans créer votre propre environnement virtuel, mais l'habileté de créer un environnement virtuel peut être utile si, par exemple, vous développez une application avec une version spécifique de la bibliothèque et ne souhaitez pas installer les bibliothèques globalement et salir votre système.

Alors, comment utilisez-vous virtual env?



1) L'option la plus simple. Vous pouvez télécharger le merveilleux IDE de JET BRAINS PyCharm Community Edition à partir d'ici . Après avoir installé PyCharm, créez un nouveau projet, et Pycharm vous proposera de créer Virtual Env par défaut, dans lequel il sera possible d'installer la version requise de Django (ou par défaut la dernière, qui au moment de la rédaction de cet article était 3.0.2):

pip3 install django

2) Une option un peu plus hardcore:

que faire si vous voulez exécuter Django en env virtuel, par exemple, dans votre dossier préféré?
Créez d'abord un dossier dans lequel nous allons créer:

	mkdir myfirstdjango && cd myfirstdjango

Ensuite, entrez les commandes suivantes pour activer venv, oĂą django_env est le nom de notre environnement virtuel:

	python3 -m venv django_env
	source django_env/bin/activate

De plus, notre environnement virtuel a été activé. Nous pouvons fournir les colis nécessaires. Dans notre cas, c'est Django:

	pip3 install django

Si vous souhaitez désactiver l'environnement virtuel afin de revenir à votre python global (retour au contexte système), entrez la commande suivante:

    deactivate

Eh bien, j'espère que nous avons compris l'environnement virtuel. Si vous avez des problèmes et des questions supplémentaires, des liens utiles peuvent être trouvés ici et ici .

Création du projet lui-même


Supposons que vous choisissiez l'une des façons de créer votre propre environnement virtuel (ou même que vous fassiez tout à l'échelle mondiale, eh bien, personne ne vous interdit de le faire). Maintenant, nous allons dans le dossier du projet et commençons sa création:

    django-admin startproject todo  #    
    cd todo #  
    python manage.py startapp todolist  #   todolist
	python3 manage.py runserver 8100 #      , 8000  
 

Donc, après que Django a ouvert la page de démarrage, vous devez installer notre application todolist dans l'application principale. Ouvrez settings.pyet ajoutez à notre liste existante d'applications notre propre todolist:

INSTALLED_APPS = [
	# ,     ,     
    'todolist',
]

L'étape suivante consiste à lier l'application à la base de données. Si les bases de données ne sont pas celles avec lesquelles vous voulez jouer, vous devez utiliser la solution par défaut, SQlite. J'ai décidé d'utiliser PostgreSQL - il est populaire et lié classiquement à Django, en plus, alors nous pouvons vouloir augmenter les performances de l'application. Il existe de nombreuses instructions sur la façon d'installer PostgreSQL sur tous les systèmes d'exploitation. Je développe pour MacOS et avec quelques petites danses avec un tambourin, j'ai installé cette base de données en téléchargeant Postgres.app à partir d'ici . Quant aux interfaces pour la base de données, ici j'ai utilisé Posticoet une version d'essai pour développer l'application nous suffit (même si, en principe, vous pouvez vous en passer, car toute notre interaction avec la base de données se fera via l'application web elle-même et la migration). De plus, j'ai dû mettre psycopg2 dans l'environnement virtuel du projet (sans ce pilote, votre application ne fonctionnera pas avec la base de données).

Ensuite, vous devez configurer le travail de la statique. Nous Ă©ditons toujours le fichier settings.py, maintenant Ă  la toute fin nous ajoutons du travail avec la statique:

STATIC_URL = '/static/'
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'

Pour que votre statique fonctionne, vérifiez que le package responsable de la statique était dans la liste INSTALLED_APPS :

django.contrib.staticfiles,en cas d'erreur.
Et la dernière chose dans le travail préparatoire, nous devons encore configurer le travail de base de l'url dans le projet:

	from django.conf.urls import url
	from django.contrib import admin
	from todolist.views import todo
	from todolist.views import category
	from todolist.views import redirect_view
 
urlpatterns = [
	url(r'$^', redirect_view ),
	url(r'^admin/', admin.site.urls),
	url(r'^todo/', todo, name="TodoList"),
	url(r'^category/', category, name="Category"),
]

J'ai ajouté une redirection parce que je veux que localhost accède directement à la sous-page de catégorie à partir de la page par défaut (donc Dieu ne plaise pas à l'utilisateur n'est pas perdu). Nous avons également un routage de deux pages: catégories et cas.

J'espère donc que votre application ne plante pas. Ensuite, nous pouvons enfin passer à la création de l'application elle-même:

Création d'un modèle et de catégories Todo


Ensuite, nous allons commencer à créer un modèle qui interagira fondamentalement avec notre base de données. Pour créer un modèle, ouvrez le fichier models.pydans notre liste de tâches et commencez à créer. Commençons par créer un tableau des catégories:

from django.utils import timezone #     todo
from django.db import models
 
class Category(models.Model): #     models.Model
    name = models.CharField(max_length=100) #varchar.    
	class Meta:
    	verbose_name = ("Category") #   
    	verbose_name_plural = ("Categories")  #    
    def __str__(self):
        return self.name  # __str__      

Bien! Oui, ici, nous n'aurons que deux colonnes dans la table Catégories: id et nom. Ensuite, créez une table pour nos affaires. Je pense que tout ressort clairement des commentaires:

class TodoList(models.Model):
	title = models.CharField(max_length=250)
	content = models.TextField(blank=True) # 
	created = models.DateField(default=timezone.now().strftime("%Y-%m-%d")) #  
	due_date = models.DateField(default=timezone.now().strftime("%Y-%m-%d")) #      
	category = models.ForeignKey(Category, default="general",on_delete=models.PROTECT) # foreignkey          
	class Meta: #       
        ordering = ["-created"] #     
	def __str__(self):
    	return self.title

Une fois votre modèle prêt, vous devez créer des migrations:

	python3 manage.py makemigrations

Et puis exécutez les migrations elles-mêmes:

	python3 manage.py migrate

Créer une vue


Ouvrez le fichier view.pydans todolist et modifiez-le. Tout d'abord, ajoutez les importations nécessaires et redirigez du principal vers la catégorie:

from django.shortcuts import render, redirect #      
from django.http import HttpResponse
from .models import TodoList, Category #   
 
def redirect_view(request):
	return redirect("/category") #     

Ensuite, nous commençons la création de notre entreprise. L'instance du cas aura les champs du texte lui-même, la date à laquelle le cas doit être complété, la catégorie du cas et le contenu combiné:

def todo(request):
	todos = TodoList.objects.all() #   todo   
    categories = Category.objects.all() #    

Après cela, ajoutez les fonctions d'ajout et de suppression de cas:

if request.method == "POST": #     POST
	if "Add" in request.POST: #   todo
    	title = request.POST["description"] # 
    	date = str(request.POST["date"]) #,      
        category = request.POST["category_select"] #,      .
        content = title + " -- " + date + " " + category #   
    	Todo = TodoList(title=title, content=content, due_date=date, category=Category.objects.get(name=category))
    	Todo.save() #   
        return redirect("/todo") #   (        )
    if "Delete" in request.POST: #     
        checkedlist = request.POST.getlist('checkedbox') #    ,    
        for i in range(len(checkedlist)): # -    
            todo = TodoList.objects.filter(id=int(checkedlist[i]))
        	todo.delete() # 
return render(request, "todo.html", {"todos": todos, "categories": categories})

C'est tout avec les orteils. Ensuite, nous pouvons aller à la page Catégories. Nous créons une fonction de catégories dans laquelle nous aurons également la fonction d'ajouter et de supprimer une catégorie. Fondamentalement, il n'y aura rien de nouveau ici, nous aurons également la possibilité d'ajouter et de supprimer:

def category(request):
	categories = Category.objects.all()  #   
	if request.method == "POST": #    POST
    	if "Add" in request.POST: #  
        	name = request.POST["name"] #  
        	category = Category(name=name) #     
            category.save() #   
        	return redirect("/category")
    	if "Delete" in request.POST: #    
            check = request.POST.getlist('check') #       todo,       
            for i in range(len(check)):
            	try:
                	ateg = Category.objects.filter(id=int(check[i]))
                	ateg.delete()   # 
            	except BaseException: #        ,       
                	return HttpResponse('<h1>     )</h1>')
	return render(request, "category.html", {"categories": categories})

C'est là que nous terminons avec le fichier viewet pouvons passer aux modèles:

Travailler avec des modèles


Comme vous vous en souvenez, pour ne pas réécrire css, je bulma.csssimplifiais la mise en page. Parce que nos pages de catégories et nos tâches seront très similaires, j'ai créé trois fichiers:
base.htmlqui comprendront tous les mêmes que ceux que nous avons sur les pages, et dans category.html, les todo.htmldifférences seront localisées:



Créez-le base.htmlet éditez-le:

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="UTF-8">
  <title>   </title>
  {% load static %}
	<link rel="shortcut icon" type="image/png" href="{% static 'favicon.png' %}"/>
   <link rel="stylesheet" type="text/css" href="{% static 'bulma.min.css' %}">
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<div django-app="TaskManager">
	<nav class ="navbar is-success" role="navigation" aria-label="main navigation">
     	<div class="navbar-menu ">
        	<div class="navbar-start">
        	<a class="navbar-item" href="../category"> </a>
        	<a class="navbar-item" href="../todo">   </a>
        	</div>
         </div>
	</nav>
<!--               -->
{% block content %}
{% endblock %}
</div>
</body>
</html>

Ensuite, nous irons Ă  la page todo.htmlet category.html:

Tudushka:

{% extends 'base.html' %}
{% block content %}
<div class="columns has-background-black-ter is-centered has-text-white-bis" style="min-height:101vh;">
	<!--        hero,     inline-css -->
	<div class="column is-half">
    	<h1 class="is-size-3 has-text-centered">   </h1>
    	<form action="" method="post">
        	{% csrf_token %}
        	<!-- csrf      -->
            <div class="field has-text-centered">
            	<label for="description" class="label has-text-white-bis"> </label>
            	<div class="control">
             	   <input type="text" id="description" class="input" placeholder="  ?"
                    	name="description" required>
            	</div>
        	</div>
        	<div class="columns">
            	<div class="column">
                	<label for="category"></label>
                	<div class="control">
                    	<div class="select">
                        	<select id="category" class="select" name="category_select" required>
                            	<!--  required,       .    -->
                            	<option class="disabled" value="">  </option>
                    	        {% for category in categories %}
 	                           <option class="" value="{{ category.name }}" name="{{ category.name }}">
                                    {{ category.name }}</option>
                            	{% endfor %}
                        	</select>
    	                </div>
                	</div>
            	</div>
            	<div class="column">
                	<label for="dueDate"> </label>
                	<input type="date" id="dueDate" class="input calendar" name="date" required>
            	</div>
        	</div>
        	<div class="column">
            	<div class="field">
                	<button class="button is-primary" name="Add" type="submit">
                    	<span class="icon is-small">
                        	<i class="fa fa-plus"></i>
                    	</span>
                    	<span> </span>
                	</button>
             	   <button class="button is-link" name="Delete" formnovalidate="" type="submit">
                    	<span class="icon is-small">
                        	<i class="fa fa-trash-o"></i>
                    	</span>
                    	<span>
                        	 
                    	</span>
                	</button>
            	</div>
        	</div>
        	<div class="list is-hoverable">
            	{% for todo in todos %}
            	<!--   django- for loop -->
            	<div class="list-item">
                	<label class="checkbox">
                    	<input type="checkbox" class=" checkbox" name="checkedbox" value="{{ todo.id }}">
                    	<span class="complete-">{{ todo.title }}</span>
                	</label>
                	<span class=" category-{{ todo.category }} has-text-info">{{ todo.category }}</span>
                	<strong class="is-pulled-right"><i class="fa fa-calendar"></i>{{ todo.created }} -
                    	{{ todo.due_date }}</strong>
            	</div>
            	{% endfor %}
        	</div>
    	</form>
	</div>
</div>
{% endblock %}

Et category.html. Dans ce document, nous n'avons pas beaucoup de changements, il ne diffère pas fondamentalement de todo.html:

{% extends 'base.html' %}
{% block content %}
<div class="columns has-background-link has-text-white is-centered" style="min-height: 101vh;">
	<div class="column is-half">
    	<h1 class="is-size-4 has-text-centered">    </h1>
    	<form action="" method="post">
        	{% csrf_token %}
        	<!-- csrf      -->
            <div class="field has-text-centered">
            	<label for="description" class="label has-text-white-bis">   </label>
            	<div class="control">
     	           <input type="text" id="description" class="input" placeholder="    ?"
                    	name="name" required>
            	</div>
            	<div class="field">
                	<button class="button is-primary" name="Add" type="submit">
                    	<span class="icon is-small">
                        	<i class="fa fa-plus"></i>
                    	</span>
                    	<span> </span>
                	</button>
                	<button class="button is-danger" name="Delete" formnovalidate="" type="submit">
                    	<span class="icon is-small">
           	             <i class="fa fa-trash-o"></i>
                    	</span>
	                    <span>   </span>
                	</button>
            	</div>
            </div>
 
            <!--  c   -->
            <div class="list is-hoverable">
            	{% for category in categories %}
            	<div class="list-item">
                	<label class="checkbox">
                    	<input type="checkbox" class="checkbox" name="check" value="{{category.id}}">
                    	<span class="complete-">{{ category.name }}</span>
                	</label>
            	</div>
            	{% endfor %}
 
        	</div>
    	</form>
	</div>
    {% endblock %}
 

Merci à tous! C'est tout. Peut-être, quelque part, la mise en page n'est pas parfaite, ou il y a d'autres suggestions pour améliorer l'application, j'attends tout le monde dans le commentaire. Par tradition, quelques liens utiles:

  1. Django, 3
  2. ,
  3. PostgreSQL

All Articles