djangodjango-viewsdjango-templatesbootstrap-cards

Rendering data on the same template from different models


I want to render data on the same template(shared template) from different models I have the following models in models.py


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

class CustomUser(AbstractUser):
    """
    Custom user model to support role-based authentication.
    """

    USER_TYPE_CHOICES = [
        ('client', 'Client'),
        ('staff', 'Staff'),
        ('admin', 'Admin'),
    ]
    
    user_type = models.CharField(max_length=10, choices=USER_TYPE_CHOICES, default='client')
    phone = models.CharField(max_length=15, blank=True, null=True)
    email = models.EmailField(unique=True)
    address = models.CharField(max_length=255, blank=True, null=True)

    # Specify unique related_name for groups and user_permissions
    user_groups = models.ManyToManyField(
        'auth.Group',
        related_name='custom_user_groups',
        blank=True,
        verbose_name='groups',
        help_text='The groups this user belongs to.',
    )

    user_permissions = models.ManyToManyField(
        'auth.Permission',
        related_name='custom_user_permissions',
        blank=True,
        verbose_name='user permissions',
        help_text='Specific permissions for this user.',
    )

    def get_user_type_display(self):
        """
        Display the user type in a more readable format.
        """
        return dict(CustomUser.USER_TYPE_CHOICES)[self.user_type]

    class Meta:
        swappable = 'AUTH_USER_MODEL'






class GarbageCollectionRequest(models.Model):
    """
    Represents a request for garbage collection made by a client.
    """

    client = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='garbage_requests')
    request_date = models.DateTimeField(auto_now_add=True)
    request_details = models.TextField(max_length=255)
    address = models.CharField(max_length=255)
    phone = models.CharField(max_length=15, blank=True, null=True)
    email = models.EmailField()
    is_assigned = models.BooleanField(default=False)
    collection_date = models.DateTimeField(blank=True, null=True)

    def __str__(self):
        return f"Request #{self.pk} - {self.client.username} - {self.address}"

And my class-based views.py

from django.shortcuts import render, redirect


from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import CustomUser, GarbageCollectionRequest, CollectionAssignment, GarbageCollectionLog, Payment


class CustomUserListView(ListView):
    model = CustomUser
    template_name = 'admin_dash.html'


class GarbageCollectionRequestListView(ListView):
    model = GarbageCollectionRequest
    template_name = 'garbage/admin_dash.html'
    ordering = ('-request_date')

my admin_dash.html which i have extended from main.html

{% extends 'garbage/main.html' %}
{% load static %}
{% block title %} Admin Dashboard {% endblock title %}

{% block content %}

<div class="main--content">
    <br><br>
    <div class="overview">
        <div class="title">
            <h2 class="section--title">Overview</h2>
            <select name="date" id="date" class="dropdown">
                <option value="today">Today</option>
                <option value="lastweek">Last Week</option>
                <option value="lastmonth">Last Month</option>
                <option value="lastyear">Last Year</option>
                <option value="alltime">All Time</option>
            </select>
        </div>
        <div class="cards">
            <div class="card card-1">
                <div class="card--data">
                    <div class="card--content">
                        <h5 class="card--title">Requests</h5>
                        <h1>152</h1>
                    </div>
                    <i class="ri-user-2-line card--icon--lg"></i>
                </div>
                <div class="card--stats">
                    <span><i class="ri-bar-chart-fill card--icon stat--icon"></i>65%</span>
                    <span><i class="ri-arrow-up-s-fill card--icon up--arrow"></i>10</span>
                    <span><i class="ri-arrow-down-s-fill card--icon down--arrow"></i>2</span>
                </div>
            </div>
            <div class="card card-2">
                <div class="card--data">
                    <div class="card--content">
                        <h5 class="card--title">Assigned</h5>
                        <h1>1145</h1>
                    </div>
                    <i class="ri-user-line card--icon--lg"></i>
                </div>
                <div class="card--stats">
                    <span><i class="ri-bar-chart-fill card--icon stat--icon"></i>82%</span>
                    <span><i class="ri-arrow-up-s-fill card--icon up--arrow"></i>230</span>
                    <span><i class="ri-arrow-down-s-fill card--icon down--arrow"></i>45</span>
                </div>
            </div>
            <div class="card card-3">
                <div class="card--data">
                    <div class="card--content">
                        <h5 class="card--title">Completed</h5>
                        <h1>102</h1>
                    </div>
                    <i class="ri-calendar-2-line card--icon--lg"></i>
                </div>
                <div class="card--stats">
                    <span><i class="ri-bar-chart-fill card--icon stat--icon"></i>27%</span>
                    <span><i class="ri-arrow-up-s-fill card--icon up--arrow"></i>31</span>
                    <span><i class="ri-arrow-down-s-fill card--icon down--arrow"></i>23</span>
                </div>
            </div>
            <div class="card card-4">
                <div class="card--data">
                    <div class="card--content">
                        <h5 class="card--title">Pending</h5>
                        <h1>15</h1>
                    </div>
                    <i class="ri-hotel-bed-line card--icon--lg"></i>
                </div>
                <div class="card--stats">
                    <span><i class="ri-bar-chart-fill card--icon stat--icon"></i>8%</span>
                    <span><i class="ri-arrow-up-s-fill card--icon up--arrow"></i>11</span>
                    <span><i class="ri-arrow-down-s-fill card--icon down--arrow"></i>2</span>
                </div>
            </div>
        </div>
    </div>


    <div class="doctors">
        <div class="title">
            <h2 class="section--title">Clients</h2>
            <div class="doctors--right--btns">
                <select name="date" id="date" class="dropdown doctor--filter">
                    <option >Filter</option>
                    <option value="free">Free</option>
                    <option value="scheduled">Scheduled</option>
                </select>
                <button class="add"><i class="ri-add-line"></i>Add Client</button>
            </div>
        </div>
        <div class="doctors--cards">

            <!--Rendering clients ---->
            {% for user in custom_users %}
                
                    <a href="#" class="doctor--card">
                        <div class="img--box--cover">
                            <div class="img--box">
                                <img src="" alt="">
                            </div>
                        </div>
                        <p class="free">Free</p>
                    </a>
                
            {% endfor %}
        </div>
    </div>

    <div class="recent--patients">
        <div class="title">
            <h2 class="section--title">Recent Requests</h2>
            <button class="add"><i class="ri-add-line"></i>Add Request</button>
        </div>
        <div class="table">
            <table>
                <thead>
                    <tr>
                        <th>Client</th>
                        <th>Date in</th>
                        <th>Address</th>
                        <th>Phone</th>
                        <th>Assigned</th>
                        <th>Collection Date</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                    <!--Rendering requests ---->
                    {% for request in object_list %} 
                        <tr>
                            <td>{{ request.client.username }}</td>
                            <td>{{ request.request_date }}</td>
                            <td>{{ request.address }}</td>
                            <td>{{ request.phone }}</td>
                            <td>{{ request.is_assigned }}</td>
                            <td class="pending">{{ request.collection_date }}</td>
                            <td><span><i class="ri-edit-line edit"></i><i class="ri-delete-bin-line delete"></i></span></td>
                        </tr>
                    {% endfor %}
            
                </tbody>
            </table>
        </div>
    </div>
</div>


{% endblock content %}

rendering requests in a table format am satisfied with it at the moment:

<div class="table">
            <table>
                <thead>
                    <tr>
                        <th>Client</th>
                        <th>Date in</th>
                        <th>Address</th>
                        <th>Phone</th>
                        <th>Assigned</th>
                        <th>Collection Date</th>
                        <th>Action</th>
                    </tr>
                </thead>
                <tbody>
                    <!--Rendering requests ---->
                    {% for request in object_list %} 
                        <tr>
                            <td>{{ request.client.username }}</td>
                            <td>{{ request.request_date }}</td>
                            <td>{{ request.address }}</td>
                            <td>{{ request.phone }}</td>
                            <td>{{ request.is_assigned }}</td>
                            <td class="pending">{{ request.collection_date }}</td>
                            <td><span><i class="ri-edit-line edit"></i><i class="ri-delete-bin-line delete"></i></span></td>
                        </tr>
                    {% endfor %}
            
                </tbody>
            </table>
        </div>

NB: Am not getting any errors I added a method on CustomUser model


def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['custom_users'] = CustomUser.objects.all()
        return context

to return data that is passed to the template and modified the part i want to render the clients in the template using bootstrap like cards:

<div class="doctors--cards">

            <!--Rendering clients ---->
            {% for client in custom_users %}
                {% if client.user_type == 'client' %}
                    <a href="#" class="doctor--card">
                        <div class="img--box--cover">
                            <div class="img--box">
                                <img src="" alt="">
                            </div>
                        </div>
                        <p class="free">Free</p>
                    </a>
                {% endif %}
            {% endfor %}
        </div>

but i seen not to archive that< any advise and suggestions how i acn go about? I have also added a screenshot of the progress so.


Solution

  • I added a method on CustomUser model

    The method get_context_data has to be used in a class based view, not in a model. You should add it to your GarbageCollectionRequestListView. Then custom_users variable will be available in your template (but only for the garbage collection request list).

    In order to use the same template for garbage collection, you'll have to modify CustomUserListView like this :

    class CustomUserListView(ListView):
        model = CustomUser
        template_name = 'admin_dash.html'
        context_object_name = 'custom_users'
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['object_list'] = GarbageCollectionRequest.objects.all()
            return context
    

    context_object_name property indicates the name to provide to the users list variable.