What would be the best approach to create a separate profile page for registered users?

I’m working on a test blog app to hone my Django skills and reached the point where I want to make it so the link of the author of the blog post shows his/her profile page when a visitor clicks on the author’s name on the post page.

At this moment when I click on the author’s name–it shows the currently logged in users(superusers’) profile page, and not the author’s.

Can someone please guide me in the right path to achieve this?

Should I create a separate model for registered users?

1 Like

It’ll be easier if you post the view and the template you’re current using for us to explain what may need to be changed.

Here are my accounts app models.py, urls.py, and views.py files.
Note that this profile model is the only one i created in the entire application to which my superuser account links to.

I’m not sure if both user types–superusers and registered are linked to this one Profile model, or do I need a separate model for registered users.

My goal is to create a profile page for users to display their posts in it.

models.py


class Profile(models.Model):
	user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
	profile_image = models.ImageField(default='default.jpg', upload_to='profile_images', null=True)
	biography = models.TextField(max_length=3000, null=True, blank=True)

	skills_set = models.ManyToManyField(SkillSet,  null=True)

	

	def __str__(self):
		return str(self.user)

views.py

@login_required 
def profile(request): 

	if request.method == 'POST':

		p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile)

		if p_form.is_valid():

			p_form.save()

			messages.success(request, 'your profile has been updated.')
			return redirect('membership:profile')
	else:

		p_form = ProfileUpdateForm(instance=request.user.profile)

		context = {

			'p_form':p_form,
		}
	return render(request,'registration/profile.html', context)

urls.py


from django.urls import path
from . import views  
from django.contrib.auth import views as auth_views


app_name = 'membership'

urlpatterns = [
	path('register/', views.register, name='register'),
	path('login/', auth_views.LoginView.as_view(template_name='registration/login.html'), name='login'),
	path('logout/', auth_views.LogoutView.as_view(template_name='registration/logout.html'), name='logout'),
	path('profile/', views.profile, name='profile'),
	path('edit_profile/', views.edit_profile, name='edit_profile'),
	path('account_settings/', views.account_settings, name='account_settings'),

]


First, a User is a User, regardless of what attributes may be set on that user. Structurally, there’s no difference between a “superuser” and any other user.

That’s because in this view, you have:

and

You’re explictly selecting the profile for the currently logged-in user. (If a different user were logged in, they would see their own profile.)

If you want to view someone else’s profile, you’ll want to create a view to show that profile only (not allowing an edit!), passing the user’s pk as a url parameter to that view.

Works perfect, thank you

Hello,

I followed your tip and everything works fine.

Until today, the page that I made for the registered member is rendering data twice in the template. I have no idea what caused that.

Is this something that ever happened to you?

I did the following.

  1. Created a new view for the registered member called MemberProfileView

views.py


class MemberProfileView(generic.ListView):

	model = Tutorial
	template_name = 'members/member_profile.html' 
	context_object_name = 'tutorials'
	

	def get_queryset(self):
		user = get_object_or_404(User, username=self.kwargs.get('username'))
		return Tutorial.objects.filter(creator=user).order_by('-created_date')

  1. created a URL but instead of passing the pk I passed the username*(correct me if I’m wrong)*
    urls.py
	path('member_profile/<str:username>', MemberProfileView.as_view(), name='member_profile')
  1. rendered the member_profile data in the member_profile templates page like so:
    member_profile.html

{% for tut in tutorials %}
    <img src="{{tut.creator.profile.profile_image.url}}" class='img-fluid profile_image'>

    
    
    <br><br>
    <h4 class="profile_page_heading">{{tut.creator.profile.user.first_name}}
    {{tut.creator.profile.user.last_name}}</h4>
    <hr>
    <p>{{tut.creator.profile.user.username}}<br> 
    {{tut.creator.profile.user.email}}</p>

{% endfor %}

Everything worked fine for a few days, until today suddenly it shows all the data in doubles, like duplicated data, twice.

I spent a few hours trying to figure whats going on.

Any idea?

Thank you in advance.

EDIT: Is only happens in the member_profile page not the user page

Should I use an if statement with Jinja?

I don’t understand the problem that you’re trying to describe here.

What specifically is being shown as duplicated?

I’m trying to retrieve member’s blog posts/tutorials and display them on their profile page.

Everything is displayed fine, however–instead of creating a list of their posts/tutorials, below their information, its creates a list of the entire profile database repeatedly for every blog post/tutorial they have

could it have something to do with the way the view is returning the profile?


class MemberProfileView(generic.ListView):

	model = Tutorial
	template_name = 'members/member_profile.html' 
	context_object_name = 'tutorials'
	

	def get_queryset(self):
		user = get_object_or_404(User, username=self.kwargs.get('username'))
		return Tutorial.objects.filter(creator=user).order_by('-created_date')

No, it’s because your template is specifically coded to do that.

OK, I removed the for loop and “tut” and changed of “tut.creator.profile.profile_image.url” to " user.profile.profile_image.url" and everything works fine now. I feel like such a silly goose for not seeing this one. But, is this a good practice? Would you improve it in anyway?

This isn’t a case of “right” or “wrong” or “good practice”. It all just depends upon what you want presented on that page and how you want it to look.