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

I'm trying to learn Django, and with that I'm trying to create a simple ticket system.

I have advanced a lot in my studies, but now I have packed into the following problem.

How does Django save the currently logged in user by default when saving a Ticket?

Follow my file codes 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 so far of the listing, using the Django

insert the description of the image here

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

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

Now the system fails to record the ID of the logged in user so that I can identify who opened the ticket.

Follows form image:

insert the description of the image here

All help is welcome! Thank you guys!

Author: Raphael Schubert, 2017-02-23

2 answers

There is a method called .save_model in ModelAdmin that aims to do 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
Author: Hugo Brilhante, 2017-02-24 11:45:10

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

For your example, you create a file common.py:

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:

Models.py

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)
 0
Author: Ernesto Casanova, 2020-02-22 14:31:46