Perfil de usuário Django

Resumo : neste tutorial, você aprenderá como implementar um perfil de usuário em aplicações Django.

Este tutorial começa onde o  tutorial de redefinição de senha do Django  parou.

Um perfil de usuário consiste em configurações e informações associadas a um usuário. Neste tutorial, você aprenderá como permitir que usuários atualizem seus perfis em aplicações Django.

Instalando o pacote de travesseiros

Como trataremos de imagens, precisamos instalar o pillowpacote usando o seguinte pipcomando:

pip install PillowLinguagem de código:  Python  ( python )

Configurando o diretório para armazenar as imagens enviadas

Primeiro, crie um mediadiretório no projeto:

mkdir mediaLinguagem de código:  Python  ( python )

Em segundo lugar, adicione o MEDIA_ROOTe MEDIA_URLao settings.pydo projeto:

MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'Linguagem de código:  Python  ( python )

Especifica MEDIA_ROOTo diretório que armazena a imagem carregada. Especifica MEDIA_URLo URL que exibe os arquivos de imagem do MEDIA_ROOTdiretório.

Terceiro, adicione a URL que fornece os arquivos de mídia ao urls.pyprojeto da seguinte maneira:

from django.contrib import admin
from django.urls import path, include

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('todo.urls')),
    path('',include('users.urls'))
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL,
                          document_root=settings.MEDIA_ROOT)
Linguagem de código:  Python  ( python )

Se DEBUGestiver Trueno settings.pyarquivo, o aplicativo Django servirá os arquivos de mídia de MEDIA_URL.

Criando um modelo de perfil

Modifique o models.pydo usersaplicativo e defina o Profilemodelo da seguinte forma:

from django.db import models
from django.contrib.auth.models import User
from PIL import Image


class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

    avatar = models.ImageField(
        default='avatar.jpg', # default avatar
        upload_to='profile_avatars' # dir to store the image
    )

    def __str__(self):
        return f'{self.user.username} Profile'

    def save(self, *args, **kwargs):
        # save the profile first
        super().save(*args, **kwargs)

        # resize the image
        img = Image.open(self.avatar.path)
        if img.height > 300 or img.width > 300:
            output_size = (300, 300)
            # create a thumbnail
            img.thumbnail(output_size)
            # overwrite the larger image
            img.save(self.avatar.path)Linguagem de código:  Python  ( python )

Como funciona.

Primeiro, defina o Profilemodelo que herda da Modelclasse:

class Profile(models.Model):Linguagem de código:  CSS  ( css )

Segundo, cada usuário possui um perfil e cada perfil pertence a um usuário. Portanto, a relação entre o Usermodelo e o Profilemodelo é um para um.

Para definir o relacionamento um-para-um , você usa OneToOneField:

user = models.OneToOneField(User, on_delete=models.CASCADE)Linguagem de código:  Python  ( python )

Se a Userfor excluído, o Profileassociado a Usertambém será excluído. Isso indica no on_delete=models.CASCADEparâmetro do OneToOneField().

Terceiro, defina o avatarcampo que contém o avatar do usuário:

avatar = models.ImageField(
        default='avatar.jpg', # default avatar
        upload_to='profile_avatars' # dir to store the image
)Linguagem de código:  Python  ( python )

Se os usuários não carregaram avatares, o padrão é avatar.jpgfile. Além disso, especificamos o diretório ( profile_avatars) que armazenará os avatares carregados.

Observe que você pode adicionar mais campos ao Profilemodelo, como endereços, interesses, etc., se necessário.

Quarto, baixe o avatar.jpgarquivo e copie-o para o mediadiretório do projeto:

Quinto, defina o __str__()método que retorna uma representação em string do Profilemodelo:

def __str__(self):
   return f'{self.user.username} Profile'Linguagem de código:  Python  ( python )

Sexto, defina o save()método que salva o perfil no banco de dados, cria uma miniatura do avatar e o armazena no diretório especificado:

def save(self, *args, **kwargs):
    # save the profile first
    super().save(*args, **kwargs)

    # resize the image
    img = Image.open(self.avatar.path)
    if img.height > 150 or img.width > 150:
        output_size = (150, 150)
        # create a thumbnail
        img.thumbnail(output_size)
        
        # overwrite the large image
        img.save(self.avatar.path)Linguagem de código:  Python  ( python )

Sétimo, cadastre o Perfil no admin.pypara que possamos gerenciar o perfil na página de administração:

from django.contrib import admin
from .models import Profile


admin.site.register(Profile)Linguagem de código:  Python  ( python )

Aplicando as migrações

Primeiro, faça migrações executando o makemigrationscomando:

python manage.py makemigrationsLinguagem de código:  Python  ( python )

Saída:

Migrations for 'users':
   users\migrations\0001_initial.py
      - Create model ProfileLinguagem de código:  Python  ( python )

Segundo, aplique as migrações:

python manage.py migrateLinguagem de código:  Python  ( python )

Saída:

Operations to perform:
   Apply all migrations: admin, auth, contenttypes, sessions, todo, users
Running migrations:  
   Applying users.0001_initial... OKLinguagem de código:  Python  ( python )

Criando a visualização MeuPerfil

Defina uma MyProfilevisualização baseada em classe no views.pyarquivo:

from django.views import View

# ...

class MyProfile(LoginRequiredMixin, View):
    def get(self, request):
        user_form = UserUpdateForm(instance=request.user)
        profile_form = ProfileUpdateForm(instance=request.user.profile)
        
        context = {
            'user_form': user_form,
            'profile_form': profile_form
        }
        
        return render(request, 'users/profile.html', context)
    
    def post(self,request):
        user_form = UserUpdateForm(
            request.POST, 
            instance=request.user
        )
        profile_form = ProfileUpdateForm(
            request.POST,
            request.FILES,
            instance=request.user.profile
        )

        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            
            messages.success(request,'Your profile has been updated successfully')
            
            return redirect('profile')
        else:
            context = {
                'user_form': user_form,
                'profile_form': profile_form
            }
            messages.error(request,'Error updating you profile')
            
            return render(request, 'users/profile.html', context)Linguagem de código:  Python  ( python )

Primeiro, importe a Viewclasse de django.views:

from django.views import ViewLinguagem de código:  Python  ( python )

Segundo, defina MyViewa classe que herda da Viewclasse. A MyViewclasse possui os métodos get()e post()que correspondem aos métodos HTTP GETe POST.

Ao usar a Viewclasse, você não precisa ter ramificações if-else dentro de uma função de visualização para determinar se o método HTTP é GET ou POST.

No get()método da MyProfileclasse, criamos os objetos UserUpdateForme ProfileUpdateForme os passamos para o profile.htmltemplate.

No post()método, também criamos os objetos UserUpdateFormand ProfileUpdateForm, mas passamos dados adicionais de request.POSTand request.FILES.

Quando ambos os formulários são válidos, nós os salvamos no banco de dados, criamos uma mensagem flash e redirecionamos o usuário de volta para a página de perfil.

Se um dos formulários não for válido, criamos uma mensagem de erro e redirecionamos o usuário de volta à página de perfil e renderizamos novamente o modelo.

Criando modelo profile.html

Crie profile.htmlno templates/usersdiretório que estende o base.htmlmodelo:

{% extends 'base.html' %} 

{% block content %}


<div class="center">
	<form method="POST" enctype="multipart/form-data" class="card">
		{% csrf_token %} 
		
	    {% if user.profile %}
			<img src="{{user.profile.avatar.url}}" alt="{{ user.username }}" class="avatar"  accept=".jpg,.jpeg,.png"/>
	    {% endif %}
	    
	    <h2 class="text-center">{{ user.username | title }}</h2>
	    <p class="text-center"><a href="mailto:{{user.email}}">{{user.email}}</a></p>
   	    <hr>
		
            <label for="email">Email Address:</label>
            <input type="email" id="email" name="email" value="{{user.email}}" />
			
		
		<label for="avatar">Avatar:</label>
		<input type="file" name="avatar" id="avatar">	
		
	    <button type="submit" class="btn btn-primary full-width">Update Profile</button>
	
	</form>
</div>

{% endblock content %}Linguagem de código:  Python  ( python )

Criando um perfil manualmente

Primeiro, faça login no site de administração usando a conta de superusuário, você verá Profilesabaixo do Usersaplicativo:

Segundo, clique no botão Adicionar perfil para criar um novo perfil para o usuário existente:

Terceiro, adicione um novo perfil para o usuário John e clique no botão Salvar:

O Django mostrará que o perfil do usuário John foi adicionado com sucesso.

Se você fizer login como John e abrir a página de perfil http://127.0.0.1:8000/profile/, verá a seguinte página:

Neste formulário você pode atualizar um perfil alterando o endereço de e-mail e enviando um novo avatar.

Incluir o URL do perfil no cabeçalho

Modifique o base.htmlmodelo para adicionar o URL do perfil ao cabeçalho:

{%load static %}
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="{% static 'css/style.css' %}" />
        <title>Todo List</title>
    </head>

    <body>
        <header class="header">
            <div class="container">
            	<a href="{%url 'home'%}" class="logo">Todo</a>
            	<nav class="nav">
	            	<a href="{%url 'home'%}"><i class="bi bi-house-fill"></i> Home</a>
	                {% if request.user.is_authenticated %}
	    	              	<a href="{% url 'tasks' %}"><i class="bi bi-list-task"></i> My Tasks</a>
	    	              	<a href="{% url 'task-create' %}"><i class="bi bi-plus-circle"></i> Create Task</a>
		                <a href="{% url 'profile' %}" title="Update my profile">Hi {{request.user | title}}</a>
	    	                <a href="{% url 'logout' %}" class="btn btn-outline">Logout</a>
	                {% else %}
				<a href="{% url 'login' %}" class="btn btn-outline">Login</a>
	            	        <a href="{% url 'register' %}" class="btn btn-primary">Join Now</a>
	                {% endif %}
	             </nav>
            </div>
        </header>
        <main>
            <div class="container">
            	{% if messages %}
				{% for message in messages %}
					<div class="alert alert-{{message.tags}}">
					       {{message}}
					     </div>
					   {% endfor %}
				{% endif %}
            
             {%block content %}
             {%endblock content%}
            </div>
        </main>
        <footer class="footer">
            <div class="container">
                <p>© Copyright {% now "Y" %} by <a href="https://tutorials.acervolima.com">Python Tutorial</a></p>
            </div>
        </footer>
    </body>
</html>
Linguagem de código:  HTML, XML  ( xml )

Criando perfil automaticamente

Se você fizer login como Janee acessar a página de perfil, receberá o seguinte erro:

A razão é que não criamos o perfil do usuário Jane. Para corrigir esse problema, devemos criar um perfil assim que o usuário se registrar com sucesso. Para implementar isso, usaremos algo chamado sinais no Django.

Primeiro, crie signals.pyum arquivo no usersaplicativo com o seguinte código:

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile


@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)


@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
    instance.profile.save()Linguagem de código:  Python  ( python )

Neste signals.pyarquivo:

  • A create_profile()função cria um novo perfil após Usera criação de um objeto.
  • A save_profile()função atualiza o perfil depois que um Userobjeto é salvo.

O @receiverdecorador conecta o post_saveevento do Usermodelo a cada função.

Segundo, importe sinais para o apps.pyarquivo do usersaplicativo:

from django.apps import AppConfig


class UsersConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'users'
    
    def ready(self):
        import users.signalsLinguagem de código:  Python  ( python )

No apps.pyaplicativo users, importamos o signals.pymétodo ready da UsersConfigclasse.

Terceiro, registre um novo usuário e verifique o perfil:

Você pode baixar o código-fonte completo do perfil de usuário do Django aqui .

Resumo

  • Use o sinal Django para criar um perfil para um usuário automaticamente.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *