Erstellen Sie eine Todo-Anwendung mit Django. Teil 1

Hallo wieder. Im Vorfeld des Beginns des Python Web Developer- Kurses hat unser freiberuflicher Autor einige interessante Materialien vorbereitet, die wir gerne mit Ihnen teilen.




Django ist ein leistungsstarkes Framework für Webanwendungen. Ursprünglich wurde Django erstellt, um beispielsweise Nachrichten-Websites (oder andere Websites, die so schnell wie möglich erstellt werden müssen) schnell zu erstellen. Und nach nativem PHP lässt das Gefühl, dass Sie eine sehr schnelle Entwicklungsmaschine fahren, nicht nach. Um alle Funktionen für eine schnelle Entwicklung zu sehen, werden wir versuchen, eine einfache Todo-Anwendung zu erstellen.



Beginnen wir mit dem Wortlaut des kurzen t.z. Wir werden eine kleine Webanwendung mit Layout auf Bulma haben (ja, ich mag Bulma wirklich. Vielleicht werde ich eines Tages Bootstrap oder Picnic ausschalten, aber alles hat seine Zeit). Wir haben (bisher) keine Berechtigungen und der Benutzer kann entweder die Aufgabenkategorie oder die Aufgabenkarte erstellen, bearbeiten und löschen, die einer vom Benutzer erstellten Kategorie zugeordnet ist. Eine Todo-Karte oder -Kategorie kann gelöscht werden, indem Sie das Kontrollkästchen aktivieren und auf die Schaltfläche Löschen klicken.

Django-Kernkonzepte


Reden wir ein wenig über Django. Django implementiert das MVT-Architekturmuster (Model View Template), das sich geringfügig von dem bekannten MVC (Model View Controller) unterscheidet, auf dem Ruby on Rails und Laravel ausgeführt werden.

Modell Das Modell in Django beschreibt das Datenschema in der Datenbank. Mit Django ORM können Sie Felder und andere Datentypen unabhängig beschreiben und Migrationen durchführen, um die Entwicklung zu vereinfachen.

Ansicht In der Ansicht in Django legen Sie die grundlegende Logik und die Algorithmen der Anwendung fest, rufen verschiedene Daten aus der Datenbank ab oder bearbeiten sie. Die Ansicht basiert normalerweise auf den Anforderungs- / Antwortfunktionen. Die Antwort ist normalerweise HTTP-Umleitung, HTTP-Fehler (404), MimeTypes oder eine Art Muster.

VorlageVorlage in Django ist ein einfacher HTML-Code mit einer speziellen Vorlagensprache Django. DTL (Django Template Language) ist eine Sprache, mit der Sie den Inhalt einer Seite dynamisch ändern können (z. B. den Benutzernamen auf einer Seite abhängig vom Namen des autorisierten Benutzers).

Einstellungen Die Einstellungsdatei in Django, die alle Einstellungen für Ihre Webanwendung enthält. Es enthält einen geheimen Schlüssel, Vorlagenordner, Middlewares (die beispielsweise dafür verantwortlich sind, dass andere Benutzer Ihre privaten Alben nicht sehen können), eine Datenbankverbindung und vieles mehr.

URL Die Routing-Konfigurationsdatei entspricht in etwa Angular oder Laravel. Dadurch wird die Ansicht mit URL-Anforderungen verknüpft.

Administrator Seite Da Django ursprünglich für das Rapid Prototyping und die Bereitstellung von Nachrichtenseiten entwickelt wurde, ist das Admin-Panel standardmäßig enthalten.

Installieren Sie Python und Django


Kreativer Rückzug
( ) . Python . , . , .

Python-Versionen


Bis vor kurzem wurden zwei Hauptzweige von Python aktiv unterstützt und entwickelt: 2.7 und 3.x. Ich werde Version 3.7.3 in diesem Artikel verwenden, aber in der Tat ist es nicht so wichtig. Wenn Sie den Unterschied zwischen den beiden wirklich wissen wollen, gibt es ein spezielles Wiki . Andererseits macht es jetzt keinen Sinn, Python Version 2.7 zu verwenden - das Sprachupdate wurde um 2.7.17 gestoppt (wenn ich die Dokumentation auf der offiziellen Website richtig verstehe). Dies bedeutet, dass es sinnvoll ist, in Python 2.7.x geschriebene Projekte in einen neuen Zweig zu übertragen, aber das Schreiben neuer Projekte in zwei Versionen ist völlig sinnlos.

Python-Installation


Wenn Sie mit Mac oder Ubuntu arbeiten, ist Python wahrscheinlich bereits installiert, es gibt jedoch zwei Versionen. Python der dritten Version muss separat heruntergeladen werden und kann über Python3 in der Befehlszeile aufgerufen werden. In jedem Fall ist es am besten, die neueste Version hier herunterzuladen .

Erstellen Sie Ihre eigene virtuelle Umgebung


Tatsächlich können Sie mit der Entwicklung der ersten Anwendung auf Django beginnen, ohne eine eigene virtuelle Umgebung zu erstellen. Die Fähigkeit, eine virtuelle Umgebung zu erstellen, kann jedoch nützlich sein, wenn Sie beispielsweise eine Anwendung mit einer bestimmten Version der Bibliothek entwickeln und Bibliotheken nicht global installieren und Ihr System verunreinigen möchten.

Wie benutzt man Virtual Env?



1) Die einfachste Option. Sie können die wunderbare IDE von JET BRAINS PyCharm Community Edition hier herunterladen . Erstellen Sie nach der Installation von PyCharm ein neues Projekt, und Pycharm bietet Ihnen an, standardmäßig Virtual Env zu erstellen, in dem die erforderliche Version von Django installiert werden kann (oder standardmäßig die neueste Version, die zum Zeitpunkt des Schreibens dieses Artikels 3.0.2 vorhanden war):

pip3 install django

2) Eine etwas härtere Option:

Was ist, wenn Sie Django in einer virtuellen Umgebung ausführen möchten, beispielsweise in Ihrem Lieblingsordner?
Erstellen Sie zunächst einen Ordner, in dem wir Folgendes erstellen:

	mkdir myfirstdjango && cd myfirstdjango

Geben Sie als Nächstes die folgenden Befehle ein, um venv zu aktivieren, wobei django_env der Name unserer virtuellen Umgebung ist:

	python3 -m venv django_env
	source django_env/bin/activate

Außerdem wurde unsere virtuelle Umgebung aktiviert. Wir können die notwendigen Pakete liefern. In unserem Fall ist dies Django:

	pip3 install django

Wenn Sie die virtuelle Umgebung deaktivieren möchten, um zu Ihrem globalen Python zurückzukehren (zum Systemkontext zurückzukehren), geben Sie den folgenden Befehl ein:

    deactivate

Ich hoffe, wir haben die virtuelle Umgebung herausgefunden. Wenn Sie Probleme und zusätzliche Fragen haben, finden Sie hier und hier nützliche Links .

Das Projekt selbst erstellen


Angenommen, Sie wählen eine der Möglichkeiten, um Ihre eigene virtuelle Umgebung zu erstellen (oder tun sogar alles global, nun, niemand verbietet Ihnen dies). Nun gehen wir zum Projektordner und beginnen mit seiner Erstellung:

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

Nachdem Django die Startseite geöffnet hat, müssen Sie unsere todolist-Anwendung in der Hauptanwendung installieren. Öffnen settings.pySie unsere vorhandene Liste von Anwendungen und fügen Sie sie zu unserer vorhandenen Liste von Anwendungen hinzu:

INSTALLED_APPS = [
	# ,     ,     
    'todolist',
]

Der nächste Schritt besteht darin, die Anwendung mit der Datenbank zu verknüpfen. Wenn Sie nicht mit Datenbanken herumspielen möchten, sollten Sie die Standardlösung SQlite verwenden. Ich habe mich für PostgreSQL entschieden - es ist beliebt und klassisch mit Django verwandt. Außerdem möchten wir möglicherweise die Leistung der Anwendung steigern. Es gibt viele Anweisungen zur Installation von PostgreSQL auf allen Betriebssystemen. Ich entwickle für MacOS und habe mit einigen kleinen Tänzen mit einem Tamburin diese Datenbank installiert, indem ich Postgres.app von hier heruntergeladen habe . Für die Schnittstellen für die Datenbank habe ich hier Postico verwendetund eine Testversion für die Entwicklung der Anwendung ist für uns völlig ausreichend (obwohl Sie im Prinzip darauf verzichten können, da die gesamte Interaktion mit der Datenbank über die Webanwendung selbst und die Migration erfolgt). Außerdem musste ich psycopg2 in die virtuelle Umgebung des Projekts einfügen (ohne diesen Treiber funktioniert Ihre Anwendung nicht mit der Datenbank).

Als nächstes müssen Sie die Arbeit der Statik konfigurieren. Wir bearbeiten die Datei noch settings.py, jetzt fügen wir ganz am Ende Arbeiten mit Statik hinzu:

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'

Überprüfen Sie, ob sich das für die Statik verantwortliche Paket in der Liste INSTALLED_APPS befindet , damit Ihre Statik funktioniert :

django.contrib.staticfiles,falls ein Fehler auftritt.
Und als letztes in der Vorarbeit müssen wir noch die grundlegende Arbeit von url im Projekt konfigurieren:

	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"),
]

Ich habe eine Weiterleitung hinzugefügt, weil ich möchte, dass localhost von der Standardseite direkt zur Kategorie- Unterseite wechselt (also Gott bewahre, dass der Benutzer nicht verloren geht). Wir haben auch zweiseitiges Routing: Kategorien und Fälle.

Ich hoffe also, dass Ihre Anwendung nicht abstürzt. Als nächstes können wir endlich mit der Erstellung der Anwendung selbst fortfahren:

Erstellen eines Todo-Modells und von Kategorien


Als nächstes werden wir beginnen, ein Modell zu erstellen, das grundlegend mit unserer Datenbank interagiert. Um ein Modell zu erstellen, öffnen Sie die Datei models.pyin unserer ToDolist und beginnen Sie mit der Erstellung. Beginnen wir mit der Erstellung einer Kategorietabelle:

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__      

Fein! Ja, hier haben wir nur zwei Spalten in der Kategorietabelle: ID und Name. Als nächstes erstellen Sie eine Tabelle für unsere Angelegenheiten. Ich denke, aus den Kommentaren geht alles hervor:

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

Nachdem Ihr Modell fertig ist, müssen Sie Migrationen erstellen:

	python3 manage.py makemigrations

Führen Sie dann die Migrationen selbst aus:

	python3 manage.py migrate

Ansicht erstellen


Öffnen Sie die Datei view.pyin todolist und bearbeiten Sie sie. Fügen Sie zunächst die erforderlichen Importe hinzu und leiten Sie von der Haupt- zur Kategorie um:

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

Dann beginnen wir mit der Gründung unseres Geschäfts. Die Instanz des Falls enthält die Felder des Textes selbst, das Datum, bis zu dem der Fall abgeschlossen sein soll, die Kategorie des Falls und den kombinierten Inhalt:

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

Fügen Sie danach die Funktionen zum Hinzufügen und Löschen von Fällen hinzu:

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})

Das ist alles mit Zehen. Dann können wir zur Seite Kategorien gehen. Wir erstellen eine Funktion von Kategorien, in der wir auch die Funktion haben, eine Kategorie hinzuzufügen und zu löschen. Grundsätzlich wird es hier nichts Neues geben, wir werden auch die Möglichkeit haben, Folgendes hinzuzufügen und zu entfernen:

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})

Hier enden wir mit der Datei viewund können mit den Vorlagen fortfahren:

Arbeiten Sie mit Vorlagen


Wie Sie sich erinnern, habe ich bulma.cssdas Layout vereinfacht , um CSS nicht noch einmal zu schreiben . weil Unsere Kategorieseiten und Aufgaben werden sehr ähnlich sein. Ich habe drei Dateien erstellt:
base.htmlDie gleichen, die wir auf den Seiten haben, und in category.htmlwerden die todo.htmlUnterschiede gefunden:



Erstellen base.htmlund bearbeiten Sie sie:

<!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>

Als nächstes gehen wir zur Seite todo.htmlund 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 %}

Und category.html. Darin haben wir nicht viel, was sich ändert, es unterscheidet sich nicht grundlegend von 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 %}
 

Danke an alle! Das ist alles. Vielleicht ist das Layout irgendwo nicht perfekt oder es gibt andere Vorschläge zur Verbesserung der Anwendung. Ich warte auf alle im Kommentar. Traditionell einige nützliche Links:

  1. Django, 3
  2. ,
  3. PostgreSQL

All Articles