Error Displaying User profiles in filtered format

I created these two class based views to display the profiles of registered users according to their gender, to an authenticated user. here is the code #views.py
class FemaleUserList(LoginRequiredMixin, generic.ListView):
queryset = Profile.objects.filter(gender=‘Female’).order_by(’-age’)
template_name = ‘users/female_user_profiles.html’
context_object_name = ‘female_users’
paginate_by = 6

class MaleUserList(LoginRequiredMixin, generic.ListView):
queryset = Profile.objects.filter(gender=‘Male’).order_by(’-age’)
template_name = ‘users/male_user_profiles.html’
context_object_name = ‘male_users’
paginate_by = 6

I know there is a better way to this since am basically repeating myself but then it was working fine with a template tag like this in #male_user_profiles.html


{% for profile in male_users %}

{{ user.username }}



{{ user.username }}





BIO: {{ user.profile.bio }}

Age : {{ user.profile.age }}




Gender : {{ user.profile.gender }}




Interested In : {{ user.profile.interested_in }}




Studying : {{ user.profile.discipline }}




At : {{ user.profile.campus }}




Relationship Status : {{ user.profile.status }}




Enjoys : {{ user.profile.hobbies }}



Start Chat with {{ user.username }}



{% endfor %}
I have the same html code for female_user_profiles.html, with different urls patterns for each.

but now all it does is to list the profile of only the logged in user and then repeats the same profile details for a number of times that corresponds to the number of registered users of that gender instead of looping through the details of each user I simply don’t know how to fix this bug, since it was working initially.

(Side note: When you’re posting code or template fragments, please enclose it between lines consisting of only three backtick - ` characters. This means you’ll have one line that is only ```, followed by the lines of code (or template), followed by another line of ```. Make sure you use the backtick - ` and not the apostrophe - '. Please edit your post for this. It makes everything a lot easier to read.)

In addition to making sure the complete view is posted, please also post your Profile object.

Also, you mentioned that it was working initially, but now it’s not working. What was the change you made between then and now?

Ken

There is no edit link on the topic, and I have no permission to delete it and create a new one with the corrections you gave. Thank you

this is my profile object in #models.py

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    avatar = models.ImageField(default='default2.PNG', upload_to='profile_pics/')
    age = models.IntegerField(default=18, validators=[MinValueValidator(18)])
    status = models.CharField(choices=CONDITION, default='Single', max_length=20)
    gender = models.CharField(choices=GENDER, default='Male', max_length=10)
    interested_in = models.CharField(choices=INTEREST, max_length=10)
    campus = models.CharField(max_length=200)
    discipline = models.CharField(max_length=300)
    level = models.CharField(choices=LEVEL, max_length=50)
    bio = models.TextField()
    hobbies = models.CharField(max_length=200)

    def __str__(self):
        return f'{self.user.username} Profile'

the only change I recall making to the code before I started noticing the issue, is adding a 1px border to the templates like in #female_user_profiles.html

{% extends 'blog/base.html' %}
{% load postman_tags %}
{% block content %}
  <div class="container-fluid" style="border:1px solid #fd7e14;">
      <div class="py-5 text-center">
        {% for profile in female_users %}
          <div class="card" style="width:600px">
              <div class="card-img-top"><img class="rounded-circle" src="{{ user.profile.avatar.url }}" alt="{{ user.username }}" width="300px"></div>
              <hr>
              <h3>{{ user.username }}</h3>
             <div class="card-body">
                  <p class="lead">
                    <div class="media-body">
                         <div class="card-text">BIO: {{ user.profile.bio }}</div>
                         <p>Age : {{ user.profile.age }}</p>
                         <hr>
                         <p>Gender : {{ user.profile.gender }}</p>
                         <hr>
                         <p>Interested In : {{ user.profile.interested_in }}</p>
                         <hr>
                         <p>Studying : {{ user.profile.discipline }}</p>
                         <hr>
                         <p>At : {{ user.profile.campus }}</p>
                         <hr>
                         <p>Relationship Status : {{ user.profile.status }}</p>
                         <hr>
                         <p>Enjoys : {{ user.profile.hobbies }}</p>
                    </div>
                    <a class="btn btn-default" href="{% url 'postman:write' %}"><i class="fa fa-envelope"></i>Start Chat with {{ user.username }}</a>
                  </p>
             </div>
          </div>
          <hr>
          <hr>
        {% endfor %}...

but even when I removed the border, the issue persisted. I will appreciate if someone shows me a better way to display the user profiles according to their gender without writing two views, urls, et’c

The reason you’re always seeing the user’s profile is due to specifying user.profile.<field name> in your template.
Your loop tag, {% for profile in female_users %} means that those above specifications should be {{ profile.<field name> }}.

Regarding the simplifications of the views, I’d like to see the URLs that refer to these views and a brief description of how those URLs get presented to the user for selection. (I don’t need to see the entire template.) In other words, what event or choice is made causing one to be displayed vs the other?

The basic idea for simplification would be to first consider whether or not you need to use two different context_object_names, thereby needing two different templates. (I don’t see anything gender-specific in the template.)
Then, instead of having two different queryset variables, I’d override the get_queryset function to apply a filter of either Male or Female depending upon a parameter supplied to the view.

1 Like

Thanks Ken, for the feedback so far. here is the URL patterns for both views

path('male-user-profiles/', user_views.MaleUserList.as_view(), name='male_user_list'),
path('female-user-profiles/', user_views.FemaleUserList.as_view(), name='female_user_list'),

and this where I created a link to those pages on my index.html file

<div class="sb-sidenav-menu-heading">Login Features</div>
                            <a class="nav-link" href="{% url 'female_user_list' %}">
                                <div class="sb-nav-link-icon"><i class="fas fa-chart-area"></i></div>
                                Female category
                            </a>
                            <a class="nav-link" href="{% url 'male_user_list' %}">
                                <div class="sb-nav-link-icon"><i class="fas fa-table"></i></div>
                                Male category
                            </a>

Ok, so one way this can all be simplified is as I described above. Starting with the urls:

path('user-profiles/<str:gender>/', user_views.UserList.as_view(), name='user_list'),

the template:

<div class="sb-sidenav-menu-heading">Login Features</div>
  <a class="nav-link" href="{% url 'user_list' 'Female' %}">
  <div class="sb-nav-link-icon"><i class="fas fa-chart-area"></i></div>
       Female category
  </a>
  <a class="nav-link" href="{% url 'user_list' 'Male' %}">
  <div class="sb-nav-link-icon"><i class="fas fa-table"></i></div>
      Male category
  </a>

The above now converts the gender being requested into a parameter for the view:

class UserList(LoginRequiredMixin, generic.ListView):
    def get_queryset(self):
        return Profile.objects.filter(gender=self.kwargs['gender']).order_by(’-age’)

    template_name = ‘users/user_profiles.html’
    context_object_name = ‘selected_users’
    paginate_by = 6

This way, you only need one template as well.

1 Like

This simplification looks cool, thanks. But I tried to use it and the View function keeps giving errors on my pycharm editor…something about needing an indented block and also that the ‘return’ statement is out of the function. I doubled checked to see if the copy and paste altered the typing format but it was same as yours.
I also tried to replace the ‘user.profile.object’ with ‘profile.object’ as you suggested, and it seems to be working but then I can’t get the username with ‘profile.username’ since it is not a profile object, and using only ‘{{ username }}’ returned nothing. meanwhile leaving it as {{ user.username }} returned the same username of the authenticated user for all the different profiles. please is there another way to get the username of the different registered users. thanks for your help so far.

Regarding the view function, yes, the error is mine. The return statement needs to be indented.

Regarding the profile objects, I’d need to see what your current template is now that’s not working.

1 Like

using the simplified form of the code returns a completely blank page when I click on any of the links on the homepage.This is the template that am using

{% extends 'blog/base.html' %}
{% load postman_tags %}
{% block content %}
 <div class="container-fluid" style="border:1px solid #fd7e14;">
      <div class="py-5 text-center">
        {% for profile in selected_users %}
          <div class="card" style="width:600px">
                <div class="card-img-top"><img class="rounded-circle" src="{{ profile.avatar.url }}" alt="{{ username.instance }}" width="300px"></div>
              <hr>
               <h3>{{ profile.username }}</h3>
                <div class="card-body">
                  <p class="lead">
                    <div class="media-body">
                         <div class="card-text">BIO: {{ profile.bio }}</div>
                         <p>Age : {{ profile.age }}</p>
                         <hr>
                         <p>Gender : {{ profile.gender }}</p>
                         <hr>
                         <p>Interested In : {{ profile.interested_in }}</p>
                         <hr>
                         <p>Studying : {{ profile.discipline }}</p>
                         <hr>
                         <p>At : {{ profile.campus }}</p>
                         <hr>
                         <p>Relationship Status : {{ profile.status }}</p>
                         <hr>
                         <p>Enjoys : {{ profile.hobbies }}</p>
                    </div>
                    <a class="btn btn-default" href="{% url 'postman:write' %}"><i class="fa fa-envelope"></i>Start Chat with {{ user.username }}</a>
                  </p>
             </div>
          </div>
          </div>
          <hr>
          <hr>
        {% endfor %}...

If am using the other format, I can’t get the username of each user with {{ user.username }} , {{ username }}, or {{ profile.username }}. If I can get a way to display the username of each user on their profile in the list, then I’ll use the double codes instead of the simplified form.

Frequently, an all-white page means an exception was thrown in the python code. This exception would be visible in the console window where you’re running runserver.

Please verify whether or not you have such an exception. If so, take a look at it to see what it’s telling you about what the error is. If you can’t figure it out from the text of the message(s), copy/paste the text of the message here and we’ll try to help.

1 Like

You’re right sir, the editor failed to recognize the (’-age’) as a string in the view function, so I had to erase and type it again for it to turn green like other strings. so now your simplified version works, except for the username issue, it still shows the username of the authenticated user for all the profiles. Am thinking of adding a username attribute to the Profile object model so I can use the {{ profile. }} tag to display it on the template like the rest, but am concerned since it will conflict with the Django’s built in username attribute. Or is there a way to connect the two in the model using ForeignKey?

Your template is referencing a field named username in the Profile object, but there is no field named username in Profile. Assuming you’re using the Django-standard User model, there is a username field in it, which means you would reference it as profile.user.username

Ken

Yes am using the Django standard user which I extended with that ‘user’ in my Profile model.

Thank you so much
KenWhitesell, the {{ profile.user.username }} works perfectly. :partying_face: :partying_face: