user11673317
user11673317

Reputation:

how to filter data by foreign key value in template

I have two model called organization and staff.Staff model have onetoone relation with user and Foreignkey relation to the organization.The problem what i got is to filter the staffs by their related organization.I have tried liked this but didn't worked out.

models.py

class Staff(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user')
    name = models.CharField(max_length=255, blank=True, null=True)
    organization = models.ForeignKey(Organization, on_delete=models.SET_NULL, blank=True, null=True,
                                     related_name='organization')

.....other fields.....

views.py

def view_staff_users(request):
    staff_users = User.objects.filter(is_staff=True)
    organizations = Organization.objects.all()
    staffs_by_org = Staff.objects.select_related('organization')
     # tried this also:
    # staffs_by_org = []
    # print('staffff',staffs_by_org)
    # for organization in organizations:
    #     staffs = Staff.objects.filter(organization=organization)
    #     staffs_by_org.extend(staffs)
    #     print('staaa',staffs_by_org)

Edited views:

def view_staff_users(request):
staff_users = User.objects.filter(is_staff=True)
organizations = Organization.objects.all()
staffs_by_org = []
for organization in organizations:
        staffs_by_org = Staff.objects.filter(organization__name=organization).select_related('organization')

template

 {% for user in staffs_by_org %}
   # tried this also: {% for u in user.organization_set.all %}
   {{user.user.name}}
   {{user.username}}
   {{user.email}}
   {{user.user.organization}}

 {% endfor %}

Edit: My template looks like this.

    <ul class="nav nav-tabs customtab" role="tablist">
        <li class="nav-item"> <a class="nav-link active" data-toggle="tab" href="#all" role="tab"><span class="hidden-sm-up"></span> <span class="hidden-xs-down">All Staffs</span></a> </li>
{% for organization in organizations %}
     <li class="nav-item"> <a class="nav-link" data-toggle="tab" href="#{{organization.name}}" role="tab"><span class="hidden-sm-up"></span> <span class="hidden-xs-down">{{organization.name}}</span></a> </li>
{% endfor %}

    </ul>
          <div class="tab-content">
        <div class="tab-pane active" id="all" role="tabpanel">
             {% for user in staff_users %}

               {{user.user.name}}
               {{user.username}}
               {{user.email}}
               {{user.user.organization}}

             {% endfor %}
             </div>
        {% for organization in organizations %}
        <div class="tab-pane tab" id="{{organization.name}}" role="tabpanel">
         {% endfor %}
         {% for user in staffs_by_org %}
               # tried this also: {% for u in user.organization_set.all %}
               {{user.user.name}}
               {{user.username}}
               {{user.email}}
               {{user.user.organization}}

             {% endfor %}
        </div>

Upvotes: 1

Views: 560

Answers (2)

Original BBQ Sauce
Original BBQ Sauce

Reputation: 696

I think one problem is that you created a loop that is rewriting itself instead of appending each batch of staff users to your queryset.

One way to do what you want (return all staff that belong to a set of organizations) is to use the in filter operator.

So, in your views.py:

organizations = Organization.objects.all()
staffs_by_org = Staff.objects.filter(
    organization__in=organizations).select_related('organization')

This will return all staff from whatever organizations is. If you want a dynamic filter for the organization name, then what you have to do is:

  1. Pass the organization name to the request. This is usually done via URL parameters or query strings.
  2. Change the organizations variable from objects.all() to objects.filter(URL_PARAMETER)

Then staffs_by_org will only return the staff from that organization.

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477035

You can filter for example with:

staffs_by_org = Staff.objects.filter(
    organization__name='My organization'
).select_related('organization')

The staffs_by_org is a QuerySet of Staffs. I therefore stronly advice to use staff in the iterator. You can access the organization with staff.organization:

{% for staff in staffs_by_org %}
   {{ staff.name }}
   {{ staff.user.username }}
   {{ staff.user.email }}
   {{ staff.organization }}
{% endfor %}

If the organization has for example a name, you can render it with:

{% for staff in staffs_by_org %}
   {{ staff.name }}
   {{ staff.user.username }}
   {{ staff.user.email }}
   {{ staff.organization.name }}
{% endfor %}

Note that the related_name of a ForeignKey is the name of the relation in reverse. A better name is probably 'staff'. If you refer to the user model, it is better to use get_user_model() [Django-doc], since if you later change your mind, you can easily use another user model.

from django.contrib.auth import get_user_model

class Staff(models.Model):
    user = models.OneToOneField(
        get_user_model(),
        on_delete=models.CASCADE,
        related_name='staff'
    )
    name = models.CharField(max_length=255, blank=True, null=True)
    organization = models.ForeignKey(
        Organization,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        related_name='staff'
    )

Upvotes: 1

Related Questions