Buat aplikasi Todo menggunakan Django. Bagian 1

Halo lagi. Untuk mengantisipasi dimulainya kursus Pengembang Web Python, penulis lepas kami telah menyiapkan beberapa materi menarik yang akan kami bagikan dengan senang hati kepada Anda.




Django adalah kerangka kerja aplikasi web yang kuat. Awalnya, Django dibuat untuk membuat dengan cepat, misalnya, situs berita (atau situs lain yang perlu dibuat secepat mungkin). Dan setelah PHP asli, perasaan bahwa Anda mengendarai mesin pengembangan yang sangat cepat tidak pergi. Untuk melihat semua fitur-fiturnya untuk pengembangan cepat, kami akan mencoba membuat aplikasi Todo sederhana.



Mari kita mulai dengan kata-kata dari t.z. Kami akan memiliki aplikasi web kecil dengan tata letak di Bulma (ya, saya sangat suka Bulma. Mungkin suatu hari nanti saya akan mematikan Bootstrap atau Piknik, tetapi semuanya memiliki waktu). Kami (sejauh ini) tidak memiliki otorisasi dan pengguna dapat membuat, mengedit, dan menghapus kategori tugas atau kartu agenda, yang dikaitkan dengan kategori apa pun yang telah dibuat pengguna. Kartu atau kategori Todo dapat dihapus dengan mencentang kotak centang dan mengklik tombol hapus.

Konsep Inti Django


Mari kita bicara sedikit tentang Django. Django mengimplementasikan pola arsitektur MVT (Model View Template), yang sedikit berbeda dari MVC (Model View Controller) yang menjalankan Ruby on Rails dan Laravel.

Model Model dalam Django menggambarkan skema data dalam database. Dengan Django ORM, Anda dapat menggambarkan bidang dan jenis data lainnya secara mandiri, dan melakukan migrasi untuk menyederhanakan pengembangan.

Lihat Dalam tampilan di Django, Anda mengatur logika dasar dan algoritma aplikasi, mendapatkan berbagai data dari database atau memanipulasinya. Tampilan biasanya didasarkan pada fungsi permintaan \ respons. Respons biasanya HTTP redirect, HTTP error (404), MimeTypes atau semacam pola.

TemplatTemplat di Django adalah kode HTML sederhana dengan bahasa templat khusus Django. DTL (Bahasa Template Django) adalah bahasa yang dengannya Anda dapat mengubah konten halaman secara dinamis (misalnya, mengubah nama pengguna pada halaman, tergantung pada nama pengguna yang diotorisasi).

Pengaturan File pengaturan di Django, yang berisi semua pengaturan untuk aplikasi web Anda. Ini termasuk kunci rahasia, folder templat, middlewares (yang bertanggung jawab, misalnya, untuk mencegah pengguna lain melihat album pribadi Anda), koneksi database, dan banyak lagi.

Url File konfigurasi perutean hampir sama dengan di Angular atau Laravel. Ini mengaitkan tampilan dengan permintaan url.

Halaman Admin Karena Django awalnya dirancang untuk pembuatan prototipe dan penyebaran cepat situs berita, panel admin disertakan secara default.

Instal Python dan Django


Retret kreatif
( ) . Python . , . , .

Versi python


Sampai saat ini, dua cabang Python utama didukung dan dikembangkan secara aktif: 2.7 dan 3.x. Saya akan menggunakan versi 3.7.3 dalam artikel ini, tetapi sebenarnya itu tidak begitu penting. Jika Anda benar-benar ingin mengetahui perbedaan antara keduanya, ada wiki khusus . Di sisi lain, sekarang tidak masuk akal untuk menggunakan Python versi 2.7 - pembaruan bahasa berhenti di 2.7.17 (jika saya memahami dokumentasi di situs resmi dengan benar). Ini berarti masuk akal untuk mentransfer proyek yang ditulis dalam Python 2.7.x ke cabang baru, tetapi menulis yang baru dalam 2 versi sama sekali tidak ada gunanya.

Instalasi python


Jika Anda bekerja di Mac atau Ubuntu, Anda mungkin sudah menginstal Python, tetapi ada 2 versi. Python dari versi ketiga harus diunduh secara terpisah, dan Anda dapat menyebutnya di baris perintah melalui python3. Bagaimanapun, yang terbaik adalah mengunduh rilis terbaru di sini .

Buat lingkungan virtual Anda sendiri


Bahkan, Anda dapat mulai mengembangkan aplikasi pertama di Django tanpa membuat lingkungan virtual Anda sendiri, tetapi keterampilan menciptakan lingkungan virtual bisa berguna jika, misalnya, Anda mengembangkan aplikasi dengan versi perpustakaan tertentu dan tidak ingin menginstal perpustakaan secara global dan membuang sampah ke sistem Anda.

Jadi bagaimana Anda menggunakan env virtual?



1) Opsi termudah. Anda dapat mengunduh IDE yang luar biasa dari JET BRAINS Edisi Komunitas PyCharm dari sini . Setelah menginstal PyCharm, buat proyek baru, dan Pycharm akan menawarkan Anda untuk membuat Virtual Env secara default, di mana dimungkinkan untuk menginstal versi Django yang diinginkan (atau versi terbaru, yang pada saat penulisan artikel ini 3.0.2):

pip3 install django

2) Opsi yang sedikit lebih hardcore:

Bagaimana jika Anda ingin menjalankan Django di virtual env, misalnya, di folder favorit Anda?
Pertama, buat folder tempat kita akan membuat:

	mkdir myfirstdjango && cd myfirstdjango

Selanjutnya, masukkan perintah berikut untuk mengaktifkan venv, di mana django_env adalah nama lingkungan virtual kami:

	python3 -m venv django_env
	source django_env/bin/activate

Selanjutnya, lingkungan virtual kami diaktifkan. Kami dapat menyediakan paket yang diperlukan. Dalam kasus kami, ini adalah Django:

	pip3 install django

Jika Anda ingin mematikan lingkungan virtual untuk kembali ke global python Anda (kembali ke konteks sistem), masukkan perintah berikut:

    deactivate

Yah, saya harap kami menemukan lingkungan virtual. Jika Anda memiliki masalah dan pertanyaan tambahan, tautan bermanfaat dapat ditemukan di sini dan di sini .

Membuat proyek itu sendiri


Misalkan Anda memilih salah satu cara untuk menciptakan lingkungan virtual Anda sendiri (atau bahkan melakukan semuanya secara global, yah, tidak ada yang melarang Anda untuk melakukan ini). Sekarang kita pergi ke folder proyek dan memulai pembuatannya:

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

Jadi, setelah Django membuka halaman awal, Anda perlu menginstal aplikasi balita kami di aplikasi utama. Buka settings.pydan tambahkan ke daftar aplikasi kami yang ada saat ini, balita kami sendiri:

INSTALLED_APPS = [
	# ,     ,     
    'todolist',
]

Langkah selanjutnya adalah menghubungkan aplikasi dengan database. Jika basis data bukan yang Anda inginkan, Anda harus menggunakan solusi default, SQlite. Saya memutuskan untuk menggunakan PostgreSQL - ini populer dan secara klasik terkait dengan Django, di samping itu, maka kita mungkin ingin meningkatkan kinerja aplikasi. Ada banyak instruksi tentang cara menginstal PostgreSQL di semua sistem operasi. Saya mengembangkan untuk MacOS dan dengan beberapa tarian kecil dengan rebana, saya menginstal database ini dengan mengunduh Postgres.app dari sini . Adapun antarmuka untuk database, di sini saya menggunakan Posticodan versi percobaan untuk mengembangkan aplikasi sudah cukup bagi kami (walaupun, pada prinsipnya, Anda dapat melakukannya tanpa itu, karena semua interaksi kami dengan database akan dibangun melalui aplikasi web itu sendiri dan migrasi). Selain itu, saya harus meletakkan psycopg2 di lingkungan virtual proyek (tanpa driver ini, aplikasi Anda tidak akan berfungsi dengan database).

Selanjutnya, Anda perlu mengkonfigurasi karya statika. Kami masih mengedit file settings.py, sekarang di bagian paling akhir kami menambahkan kerja dengan statika:

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'

Agar statika Anda berfungsi, periksa apakah paket yang bertanggung jawab untuk statika ada di daftar INSTALLED_APPS :

django.contrib.staticfiles,jika terjadi kesalahan.
Dan hal terakhir dalam pekerjaan persiapan, kita masih perlu mengkonfigurasi pekerjaan dasar url dalam proyek:

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

Saya menambahkan arahan ulang karena saya ingin localhost langsung menuju ke subhalaman kategori dari halaman default (jadi Tuhan melarang pengguna tidak hilang). Kami juga memiliki perutean dua halaman: kategori dan kasus.

Jadi, saya harap aplikasi Anda tidak macet. Selanjutnya, kita akhirnya dapat beralih ke membuat aplikasi itu sendiri:

Membuat Model dan Kategori Todo


Selanjutnya, kita akan mulai membuat model yang secara fundamental akan berinteraksi dengan basis data kita. Untuk membuat model, buka file models.pydi balita kami dan mulai membuat. Mari kita mulai dengan membuat tabel kategori:

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__      

Baik! Ya, di sini kita hanya akan memiliki dua kolom dalam tabel Kategori: id dan nama. Selanjutnya, buat tabel untuk urusan kita. Saya pikir semuanya jelas dari komentar:

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

Setelah model Anda siap, Anda perlu membuat migrasi:

	python3 manage.py makemigrations

Dan kemudian jalankan migrasi sendiri:

	python3 manage.py migrate

Buat tampilan


Buka file view.pydalam daftar balita dan edit. Pertama, tambahkan impor yang diperlukan dan arahkan dari kategori utama ke:

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

Kemudian kami memulai penciptaan bisnis kami. Contoh kasus akan memiliki bidang teks itu sendiri, tanggal penyelesaian kasus, kategori kasus, dan konten gabungan:

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

Setelah itu, tambahkan fungsi menambah dan menghapus kasus:

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

Itu semua dengan jari kaki. Lalu kita bisa pergi ke halaman Kategori. Kami membuat fungsi kategori di mana kami juga akan memiliki fungsi menambah dan menghapus kategori. Pada dasarnya, tidak akan ada yang baru di sini, kami juga akan memiliki kemampuan untuk menambah dan menghapus:

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

Di sinilah kita berakhir dengan file viewdan dapat beralih ke templat:

Bekerja dengan templat


Seperti yang Anda ingat, agar tidak menulis css lagi, saya dulu bulma.cssmenyederhanakan tata letaknya. Karena halaman dan todo kategori kami akan sangat mirip, saya membuat tiga file:
base.htmlyang akan mencakup semua yang sama yang kita miliki di halaman, dan di dalam category.html, todo.htmlperbedaan akan ditemukan:



Buat base.htmldan edit:

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

Selanjutnya, kita akan pergi ke halaman todo.htmldan 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 %}

Dan category.html. Di dalamnya, kami tidak memiliki banyak perubahan, pada dasarnya tidak berbeda dengan 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 %}
 

Terimakasih untuk semua! Itu saja. Mungkin, di suatu tempat, tata letak tidak sempurna, atau ada saran lain untuk meningkatkan aplikasi, saya menunggu semua orang di komentar. Secara tradisi, beberapa tautan bermanfaat:

  1. Django, 3
  2. ,
  3. PostgreSQL

All Articles