---
# System prepended metadata

title: 23 Usuário e autenticação + Admin
tags: [web, day2]

---

---
tags: web,day2
robots: noindex, nofollow
lang: pt-br
---

# 23 Usuário e autenticação + Admin

O Django possui um sistema de usuários que permite facilmente proteger as views com login e também tem uma interface administrativa, além disso o Django já vem com uma série de comandos administrativos para ajudar na criação de usuários.


## Criando usuários

A primeira tarefa que precisamos fazer para usar o sistema de admin e login do Django é criar um super usuário, isso pode ser feito através do terminal.

```bash
django-admin createsuperuser --username admin --email admin@blog.com
```

Este comando vai pedir para você digitar o password 2 vezes, escolha algo fácil por enquando, por exemplo: `admin`  novamente.

```bash
Password: admin
Password (again): admin 
```

O Django vai fazer algumas verificações de segurança no password mas você pode confirmat digitando `y`

```bash
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
```


## Autenticação

Agora vamos aproveitar que temos um usuário e vamos proteger a nossa view `/new/` com usuário e senha.

Edite o arquivo `views.py`

```python
from django.contrib.auth.decorators import login_required
...

@login_required
def new_post(request):
    ...
```

Agora precisamos habilitar o sistema default de login alterando o arquivo `urls.py`


```python
from django.contrib import admin
from django.urls import path, include  # NEW
from blog.views import new_post, PostList, PostDetail

urlpatterns = [
    path('admin/', admin.site.urls),
    path("accounts/", include("django.contrib.auth.urls")),  # NEW
    path('new/', new_post, name='new_post'),
    path('', PostList.as_view(), name='index'),
    path('<slug:slug>/', PostDetail.as_view(), name='detail'),
]

```

E por último precisamos criar um template para a página de login

```bash
mkdir templates/registration
touch templates/registration/login.html
```

`templates/registration/login.html`
```html
{% extends 'base.html' %} 
{% block content %} 
<h2>Log In</h2>
<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">Log In</button>
</form>
{% endblock content %}
```

Agora ao tentar acessar a URL http://127.0.0.1:8000/new/ acontecerá um redirecionamento para a página de login


![](https://github.com/rochacbruno/python-web-api/raw/day2/docs/day2/imgs/django_blog_login.png)


Basta usar `admin` e `admin` que conseguirá acessar :) 


# Django Admin e Management Commands

O Django possui 2 ferramentas administrativas, os management commands e o Django Admin,
vamos ver como podemos usar cada um deles.


## Management commands

Vamos adicionar um comando que permita escrever um novo post através da linha de 
comando.

```bash
django-admin add-post --title "Titulo" --content ¨"Este é um post da linha de comando"
```

Primeiro criamos a pasta para os comandos e o caminho deve ser exatamente uma pasta chamada `management/commands` dentro da app `blog`

```bash
mkdir -p blog/management/commands
```

Também precisamos transformar `management` e `commands` em módulos Python.

```bash
touch blog/management/__init__.py
touch blog/management/commands/__init__.py
```

Agora criamos o arquivo para o nosso primeiro comando:

```bash
touch blog/management/commands/add_post.py
```

E neste arquivo escrevemos o comando:


`add_post.py`
```python
from django.core.management.base import BaseCommand, CommandError
from blog.models import Post
from django.utils.text import slugify


class Command(BaseCommand):
    """Adds new post to the database
    
    $ django-admin add_post --title "Titulo" --content "Conteudo
    """
    help = "Creates a new Post in the database"

    def add_arguments(self, parser):
        parser.add_argument("--title", type=str, required=True)
        parser.add_argument("--content", type=str, required=True)

    def handle(self, *args, **options):
        try:
            post = Post.objects.create(
                title=options["title"],
                slug=slugify(options["title"]),
                content=options["content"],
            )
        except Exception as e:
            raise CommandError(e)
        else:
            self.stdout.write(self.style.SUCCESS(f"Post {post.title} created."))
```


Agora verá o comando disponível

```
django-admin --help    

Type 'django-admin help <subcommand>' for help on a specific subcommand.

Available subcommands:

...

[blog]
    add_post

...
``` 

E pode utilizar


```bash
django-admin add_post --title "Post do terminal" --content "Postagem bem legal no terminal" 
Post "Post do terminal" created
```

Acesse o blog http://127.0.0.1:8000/ e verá a postagem publicada.


## Interface Admin

O Admin é a principal ferramenta e talvez o motivo de muitas pessoas escolherem o Django, esta interface já vam habilidade por default e pode ser acessada em http://127.0.0.1:8000/admin/ usando a conta de superuser `admin, admin`


![](https://github.com/rochacbruno/python-web-api/raw/day2/docs/day2/imgs/django_blog_admin1.png)

Por default apenas os models referentes ao controle de usuários é ativado no admin, para adicionar os outros models precisamos alterar o arquivo `admin.py` dentro de cada app.


`blog/admin.py`

```python
from django.contrib import admin

from blog.models import Post


class PostAdmin(admin.ModelAdmin):
    list_display = ["title", "published", "date"]
    list_filter = ["published", "date"]
    search_fields = ["title", "content"]
    prepopulated_fields = {"slug": ("title",)}
    ordering = ["-date"]


admin.site.register(Post, PostAdmin)

```

Agora pode dar o refresh na página http://127.0.0.1:8000/admin/ e verá a app blog listada


![](https://github.com/rochacbruno/python-web-api/raw/day2/docs/day2/imgs/django_blog_admin2.png)

E através do admin podemos adicionar novos posts, alterar e deletar, experimente.


![](https://github.com/rochacbruno/python-web-api/raw/day2/docs/day2/imgs/django_blog_admin3.png)


Ao listar todos os posts repare que tem um dropdown **action** que permite deletar vários posts selecionados

![](https://github.com/rochacbruno/python-web-api/raw/day2/docs/day2/imgs/django_blog_admin4.png)

Podemos adicionar outras actions para serem aplicadas a todos os itens selecionados, por exemplo, para alterar o
status de publicado/não publicado.


`admin.py`
```python

class PostAdmin(admin.ModelAdmin):
    ...
    actions = ["publish"]

    @admin.action(description="Publish/Unpublish posts")
    def publish(self, request, queryset):
        for post in queryset:
            post.published = not post.published
            post.save()
```


![](https://github.com/rochacbruno/python-web-api/raw/day2/docs/day2/imgs/django_blog_admin5.png)


## Conclusão

O Django é um dos frameworks mais produtivos pelo fato de entregar muitas coisas prontas e também o mais utilizado em grandes projetos por ser bastante suportado pela comunidade.

O Django é uma ótima opção para sites de gerenciamento de conteúdo (CMS) que usem banco de dados relacional (SQL).

Em um próximo capitulo do treinamento vamos fazer um projeto completo, mas será usando o FastAPI e o motivo de usa-lo é o fato dele não abstrair tantas coisas e de fato podermos aprender sem ter as mágicas do Django escondendo a implementação.
