Register different types of users in Django admin

Asked

Viewed 888 times

4

I have three types of users: Manager, Teacher and Student. All of them need to log into the system, but the teacher and student have some more information. The manager who creates access for the Student and Teacher. I want to register by Django Admin and when Click to register the Student or Teacher, also register the default User on Jango on the same screen. In Django Admin I price three areas:

  • Register User (default)
  • Register Student + User
  • Register Teacher + User

In the default template it shows only a select box and a +button. I want the full form on the screen.

Follow the code used to create the Student class

class Aluno(models.Model):
    SEXO_CHOICES = ((u'M', 'Masculino'), (u'F', 'Feminino'))

    user = models.OneToOneField(User, on_delete=models.CASCADE)
    sexo = models.CharField(choices=SEXO_CHOICES, max_length=1)
    cpf = models.CharField(max_length=20, blank=True)
    nascimento = models.DateField(blank=True)

    def __str__(self):
        return self.user

I used Inline in admin.py to link the User class to the Student class but it failed. Follow the code

from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

class UserInlineAdmin(admin.TabularInline):
    model = User

class AlunoAdmin(admin.ModelAdmin):
    inlines = (UserInlineAdmin,)

Follows the error presented

<class 'blog.admin.UserInlineAdmin'>: (admin.E202) 'auth.User' has no ForeignKey to 'blog.Aluno'.
  • If I understood your problem correctly, wouldn’t it be ideal to go back and model your database so that the differences between one and the other is only one line to identify which type of user? For example, the Student, Manager and Teacher classes inherit from the User class (which is quite complete).

  • Anyway, here is an answer in the OS regarding your problem and the error: https://stackoverflow.com/questions/33748059/add-inline-model-to-django-admin-site

  • @Thanks for the tip. I saw this answer there but apparently it’s the same as mine. The problem is to define this union with the User class. Even if I remodel I still need an area to register the Manager, the collaborator and the Student. I just want to register each one separately and without having to change the screen to register the User.

  • I don’t know if it makes a difference, but they’re using keys instead of parentheses to assign inlines. Another thing, that last line of the answer "admin.site.Register(Rule,Ruleadmin)" goes in the admin.py file, although the person who responded did not mention it. But it’s only in this that I can help, I’m not a deep connoisseur of Jango.

1 answer

2

TL;DR

If I understood you do not need the inline, just register the Student and Teacher normally in admin, see if this is it:

py.models:

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

class Aluno(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # Adicionando os campos
    matricula = models.CharField('Matrícula', max_length=12)

    def __str__(self):
        return self.user.username


class Professor(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # Adicionando os campos
    disciplina = models.CharField('Disciplina', max_length=70)

    def __str__(self):
        return self.user.username

admin py.

from django.contrib import admin
from .models import Aluno, Professor

@admin.register(Aluno)
class AlunoAdmin(admin.ModelAdmin):
    model = Aluno
    list_display = ('user', 'matricula',)

@admin.register(Professor)
class ProfessorAdmin(admin.ModelAdmin):
    model = Professor
    list_display = ('user', 'disciplina',)

Your admin screen should look like this:

Tela principal do admin

The inclusion of a Student, for example:

Inclusão de um aluno

These screens captured repl.it, if you want to test there, see the link I leave below, remembering that to run Oce first need to make a project Fork, then, in the frame on the right, need to create the migrations, make the migrate, create a superuser and finally run.

Adding inlines in the User:

With inlines you can achieve on a single screen, in which you can make the inclusion of User, the Professor and the Aluno, but in my opinion, it gets a little strange, see that inlines is to show record(s) of the relationship between one class and another, see that I put in plural, for example when Voce wants to show the student data and his grades over a period. The inline, by default, always comes plural, in this case your inclusion screen User would look like in the figure below (Then add the changes in the code you would have to do for this):

Versão alterando o User no admin

I said it gets weird, why? Because inline in this case will request the two relationships, no matter if you are registering a teacher or a student, will appear the fields for typing the two information, but probably a User will relate to a Professor OR to a Aluno, never both at once, it gets weird.

Note that in this case I just re-registered the User in admin, the other options continue as before, for that just needed to change the file admin.py:

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import Aluno, Professor

class AlunoInline(admin.StackedInline):
    model = Aluno
    can_delete = False
    verbose_name = 'Aluno'

class ProfessorInline(admin.StackedInline):
    model = Professor
    can_delete = False
    verbose_name = 'Professor'

class UserAdmin(BaseUserAdmin):
    inlines = (AlunoInline, ProfessorInline)

# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

@admin.register(Aluno)
class AlunoAdmin(admin.ModelAdmin):
    model = Aluno
    list_display = ('user', 'matricula',)

@admin.register(Professor)
class ProfessorAdmin(admin.ModelAdmin):
    model = Professor
    list_display = ('user', 'disciplina',)

If Voce wants to avoid plural in inline (From Alunos p/ Aluno and/or Professores p/ Professor) adding in models the class Meta, and change the verbose_name_plural, for example:

class Professor(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # Adicionando os campos
    disciplina = models.CharField('Disciplina', max_length=70)

    class Meta:
        verbose_name_plural = 'Professor'

    def __str__(self):
        return self.user.username  

See working on repl.it.

  • So, in this model I need to open another screen to register the user data and select it in the select box. With the inline it appears all the form fields on the screen (what I want).

  • Okay, you can do it with the inline, but like you said you want a separate screen for each model I can’t see how, with the inline to do but with all the models that are related to the user on the same screen (or you would have to register the User of Django more than once, n know if Django allows it), serves so?

  • Then I must have expressed myself wrong, I’m sorry. What I need is all the fields on the same screen without having to open a different screen, just what the inline offers. The problem is that I can’t get student/teacher data to be on the same screen as User access data.

  • @Fláviofilipe I edited the answer, adding inlines in the User, see if this is it.

Browser other questions tagged

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