Recentemente gravei algumas aulas para auxiliar quem está começando a desenvolver para a Web utilizando Python e Django.
É um curso introdutório que não apresenta todo o processo de desenvolvimento, mas ensina como as coisas funcionam no Django para que você possa começar a aprender.
Documentação dos Sistemas de Autenticação do Django
Nesta etapa, vamos relacionar nossos modelos com a classe “User” do Django para podermos separar os objetos por usuário, de modo que um usuário tenha seus próprios registros no nosso sistema e que um usuário não acesse os registros de outros usuários.
Importe o User no models.py para poder criar chave estrangeira com ele
from django.contrib.auth.models import User
Crie um atributo na sua classe, neste caso criei no Animal
class Animal(models.Model): tipo = models.ForeignKey(Tipo, on_delete=models.PROTECT) ... telefone = models.CharField(max_length=17) usuario = models.ForeignKey(User, on_delete=models.PROTECT)
Execute o makemigrations para preparar seu banco de dados com as modificações
python manage.py makemigrations adocao
Esta mensagem indica que você está alterando uma tabela no banco que já tem registros. Como não falamos que ele pode ser “blank” e “null” você precisa fornecer um valor padrão. Por isso, vamos na opção “1” e depois digitar um valor qualquer para ser preenchido na nova coluna “usuario”, por exemplo ”0”.
Execute o migrate para atualizar o banco
python manage.py migrate
Inicie o servidor novamente e acesse a página para cadastrar um animal
python manage.py runserver
Tente cadastrar um animal e você terá o erro:
Isso aconteceu porque você também deve informar um usuário, mas no formulário não tem ele. Você pode atualizar suas views e colocar “usuario” nos “fields”, porém esse não é o jeito certo.
É aqui que entra um novo método que iremos sobrescrever nas views: o form_valid
Documentação do form_valid
O form_valid é o método chamado depois que submetemos um formulário, seja ele para inserir, alterar ou excluir. Ele vai verificar se os campos foram preenchidos, se se os valores estão de acordo e todas as outras verificações que se deve fazer. Por fim, ele cria um objeto e salva no banco de dados (quando chamamos o super).
Vá no “adocao/views.py” e procure o “AnimalCreate”. Ele já tem um método que sobrescrevemos, o “get_context_data”. Agora vamos sobrescrever o form_valid:
Agora vamos pegar o usuário que está “logado” e inserir ele como “usuario” nesse animal
Precisamos pegar o usuário antes de chamar o super(), se não ele vai dar aquele mesmo erro. Então, adicione form.instance.usuario = self.request.user antes dele:
def form_valid(self, form): # Define o usuário como usuário logado form.instance.usuario = self.request.user url = super().form_valid(form) return url
O “form.instance” vai manipular uma instância desse formulário com todos os dados recebidos antes de salvar no banco. Por isso, pegamos o “.usuario” porque é o nome do atributo criado na classe. O usuário logado sempre vai estar dentro do “request.user”. Aqui precisamos acessar ele pelo “self” porque estamos dentro de uma classe e queremos o usuário que fez essa requisição de salvar um animal.
A instrução retorna o endereço para onde redirecionar o usuário.
Fazer coisas depois de salvar o objeto no banco
É possível fazer coisas depois de salvar o objeto no banco. No exemplo anterior, adicionamos um usuário antes de chamar o super(). Basta fazer antes do return:
def form_valid(self, form): # Define o usuário como usuário logado form.instance.usuario = self.request.user url = super().form_valid(form) # código a fazer depois de salvar objeto no banco self.object.atributo = “algo” # Salva o objeto novamente self.object.save() return url
É possível acessar o objeto que foi criado pelo self.object. O método save() agora existe para salvar as alterações que você fez, por exemplo.
Como listar somente as Classes que são do “User”
Vamos alterar a view “AnimalList” dentro de “adocao/views.py” para listar somente os objetos que o próprio usuário que está logado cadastrou. No momento, nossa view é simples:
class AnimalList(LoginRequiredMixin, ListView): model = Animal template_name = "adocao/listas/list_animal.html"
As views que herdam a classe “ListView” tem um método que é chamado para listar todos os objetos daquela classe no banco. Nós podemos sobrescrever ele para colocar uma condição diferente do listar todos.
Método para alterar a listagem padrão de objetos
Crie o método “get_queryset” e altere o “object_list”:
def get_queryset(self): # O object_list armazena uma lista de objetos de um ListView self.object_list = Animal.objects.filter(usuario=self.request.user) return self.object_list
Pode ver alguma de suas listas como tem um for lá para o “object_list”.
Permitir que somente o usuário dono do objeto altere ou exclua o objeto
Uma maneira de garantir que o usuário não vai alterar o ID da sua URL para tentar ver outro registro é alterando o método padrão da sua classe que herdou um DeleteView ou UpdateView. Esse método é o “get_object”. É bem parecido com o da lista, porém ele recebe um ID pela URL para buscar exatamente um objeto e não uma lista deles.
Vamos fazer um procedimento que vai resultar uma tela de erro 404 se o usuário tentar burlar nosso site. No “adocao/views.py” faça a importação:
# Método que busca um objeto. Se não existir, da um erro 404 from django.shortcuts import get_object_or_404
Crie o método a seguir no “AnimalUpdate”:
# Altera a query para buscar o objeto do usuário logado def get_object(self, queryset=None): self.object = get_object_or_404(Animal, pk=self.kwargs['pk'], usuario=self.request.user) return self.object
O método “get_object_or_404” precisa de, pelo menos, dois parâmetros: a classe em que será feita a busca e os atributos que ela vai procurar. Neste caso procuramos pela chave primária (pk) e pelo usuário logado. Tente acessar o cadastro de algum animal com outro usuário e terá esse erro.
pk e usuario são atributos de Animal
self.kwargs[‘pk’] pega a chave primária da URL. Esse “pk” vem lá da URL:
path('editar/animal/<int:pk>/', …..)
Excluir somente objetos do usuário logado
O procedimento é exatamente o mesmo. Basta adicionar o método a seguir no seu “AnimalDelete”:
# Altera a query para buscar o objeto do usuário logado def get_object(self, queryset=None): self.object = get_object_or_404(Animal, pk=self.kwargs['pk'], usuario=self.request.user) return self.object
Fazer consultas personalizadas – Documentação
É possível fazer consultas personalizadas no banco de dados. Para mais detalhes, veja a documentação acima.
Algumas consultas interessantes
Listar todos os objetos:
Classe.objects.all()
Contar todos os objetos:
Classe.objects.all().count()
Buscar um objeto:
Classe.objects.get(pk=5)
Fazer uma consulta que retorna um ou mais objetos:
Trabalhar com mais de um monitor é muito bom quando se utiliza muitas janelas/programas ao mesmo tempo. Em alguns casos a janela fica “ligada” ao monitor que ela estava posicionada e se você resolve abrir o mesmo programa usando um só monitor, ela tende a ir lá para o canto.
O jeito mais fácil de restaurar/mover uma janela que não está na sua tela atual é usando o atalho no teclado para posicionar, maximizar e minimizar. Use a combinação das teclas Windows + setas:
Cima: maximizar para tela cheia;
Baixo: minimizar para barra de tarefas;
Esquerda: maximizar a janela até o meio do monitor;
Direita: maximizar a janela até o meio do monitor;
É provavelmente por causa da versão do MySQL que você está usando. O DBDesigner não suporta a versão 5, mas há uma maneira de fazê-lo aceitar.
Antes de começar, crie um novo usuário com todas as permisões (no menu Privilégios do phpMyadmin) para usarmos na sincronização. Se você mudar a senha do root vai ter problemas de conexão com seus sistemas/projetos.
Vá em Iniciar -> Executar -> cmd -> execute os comandos abaixo:
C:xamppmysqlbinmysql -h localhost -u root -p
Sua senha: (digite a senha, caso haja)
set password for usuarioNovo@localhost = old_password('senha nova');
É necessário alterar a senha para que a sincronização funcione.