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.
Projeto em andamento
Antes de iniciar é bom entender que este é um projeto em andamento, você pode fazer comigo do zero começando por aqui:
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:
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:
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!
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.
Oi Hugo, veja este post:
https://www.horadecodar.com.br/2019/01/08/inserindo-dados-do-banco-para-o-template-no-django/
otimo irmão muito obrigado
Valeu Tiago! 😀