djangodjango-modelsdjango-admindjango-admin-toolsdjango-admin-actions

How can I display image in admin.py and one of my field in employee table is not appearing correct in admin.py?


I am working on creating Employee monitoring system. I have 3 models right now. Here they are

class User(models.Model):
    username= models.CharField(max_length=256, verbose_name='Username')
    first_name = models.CharField(max_length=256, verbose_name='First Name')
    last_name = models.CharField(max_length=256, verbose_name='Last Name')
    email=models.EmailField(max_length=256, verbose_name='Email')

    def __str__(self):
        return self.first_name + self.last_name

class Departments(models.Model):
    department_name= models.CharField(max_length=256, verbose_name='Departments')

    def __str__(self):
        return self.department_name


class Designation(models.Model):
    department_name= models.ForeignKey(Departments, on_delete=models.CASCADE)
    designation_name=models.CharField(max_length=256, verbose_name='Designation')

    def __str__(self):
        return '{} {}'.format(self.department_name, self.designation_name)

class Employee(models.Model):
    user= models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True,)
    department_name= models.ForeignKey(Departments, on_delete=models.CASCADE)
    designation_name= models.ForeignKey(Designation, on_delete=models.CASCADE)
    salary= models.FloatField(null=False, default=0.0, verbose_name='Salary')
    image = models.ImageField(upload_to = 'employee_images', null=True, blank=True)

    def __str__(self):
        return '{} {} {}'.format(self.user.first_name + self.user.last_name, self.department_name.department_name, self.designation_name.designation_name)

    def image_tag(self):
        return mark_safe('<img src="/employee_images/%s" width="150" height="150" />' % (self.image))
    image_tag.short_description = 'Image'


my return self.first_name +self.last_name in def __str__(self) of employee table is not giving me any gap between these two names. I don't know how to do it.

and I have tried every method suggested by everyone on this website to display image on admin.py but I am unable to display them. Here is my admin.py

admin.py

@admin.register(Employee)
class EmployeeAdmin(admin.ModelAdmin):
    list_display= ('first_name', 'last_name', 'designation_name', 'department', 'salary', 'image_tag')
    def first_name(self, obj):
        return obj.user.first_name
    
    def last_name(self, obj):
        return obj.user.last_name

    def designation_name(self, obj):
        return obj.designation.designation_name
    
    def department(self, obj):
        return obj.department_name.department_name


and one last thing my designation_name is not only returning me designation_name but also department_name as well. I just want designation_name to be appeared.


Solution

  • For future - in one Question on StackOverflow include only one question. Multiple issues should be divided in few topics.

    When you add strings, they are connected without gap. Using format funtion is not usually the best way to insert variables into a string. You can resolve it in two ways:

    # now
    def __str__(self):
        return '{} {} {}'.format(self.user.first_name + self.user.last_name, self.department_name.department_name, self.designation_name.designation_name)
    
    # solution 1
    def __str__(self):
        return '{} {} {} {}'.format(self.user.first_name, self.user.last_name, self.department_name.department_name, self.designation_name.designation_name)
    
    # solution 2
    def __str__(self):
        return f'{self.user.first_name} {self.user.last_name} {self.department_name.department_name} {self.designation_name.designation_name}'
    

    About designation_name. Look what you wrote in __str__ method in Designation model.

    class Designation(models.Model):
        ...    
        def __str__(self):
            return '{} {}'.format(self.department_name, self.designation_name)
    

    Just replace '{} {}'.format(self.department_name, self.designation_name) with simple self.designation_name and it will be fine.

    And finally the admin image. According to this: https://books.agiliq.com/projects/django-admin-cookbook/en/latest/imagefield.html your admin.py might look similar to that:

    @admin.register(Employee)
    class EmployeeAdmin(admin.ModelAdmin):
    
        readonly_fields = ["show_image"]
        def show_image(self, obj):
            return mark_safe('<img src="{url}" width="{width}" height={height} />'.format(
                url=obj.image.url,
                width=obj.image.width,
                height=obj.image.height,
                )
            )
    
        list_display= ('first_name', 'last_name', 'designation_name', 'department', 'salary', 'image')
    
        def first_name(self, obj):
            return obj.user.first_name
        
        def last_name(self, obj):
            return obj.user.last_name
    
        def designation_name(self, obj):
            return obj.designation.designation_name
        
        def department(self, obj):
            return obj.department_name.department_name