Retriveing info from class based views

I am creating something like the Hall of Fame Vidz.
I want to retrieve all the halls under a username like : http://localhost:8000/users/nick - show halls 1,2 and 3

I have the code here using my variables.

urls.py:
path('users/<str:username>', views.PublicProfile.as_view(), name='public_profile'),

views.py:

class PublicProfile(generic.DetailView):
    model = User
    slug_field = "username"
    slug_url_kwarg = "username"    

    user_profiles = UserProfile.objects.filter(user=username).order_by('-created') # username does not exist
    if user_profiles:        
        latest_profile = user_profiles[0]
    else:
        latest_profile = ""

    template_name = 'public_profile.html'

    def get_object(self):
        user_profile = super(PublicProfile, self).get_object()
        return user_profile    
  1. There’s an error here as username is not defined. So how do I retrieve this in a class like we do in function based views def viewUser(request, slug):

  2. How do we pass latest_profile to the template like we do in function based views return render(request, 'view.html', { 'latest_profile': latest_profile })

I got this solved using a function based view.

In class based view u can achieve this in this way:

models.py:

class UserProfile(models.Model):
     user = models.OneToOneField(User, on_delete=models.CASCADE)
     custom_field = models.CharField(max_length=15)

in the view we need override get_object method because pk or slug are used by default

views.py:

class PublicProfile(DetailView):
    model = UserProfile
    template_name = 'public_profile.html'
        
    def get_object(self, queryset=None):
        if queryset is None:
            queryset = self.get_queryset()
        new_str = self.kwargs.get('username') or self.request.GET.get('username') or None
        
        queryset = queryset.filter(user=User.objects.get(username=new_str))
        obj = queryset.get()
        return obj 

and in html u’ve got access to UserProfile and User (username, email are from User model, custom_field is from UserProfile):

public_profile.html:

<h1>{{ object.user.username }}</h1> 
<p>email: {{ object.user.email }}</p>
<p> custom_field: {{ object.custom_field }}</p>
1 Like

Thanks for your reply. But for this case function based view is simpler I feel. Is there any advantage on using Class Based views over function based ones for more complex tasks ?

def PublicProfile(request, username):
    user = get_object_or_404(User, username=username)
    user_profiles = UserProfile.objects.filter(user_id=user.id).order_by('-created')
    if user_profiles:        
        latest_profile = user_profiles[0]
    else:
        latest_profile = ""

    return render(request, 'public_profile.html', { 'username': username, 'latest_profile' : latest_profile })

I thought u want to use generic view. It’s the reason is more complicated but. If u wan’t to use just class based view u don’t have to override specific method. u just need to have get and post method inside class. Advantage is that u’ve got everything in one place. Inside class u can collect all methods (validation, calculation etc), vars anything what is connected to the view. So for sure class view gives u better order.

class PublicProfile(View):
    def get(self, request, *args, **kwargs):
        user = get_object_or_404(User, username=username)
        user_profiles = UserProfile.objects.filter(user_id=user.id).order_by('-created')
         if user_profiles:        
             latest_profile = user_profiles[0]
         else:
             latest_profile = ""

        return render(request, 'public_profile.html', { 'username': username, 'latest_profile' : latest_profile })

        def post(self, request, *args, **kwargs):
             # something to do
             return some_response

    def some_other_method(self):
        return something

Of course for simple view - class view is not the best solution. But if u want to implement more methods class are better. Or if u want to get some behaviour for example form generic views.

1 Like

Thanks.

I was following the Halls of Fame course. Based on that I was trying with DetailView:
class PublicProfile(generic.DetailView):

1 Like