Crie um aplicativo Todo usando o Django. Parte 1

Olá de novo. Antecipando o início do curso Python Web Developer, nosso escritor freelancer preparou algum material interessante que estamos felizes em compartilhar com você.




O Django é uma poderosa estrutura de aplicativos da web. Inicialmente, o Django foi criado para criar rapidamente, por exemplo, sites de notícias (ou outros sites que precisam ser criados o mais rápido possível). E depois do PHP nativo, a sensação de que você está montando uma máquina de desenvolvimento muito rápida não deixa. Para ver todos os seus recursos para desenvolvimento rápido, tentaremos criar um aplicativo Todo simples.



Vamos começar com o texto do t.z. Teremos um pequeno aplicativo da Web com layout no Bulma (sim, eu realmente gosto do Bulma. Talvez um dia eu desligue no Bootstrap ou no Picnic, mas tudo tem seu tempo). Até o momento, não temos autorizações e o usuário pode criar, editar e excluir uma categoria de tarefas ou um cartão de tarefas, associado a qualquer categoria que o usuário criou. Um cartão ou categoria Todo pode ser excluído marcando a caixa de seleção e clicando no botão excluir.

Conceitos básicos do Django


Vamos falar um pouco sobre o Django. O Django implementa o padrão arquitetural MVT (Model View Template), que é um pouco diferente do familiar MVC (Model View Controller) que executa o Ruby on Rails e o Laravel.

Modelo O modelo no Django descreve o esquema de dados no banco de dados. Com o Django ORM, você pode descrever independentemente os campos e quaisquer outros tipos de dados e fazer migrações para simplificar o desenvolvimento.

Visão Na visão do Django, você define a lógica e os algoritmos básicos do aplicativo, obtém vários dados do banco de dados ou os manipula. A visualização geralmente é baseada nas funções request \ response. A resposta geralmente é redirecionamento HTTP, erro HTTP (404), MimeTypes ou algum tipo de padrão.

ModeloTemplate no Django é um código HTML simples com uma linguagem de template especial Django. DTL (Django Template Language) é um idioma com o qual você pode alterar dinamicamente o conteúdo de uma página (por exemplo, alterar o nome de usuário em uma página, dependendo do nome do usuário autorizado).

Configurações O arquivo de configurações no Django, que contém todas as configurações para seu aplicativo web. Ele inclui uma chave secreta, pastas de modelos, middlewares (que são responsáveis, por exemplo, por impedir que outros usuários vejam seus álbuns particulares), uma conexão com o banco de dados e muito mais.

URL O arquivo de configuração de roteamento é praticamente o mesmo que em Angular ou Laravel. Isso associa a exibição a solicitações de URL.

Página do administrador Como o Django foi originalmente projetado para prototipagem rápida e implantação de sites de notícias, o painel de administração é incluído por padrão.

Instale o Python e o Django


Retiro criativo
( ) . Python . , . , .

Versões Python


Até recentemente, dois ramos principais do Python eram ativamente suportados e desenvolvidos: 2.7 e 3.x. Usarei a versão 3.7.3 neste artigo, mas na verdade não é tão importante. Se você realmente quer saber a diferença entre os dois, existe um wiki especial . Por outro lado, agora não faz sentido usar o Python versão 2.7 - a atualização do idioma parou em 2.7.17 (se eu entendi a documentação no site oficial corretamente). Isso significa que faz sentido transferir projetos escritos em Python 2.7.x para um novo ramo, mas escrever novos em 2 versões é completamente inútil.

Instalação em Python


Se você estiver trabalhando no Mac ou Ubuntu, provavelmente já possui o Python instalado, mas existem 2 versões. O Python da terceira versão terá que ser baixado separadamente, e você pode chamá-lo na linha de comando através do python3. De qualquer forma, é melhor fazer o download da versão mais recente aqui .

Crie seu próprio ambiente virtual


De fato, você pode começar a desenvolver o primeiro aplicativo no Django sem criar seu próprio ambiente virtual, mas a habilidade de criar um ambiente virtual pode ser útil se, por exemplo, você desenvolver um aplicativo com uma versão específica da biblioteca e não desejar instalar bibliotecas globalmente e desarrumar seu sistema.

Então, como você usa o ambiente virtual?



1) A opção mais fácil. Você pode baixar o maravilhoso IDE do JET BRAINS PyCharm Community Edition aqui . Depois de instalar o PyCharm, crie um novo projeto, e o Pycharm oferecerá a você para criar o Virtual Env por padrão, no qual será possível instalar a versão necessária do Django (ou, por padrão, a mais recente, que no momento da redação deste documento era 3.0.2):

pip3 install django

2) Uma opção um pouco mais grave:

e se você quiser executar o Django em ambiente virtual, por exemplo, na sua pasta favorita?
Primeiro, crie uma pasta na qual iremos criar:

	mkdir myfirstdjango && cd myfirstdjango

Em seguida, digite os seguintes comandos para ativar o venv, em que django_env é o nome do nosso ambiente virtual:

	python3 -m venv django_env
	source django_env/bin/activate

Além disso, nosso ambiente virtual foi ativado. Nós podemos fornecer os pacotes necessários. No nosso caso, este é o Django:

	pip3 install django

Se você deseja desativar o ambiente virtual para retornar ao seu python global (retornar ao contexto do sistema), digite o seguinte comando:

    deactivate

Bem, espero que tenhamos descoberto o ambiente virtual. Se você tiver quaisquer problemas e perguntas adicionais, links úteis podem ser encontrados aqui e aqui .

Criando o próprio projeto


Suponha que você escolha uma das maneiras de criar seu próprio ambiente virtual (ou mesmo faça tudo globalmente, bem, ninguém o proíbe). Agora vamos para a pasta do projeto e começamos a sua criação:

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

Então, depois que o Django abriu a página inicial, você precisa instalar nosso aplicativo todolist no aplicativo principal. Abra settings.pye adicione à nossa lista de aplicativos existente nossa lista de crianças:

INSTALLED_APPS = [
	# ,     ,     
    'todolist',
]

O próximo passo é vincular o aplicativo ao banco de dados. Se você não mexer com os bancos de dados, use a solução padrão, SQlite. Eu decidi usar o PostgreSQL - ele é popular e classicamente relacionado ao Django. Além disso, podemos querer aumentar o desempenho do aplicativo. Existem muitas instruções sobre como instalar o PostgreSQL em todos os sistemas operacionais. Estou desenvolvendo para o MacOS e, com algumas pequenas danças com um pandeiro, instalei esse banco de dados baixando o Postgres.app a partir daqui . Quanto às interfaces para o banco de dados, aqui eu usei o Posticoe uma versão de avaliação para o desenvolvimento do aplicativo é suficiente para nós (embora, em princípio, você possa ficar sem ele, porque toda a nossa interação com o banco de dados será construída através do próprio aplicativo da Web e da migração). Além disso, tive que colocar o psycopg2 no ambiente virtual do projeto (sem esse driver, seu aplicativo não funcionará com o banco de dados).

Em seguida, você precisa configurar o trabalho da estática. Ainda estamos editando o arquivo settings.py, agora, no final, adicionamos trabalho com estática:

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'

Para que sua estática funcione, verifique se o pacote responsável pela estática estava na lista INSTALLED_APPS :

django.contrib.staticfiles,caso ocorra um erro.
E a última coisa no trabalho preparatório, ainda precisamos configurar o trabalho básico de url no projeto:

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

Eu adicionei um redirecionamento porque quero que o host local vá diretamente para a subpágina da categoria na página padrão (para que Deus não permita que o usuário não se perca). Também temos roteamento de duas páginas: categorias e casos.

Portanto, espero que seu aplicativo não falhe. Em seguida, podemos finalmente começar a criar o próprio aplicativo:

Criando um modelo Todo e categorias


Em seguida, começaremos a criar um modelo que irá interagir fundamentalmente com nosso banco de dados. Para criar um modelo, abra o arquivo models.pyem nossa lista de início e comece a criar. Vamos começar criando uma tabela de categorias:

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__      

Bem! Sim, aqui teremos apenas duas colunas na tabela Categorias: id e nome. Em seguida, crie uma tabela para nossos assuntos. Eu acho que tudo está claro nos comentários:

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

Depois que seu modelo estiver pronto, você precisará criar migrações:

	python3 manage.py makemigrations

E, em seguida, execute as migrações:

	python3 manage.py migrate

Criar visualização


Abra o arquivo view.pyna lista de tarefas e edite-o. Primeiro, adicione as importações necessárias e redirecione do principal para a categoria:

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

Então começamos a criação do nosso negócio. A instância do caso terá os campos do próprio texto, a data em que o caso deve ser concluído, a categoria do caso e o conteúdo combinado:

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

Depois disso, adicione as funções de adição e exclusão de casos:

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

Isso é tudo com os dedos dos pés. Então podemos ir para a página Categorias. Criamos uma função de categorias na qual também teremos a função de adicionar e excluir uma categoria. Fundamentalmente, não haverá nada de novo aqui, também teremos a capacidade de adicionar e remover:

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

É aqui que terminamos com o arquivo viewe podemos seguir para os modelos:

Trabalhar com modelos


Como você se lembra, para não escrever css novamente, eu costumava bulma.csssimplificar o layout. Porque nossas páginas de categoria e todo serão muito semelhantes, criei três arquivos: os
base.htmlquais incluirão todos os mesmos que temos nas páginas e em category.html, as todo.htmldiferenças serão localizadas:



Crie base.htmle edite:

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

Em seguida, iremos à página todo.htmle 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 %}

E category.html. Nele, não temos muitas mudanças, não difere fundamentalmente 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 %}
 

Obrigado a todos! Isso é tudo. Talvez, em algum lugar, o layout não seja perfeito ou haja outras sugestões para melhorar o aplicativo. Estou esperando por todos no comentário. Por tradição, alguns links úteis:

  1. Django, 3
  2. ,
  3. PostgreSQL

All Articles