Set the User logged in to the model as default | Django + Python3

Asked

Viewed 783 times

0

I am trying to learn Django, and with this I am trying to create a simple system of tickets.

I have made a lot of progress in my studies, but now I’ve tackled the following problem.

How to do by default when saving a Ticket, Django saves the currently logged in user?

Follow my codes from the archive models.py

from django.contrib.auth.models import User
from django.db import models
from datetime import datetime

class Projeto(models.Model):
    """
        Classe que gere os Projetos
        Permite que se cadastre N usuários por Projeto
        Retorna:
            NOME_DO_PROJETO | SITE_DO_PROJETO
    """
    nome = models.CharField(max_length=100)
    site = models.CharField(max_length=200)
    informacoes = models.TextField(blank=True)
    usuarios = models.ManyToManyField(User, related_name='projetos')

    def __str__(self):
        return self.nome + " | " + self.site

class Ticket(models.Model):
    """
        Classe que gere os Tickets no sistema.
        Retorna:
            DATA HORA | TITULO DO CHAMADO
    """
    TIPOS_TICKET = (
        ('BUG', 'Bug'),
        ('URGENTE', 'Urgente'),
        ('FINANCEIRO', 'Financeiro'),
        ('MELHORIA', 'Melhoria')
    )
    STATUS_TICKET = (
        ('ABERTO', 'Aberto'),
        ('AGUARDANDO_CLIENTE', 'Aguardando Cliente'),
        ('EM_ANALISE', 'Em Análise'),
        ('FINALIZADO', 'Finalizado'),
        ('CANCELADO', 'Cancelado'),
    )
    titulo = models.CharField(max_length=200)
    conteudo = models.TextField()
    tipo = models.CharField(max_length=30, choices=TIPOS_TICKET, default='BUG')
    status = models.CharField(max_length=30, choices=STATUS_TICKET, default='ABERTO')
    projeto = models.ForeignKey(
        Projeto,
        on_delete=models.CASCADE,
        limit_choices_to={'usuarios':1}
    )
    usuario = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        null=True
    )
    data_abertura = models.DateTimeField('Data Abertura', auto_now_add=True)
    data_fechamento = models.DateTimeField('Data Fechamento', blank=True, null=True)

    def __str__(self):
        return str(datetime.strftime(self.data_abertura, "%d/%m/%y %H:%M") + " | " + self.titulo)

    def save(self, *args, **kwargs):
        self.usuario = User
        super(Ticket, self).save(*args, **kwargs)

class TicketMsg(models.Model):
    """
        Mensagens dos tickets
        Retorna:
            texto da mensagem
    """
    texto = models.TextField()
    ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE)
    data_resposta = models.DateTimeField('Data Resposta')

    def __str__(self):
        return str(self.texto)

And my file admin.py

from django.contrib import admin
from django.contrib.auth.models import User
from .models import Ticket, TicketMsg, Projeto

# Register your models here.
class ProjetoAdmin(admin.ModelAdmin):
    model = Projeto
    filter_horizontal = ('usuarios',)

class TicketAdmin(admin.ModelAdmin):
    model = Ticket
    exclude = ('status', 'data_fechamento', 'data_abertura', 'usuario')
    list_display = ('titulo', 'tipo', 'status', 'projeto', 'data_abertura')
    list_filter = ('projeto', 'tipo', 'status')

    def get_ordering(self, request):
        return ['data_abertura']

admin.site.register(Projeto, ProjetoAdmin)
admin.site.register(Ticket, TicketAdmin)
admin.site.register(TicketMsg)

This is the result of the listing so far, using the Django ADMIN

inserir a descrição da imagem aqui

The idea is that when the person enters a ticket, the system identifies which user did it.

I have already managed to filter which projects a user has the right to open ticket to.

Now the system needs to record the logged in User ID so I can identify WHO opened the ticket.

Follow image of the form:

inserir a descrição da imagem aqui

All help is welcome! Personal thank you!

2 answers

0


There is a method called .save_model in Modeladmin that aims to make pre and post save operations.

class TicketAdmin(admin.ModelAdmin):
...

def save_model(self, request, obj, form, change):
    obj.user = request.user
    super(ArticleAdmin, self).save_model(request, obj, form, change)

More details in the documentation Modeladmin.save_model.

0

Another solution that I typically use is to create an "Abstract" class, which implements the typical logic of saving the user who created the register or updated the register, but here adapted to your case:

For your example, create a common.py file:

common py.

from django.conf import settings
from django.db import models
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from ai.middleware.current_user import CurrentUserMiddleware
from django.contrib.admin.models import LogEntry
from django.contrib.contenttypes.fields import GenericRelation

class CommonInfo(models.Model):
    usuario = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_("Usuário"), blank=True, null=True,
                                   related_name="%(app_label)s_%(class)s_created", on_delete=models.SET_NULL, editable=False)

    @staticmethod
    def get_current_user():
        """
        Get the currently logged in user over middleware.
        Can be overwritten to use e.g. other middleware or additional functionality.
        :return: user instance
        """
        return CurrentUserMiddleware.get_current_user()

    def set_user_fields(self, user):
        """
        Set user-related fields before saving the instance.
        If no user with primary key is given the fields are not set.
        :param user: user instance of current user
        """
        if user and user.pk:
            if not self.pk:
                self.usuario = user
            else:
                self.usuario = user

    def save(self, *args, **kwargs):
        current_user = self.get_current_user()
        self.set_user_fields(current_user)
        super(CommonInfo, self).save(*args, **kwargs)

    class Meta:
        abstract = True

In your models you change to use the Abstract class:

py.models

from yourapp.common import CommonInfo

class Ticket(CommonInfo): # trocas models.Model por CommonInfo, que já herda de models.Model
    """
        Classe que gere os Tickets no sistema.
        Retorna:
            DATA HORA | TITULO DO CHAMADO
    """
    TIPOS_TICKET = (
        ('BUG', 'Bug'),
        ('URGENTE', 'Urgente'),
        ('FINANCEIRO', 'Financeiro'),
        ('MELHORIA', 'Melhoria')
    )
    STATUS_TICKET = (
        ('ABERTO', 'Aberto'),
        ('AGUARDANDO_CLIENTE', 'Aguardando Cliente'),
        ('EM_ANALISE', 'Em Análise'),
        ('FINALIZADO', 'Finalizado'),
        ('CANCELADO', 'Cancelado'),
    )
    titulo = models.CharField(max_length=200)
    conteudo = models.TextField()
    tipo = models.CharField(max_length=30, choices=TIPOS_TICKET, default='BUG')
    status = models.CharField(max_length=30, choices=STATUS_TICKET, default='ABERTO')
    projeto = models.ForeignKey(
        Projeto,
        on_delete=models.CASCADE,
        limit_choices_to={'usuarios':1}
    )
    # usuario = models.ForeignKey(User, on_delete=models.CASCADE, null=True) # removes esta linha, uma vez que herda da classe CommonInfo
    data_abertura = models.DateTimeField('Data Abertura', auto_now_add=True)
    data_fechamento = models.DateTimeField('Data Fechamento', blank=True, null=True)

    def __str__(self):
        return str(datetime.strftime(self.data_abertura, "%d/%m/%y %H:%M") + " | " + self.titulo)

    def save(self, *args, **kwargs):
        # self.usuario = User deixa de ser necessário esta linha uma vez que já grava na classe abstract
        super(Ticket, self).save(*args, **kwargs)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.