Search code examples
djangodjango-modelsaccessordjango-tables2

Display misconception in django-tables2


After creating a custom user model in my app, I have a studentProfile that inherits from the user model, which also contains avatar, semester, and dept_name. which works fine. However, when I was trying to display this studentProfile data using django-tables2, all rows keeps showing "-" and the ID been captured is from user model instead of studentProfile.

The weirdiest thing is i can get all the values from user model correctly even when studentProfile is my table model for django-tables2

I don't know what I am doing wrongly. Any help is really appreciated

my model definitions are as follow

class DepartmentData(models.Model):
    fid = models.ForeignKey(FacultyData, on_delete=models.CASCADE)
    dept_name = models.CharField(max_length=50)
    created_on = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.dept_name



class User(AbstractBaseUser):

    # add additional fields here
    user_id = models.CharField(max_length=15, unique=True)
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    active = models.BooleanField(default=True)# can login
    staff = models.BooleanField(default=False)  # staff user non superuser
    admin = models.BooleanField(default=False)  # superuser

    USER_TYPE_CHOICES = (
        (1, 'student'),
        (2, 'lecturer'),
        (3, 'bursary'),
        (4, 'system'),
        (5, 'admin'),
    )

    user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES)
    USERNAME_FIELD = 'user_id'
    REQUIRED_FIELDS = ['first_name', 'last_name', 'user_type']

    objects = UserManager()

    def __str__(self):
        return self.user_id

    def get_full_name(self):
        return self.first_name + " " + self.last_name

    def get_user_type(self):
            return self.user_type

    def has_perm(self, perm, obj=None):
        return True

    def has_module_perms(self, app_label):
        return True


    @property
    def is_staff(self):
        return self.staff

    @property
    def is_admin(self):
        return self.admin
    @property
    def is_active(self):
        return self.active


class StudentProfile(models.Model):
    user = models.OneToOneField(User,on_delete=models.CASCADE)
    semester = models.ForeignKey(SemesterData, on_delete=models.SET_NULL, null=True)
    dept_name = models.ForeignKey(DepartmentData, on_delete=models.SET_NULL, null=True)
    avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)

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

class SemesterData(models.Model):
    sid = models.ForeignKey(SessionData, on_delete=models.CASCADE)
    semester_name = models.CharField(max_length=50)

    def __str__(self):
            return self.semester_name

    def current(self):

        if SettingsData.objects.all().count():
            st = SettingsData.objects.get(id=1)
            if self.id == st.current_id:
                return "Current Session-Semester"
            else:
                return format_html('<a href="{}"  class="btn btn-primary btn-sm">{}</a>', reverse('system:current_session_semester', args=[self.id]),
                                   'Set Current')
        else:
                return format_html('<a href="{}" class="btn btn-primary">{}</a>', reverse('system:current_session_semester', args=[self.id]),
                                   'Set Current')

here is my table.py

class StudentTable(tables.Table):

    user_id = tables.Column(attrs = {'th': {'class': 'danger'}})
    first_name = tables.Column(attrs = {'th': {'class': 'danger'}})
    last_name = tables.Column(attrs = {'th': {'class': 'danger'}})

    avatar = tables.Column(accessor ="user", verbose_name = "ass" )



    active = tables.Column(attrs = {'th': {'class': 'danger'}})

    last_login = tables.Column(attrs = {'th': {'class': 'danger'}})
    edit_Action = tables.LinkColumn('system:semester_edit', text='Edit', args=[A('pk')],attrs={'a':{'class':'btn btn-info btn-sm'}, 'td':{'align': 'center'}, 'th': {'class': 'danger'}}, orderable=False)

    class Meta:
        model = StudentProfile
        attrs = {'class':'table table-hover table-bordered table-responsive'}
        sequence = ('user_id', 'first_name', 'last_name', 'avatar')
        exclude = {'id', 'user', 'password', 'staff', 'admin'}
        empty_text = _("There are no students yet")
        template_name = 'django_tables2/bootstrap4.html'

I would love to get the department_name, semester_name as well as fields in the studentProfile which is serving as my table model


Solution

  • You are seeing empty values for all fields with your current configuration because you're trying to access fields user_id, first_name and last_name which are not fields of the StudentProfile model, but rather fields of the User model (to which StudentProfile is related by user field).

    That being said, you should access those fields via the user relation, something like this:

    class StudentTable(tables.Table):
        user_id = tables.Column(accessor='user.user_id', ...)
        first_name = tables.Column(accessor='user.first_name', ...)
        last_name = tables.Column(accessor='user.last_name', ...)
        ...
    

    As far as the DepartmentData and SemesterData relations go, I'm not sure why aren't they displayed by default, since they are fields of the StudentProfile model, and they aren't excluded via the exclude property on the Meta. You can maybe try to explicitly list them in the fields property and see if that helps.