Cannot assign "'Maria'": "Student.name_mae" must be a "Student" instance. When I try to access a student subclass field

Asked

Viewed 225 times

5

I have a system with multiple users, I decided to make inheritance of Django’s default user, I have two users: student and teacher, which has several characteristics in common, so I created a base class User and the subclasses Pupil and Professor.

account/models.py

class User(AbstractBaseUser, PermissionMixin):
    username = models.CharField('Usuário', max_length=30, unique=True,
        validators=[validators.RegexValidator(re.compile('^[\w.@+-]+$'),
            'O nome de usuário só pode conter letras, digitos ou os '
            'seguintes caracteres: @/./+/-/_', 'invalid')]
    )

    nome = models.CharField('Nome', max_length=100)
    email = models.EmailField('E-mail', unique=True) # blank=True?
    instituicao = models.CharField('Instituição', max_length=200)
    SEXO_CHOICE = ((0, 'Masculino'), (1, 'Feminino'))
    sexo = models.IntegerField('Sexo', choices=SEXO_CHOICE, default=0)
    imagem_perfil = models.ImageField('Imagem do perfil', upload_to='media/img/%Y/%m/%d', blank=True)
    is_active = models.BooleanField('Está ativo?', blank=True, default=True)
    is_staff = models.BooleanField('É administrador?', blank=True, default=False)
    date_joined = models.DateTimeField('Data de Entrada', auto_now_add=True)

    objects = UserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    def __str__(self):
        return self.nome

    def get_short_name(self):
        return str(self)

    def get_full_name(self):
        return self.nome

    class Meta:
        verbose_name = 'Usuário'
        verbose_name_plural = 'Usuários'

student/models.py

class Aluno(User):
    nome_mae = models.CharField('Nome da Mãe ', max_length=100)

    class Meta:
        verbose_name = 'Aluno'
        verbose_name_plural = 'Alunos'

professor/models.py

class Professor(User):
    endereco = models.CharField('Endereço', max_lenght=100)

    class Meta:
        verbose_name = 'Professor'
        verbose_name_plural = 'Professores'

py views.

def dashboard_aluno(request):
    user = User.objects.all()
    aluno = Aluno.objects.all()
    professor = Professor.objects.all()
    print(user)
    print(aluno)# o erro acontece nessa linha
    print(professor)
    turma_aluno = Turma.objects.filter(alunos__id__contains=request.user.id)
    disciplina_aluno = Disciplina.objects.filter(turmas__id__contains=turma_aluno[0].id)
    template_name = 'dashboard_aluno.html'
    context = {'turma_aluno': turma_aluno, 'disciplina_aluno': disciplina_aluno}
    return render(request, template_name, context)

I can log in with both types of users, but when I try to access information that is only one of the types of users, for example the field name_mae user’s Pupil i get the bug:

Traceback:

File "/home/andre/andre/ifce/iniciacaocientifica/rede_social/projeto/venv/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/andre/andre/ifce/iniciacaocientifica/rede_social/projeto/venv/lib/python3.4/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  21.                 return view_func(request, *args, **kwargs)
File "/home/andre/andre/ifce/iniciacaocientifica/rede_social/projeto/rede_social/conta/views.py" in dashboard_aluno
  18.     print(aluno)
File "/home/andre/andre/ifce/iniciacaocientifica/rede_social/projeto/venv/lib/python3.4/site-packages/django/db/models/query.py" in __repr__
  116.         data = list(self[:REPR_OUTPUT_SIZE + 1])
File "/home/andre/andre/ifce/iniciacaocientifica/rede_social/projeto/venv/lib/python3.4/site-packages/django/db/models/query.py" in __iter__
  141.         self._fetch_all()
File "/home/andre/andre/ifce/iniciacaocientifica/rede_social/projeto/venv/lib/python3.4/site-packages/django/db/models/query.py" in _fetch_all
  966.             self._result_cache = list(self.iterator())
File "/home/andre/andre/ifce/iniciacaocientifica/rede_social/projeto/venv/lib/python3.4/site-packages/django/db/models/query.py" in iterator
  275.                     obj = model(*row_data)
File "/home/andre/andre/ifce/iniciacaocientifica/rede_social/projeto/venv/lib/python3.4/site-packages/django/db/models/base.py" in __init__
  382.                 setattr(self, field.attname, val)
File "/home/andre/andre/ifce/iniciacaocientifica/rede_social/projeto/venv/lib/python3.4/site-packages/django/db/models/fields/related.py" in __set__
  454.                     self.related.opts.object_name,

Exception Type: ValueError at /conta/dashboard_aluno/
Exception Value: Cannot assign "'Maria'": "Aluno.nome_mae" must be a "Aluno" instance.

I’m new to Django, so any advice or tip I’d be happy to take. I am using version 1.7.7 and python 3.4

Ps.: This is the best way to have multiple users?

  • You just put the template, put also the part of the code that is generating the error.

  • That one UserManager is something of Django’s own or did you create it? What does it do? It has how to put the stack trace error whole in question, instead of only the message? Apparently you created the query set normally (using objects.all()) but at the time of executing it gave some problem. My only guess is that it may be a problem in the Manager. I have no experience with recent versions of Django (after 1.5), so I can’t tell you whether or not it’s right to make subclasses of User this way. Why not instead create a separate template with OneToOneField for User?

  • @mgibsonbr the 'Usermanaget' is Django’s own, basically this says which Manager(create user and superuser) I will use, in this case I use Django’s own. I thought about creating with Onetoonefield but I thought about DRY, since my project will be much more complex.

  • 1

    I don’t see any additional complexity - a "subclass" is simply an extra table whose primary key is also a foreign key to another table... Even call User.objects.all() returns all users - including students and teachers - but you only have access to class fields User. That is, the difficulty to use is more or less the same. In time: I’m not saying that doing subclass is bad, I’m just saying that me I have no experience with recent versions of Django to give an opinion on this practice.

1 answer

1


After a week of searching, discover that the error was in creating the subclasses Professor and Aluno in different apps. I solved the problem by creating subclasses in the same base class file User:

account/models.py

class User(AbstractBaseUser, PermissionMixin):
    username = models.CharField('Usuário', max_length=30, unique=True,
        validators=[validators.RegexValidator(re.compile('^[\w.@+-]+$'),
            'O nome de usuário só pode conter letras, digitos ou os '
            'seguintes caracteres: @/./+/-/_', 'invalid')]
    )

    nome = models.CharField('Nome', max_length=100)
    email = models.EmailField('E-mail', unique=True) # blank=True?
    instituicao = models.CharField('Instituição', max_length=200)
    SEXO_CHOICE = ((0, 'Masculino'), (1, 'Feminino'))
    sexo = models.IntegerField('Sexo', choices=SEXO_CHOICE, default=0)
    imagem_perfil = models.ImageField('Imagem do perfil', upload_to='media/img/%Y/%m/%d', blank=True)
    is_active = models.BooleanField('Está ativo?', blank=True, default=True)
    is_staff = models.BooleanField('É administrador?', blank=True, default=False)
    date_joined = models.DateTimeField('Data de Entrada', auto_now_add=True)

    objects = UserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    def __str__(self):
        return self.nome

    def get_short_name(self):
        return str(self)

    def get_full_name(self):
        return self.nome

class Meta:
    verbose_name = 'Usuário'
    verbose_name_plural = 'Usuários'

class Aluno(User):
    nome_mae = models.CharField('Nome da Mãe ', max_length=100)

    class Meta:
        verbose_name = 'Aluno'
        verbose_name_plural = 'Alunos'

class Professor(User):
    endereco = models.CharField('Endereço', max_lenght=100)

    class Meta:
        verbose_name = 'Professor'
        verbose_name_plural = 'Professores'

Browser other questions tagged

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