Neste artigo veremos como atualizar um registro por meio do recurso de form do django, criaremos uma view e um template para depois executar a requisição POST no banco.

django update cover

Projeto em andamento

Antes de iniciar é bom entender que este é um projeto em andamento, você pode fazer comigo do zero começando por aqui:

  1. Instalando Django 2 e criando um projeto;

O código de todo o conteúdo está disponível aqui!

obs: esta é a parte 11


 Atualizar registros é uma ação normal nas aplicações web

Então neste artigo vamos seguir a mesma lógica do post passado de inserção, veja aqui, e pedir autenticação para o usuário que quer alterar o post

Com esta medida nos protegemos para que pessoas que não tem acesso administrativo mexam em nossos registros

Vamos lá!

Criar URL

Como teremos uma nova view devemos adicionar uma nova URL

Então no arquivo urls.py da aplicação blog, deixe a variável urlspatterns assim:

urlpatterns = [
    path('', views.post_list, name='post_list'),
    path('<slug:slug>', views.post_detail, name='post_detail'),
    path('criar/', views.post_create, name='post_create'),
    path('editar/<int:id>/', views.post_update, name='post_update'),
    path('sobre-nos/', views.about, name='about'),
    path('contato/', views.contact, name='contact'),
]

Perceba que apenas adicionamos a url post_update

Criar View

O próximo passo, você já deve estar careca de saber, é criar a view

Precisamos criar uma função que comporte tanto a visualização do form de edit, o GET, quanto também o POST para alteração de dados

Abra seu arquivo views.py de blog e crie esta função post_update:

@login_required
def post_update(request, id):
    post = get_object_or_404(Post, pk=id)
    form = PostForm(instance=post)

    if(request.method == 'POST'):
        form = PostForm(request.POST, instance=post)
        
        if(form.is_valid()):
            post = form.save(commit=False)
            post.title = form.cleaned_data['title']
            post.description = form.cleaned_data['slug']
            post.body = form.cleaned_data['body']
            post.author = form.cleaned_data['author']
            post.status = form.cleaned_data['status']

            post.save()

            return redirect('blog:post_list')
        else:
            return render(request, 'blog/edit_post.html', {'form': form, 'post' : post})

    elif(request.method == 'GET'):
        return render(request, 'blog/edit_post.html', {'form': form, 'post' : post})

Vamos verificar os pontos mais importantes da view:

  • @login_required: permite que apenas usuários autenticados entrem na view;
  • post = get_object_or_404(Post, pk=id): busca o post que queremos editar;
  • form = PostForm(instance=post): preenche o form com os dados do post;
  • if e else: verificam se o request é GET, que visualiza o form preenchido, ou POST, que insere os registros alterados no banco
  • if(form.is_valid()): verifica se o formulário está correto e depois validamos cada campo com cleaned_data;
  • return redirect(‘blog:post_list’): o redirect serve para redirecionar para uma view que optamos como parâmetro dele;

Criar Template

Agora devemos criar o template, escolhemos o nome para o arquivo ser edit_post.html, la na URL que criamos anteriormente

Crie esse arquivo em blog/templates/blog, com o seguinte conteúdo:

{% extends 'blog/base.html' %}
{% block title %}Editar '{{post.title}}'{% endblock %}

{% block content %}
    <div class="container">
        <h1>Editar '{{post.title}}'</h1>
        <div>
            <form action="." method="POST">
                {% csrf_token %}
                {{ form.as_p }}
                <input type="submit" class="btn btn-default" value="Editar">
            </form>
            
        </div>
    </div>
{% endblock %}

Aqui neste template não há nada que já não foi visto antes, utilizamos o objeto do post  que veio da view para preencher o title e o h1

E criamos o formulário a partir do form que também veio da view, já com os dados preenchidos

Ficou com dúvidas sobre templates? Veja mais sobre eles aqui.

Mudar a URL_LOGIN

Um detalhe, como nós alteramos a url padrão de registro do Django devemos fazer uma pequena adição em settings.py

A nossa URL é /account/ e a padrão do Django é /accounts/, isso pode causar um 404 quando o usuário recebe um redirect

Então no fim do arquivo adicione a seguinte linha

LOGIN_URL = '/account/login'

Isso fará com que o @login_required redirecione o usuário para a nossa URL de login correta

Testando o update

Agora devemos realizar o teste da aplicação para ver se o update está realmente funcionando

Deixe o server rodando com o comando

python manage.py runserver

Entre em algum post com  a url editar/id_do_post, onde id_do_post é um id de um post existente no seu projeto

Deve aparecer um formulário igual a este:

editando post django

O form já vem preenchido pois nós enviamos pela view assim

Agora tente editar e veja se as mudanças aparecem após o envio do formulário

Editar na lista de posts

Para finalizar o projeto devemos colocar uma opção de editar na listagem de posts

Para os usuários autenticados conseguirem de forma fácil acessar a edição

Para isso abra o arquivo post_list.html

E deixe a div com a classe card-body assim:

<div class="card-body">
        <h5 class="card-title">{{ post.title }}</h5>
    <p class="card-text">{{ post.body|truncatechars:50 }}...</p>
    <p>Criado em {{ post.created_at }} por {{ post.author }}</p>
    <a href="{% url 'blog:post_detail' post.slug %}" class="btn btn-primary">Ver o post completo</a>
    {% if user.is_authenticated %}
        <p><a href="{% url 'blog:post_update' post.id %}">Editar post</a></p>
    {% endif %}
</div>

Perceba que adicionamos um if, que checa se o usuário está logado

A partir disso adicionamos uma URL que vai direto a edição do post

Adicionando else para formulários não válidos

Um detalhe que você pode não ter notado é que temos um else a mais na view de edição que não temos na criação

Depois do if do form.is_valid(), redirecionamos o usuário para a mesma página caso o form não esteja certo

Assim mensagens de erro que vem do back end serão exibidas ao usuário, para que corrija alguma informação errada que ele mandou e não foi tratada no front-end

Então aconselho a fazer isso na view de post_create também

Que deve ficar assim:

@login_required
def post_create(request):
    form = PostForm()

    if(request.method == 'POST'):

        form = PostForm(request.POST)

        if(form.is_valid()):
            post_title = form.cleaned_data['title']
            post_slug = form.cleaned_data['slug']
            post_body = form.cleaned_data['body']
            post_author = form.cleaned_data['author']
            post_status = form.cleaned_data['status']

            new_post = Post(title=post_title, slug=post_slug, body=post_body, author=post_author, status=post_status)
            new_post.save()

            return redirect('blog:post_list')
        else:
            return render(request, 'blog/add_post.html', {'form' : form})

    elif(request.method == 'GET'):
        return render(request, 'blog/add_post.html', {'form' : form})

Exemplo da mensagem de erro em ação:

erro de slug django

Conclusão

Nós iniciamos o post fazendo a URL necessária para acessar a edição de post, nela vimos que precisamos inserir um argumento, que é o id, para encontrar o post

Depois criamos a view que tem uma bifurcação entre os requests de GET e POST

Se for GET o usuário verá o post com o formulário preenchido

Caso seja POST as alterações serão inseridas no banco, caso sejam válidas

E então criamos o template da view, que receberá o formulário preenchido e por fim adicionamos um botão de edição na listagem de posts

Confira também o nosso canal do Youtube com muito conteúdo sobre programação, clicando aqui.

Pessoal, agradeço a todos por lerem até o fim, se possível compartilhem com os amigos interessados em Django e se inscrevam na nossa lista de e-mail para não perder as novidades.

Caso haja alguma dúvida ou crítica, comentem abaixo que responderei assim que possível, obrigado!

Subscribe
Notify of
guest

4 Comentários
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Hugo

Olá, parabéns pelo excelente conteúdo! Gostaria de ver também algum tipo de consulta no banco e retornando na tela.
Forte abraço.

Tiago

otimo irmão muito obrigado

Battisti

Valeu Tiago! 😀