Kok Hyvv
Kok Hyvv

Reputation: 195

Change URL Path for View Profile Page - Django

How would one go about creating a user-profile page that other users can view without being able to edit the profile unless they are the user?

The thing I'm trying to work out is how the url routing would work, is it best practice to store a user's profile on a profile/ or <user_id> page and then load in the individual user's data like recent posts using the username or id passed through the url?

Also would this be handled by the one view and template and just use {% if request.user == profile.user %} to display things like edit profile etc?

my problem is any user can edit for others there profiles when he edit url

for example my id is www.test.com/profile/44/ and other user have this id www.test.com/profile/40/ okay ,, now when i edit the link to be 40 not 44 i can access and edit the second user ! how to fix that

models.py :

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    email_confirmed = models.BooleanField(default=False)

@receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
        instance.profile.save()
    def __str__(self):
        return self.user

urls.py :

from django.urls import path
from blog_app.views import ProfileView

urlpatterns = [
    path('profile/<int:pk>/', ProfileView.as_view(), name='profile'),
]

forms.py :

# Profile Form

class ProfileForm(forms.ModelForm):
    # constructor of the UserForm, not Meta
    def __init__(self, *args, **kwargs):
        super().__init__(*args,**kwargs)
        self.fields['username'].widget.attrs.update({'class':'form-control','placeholder':' Enter your username in English ','style': 'font-size:19px;text-align: center;'})
    class Meta:
        model = User
        fields = [
            'username',
            'first_name',
            'last_name',
            'email',
            ]

views.py:

# Edit Profile View
class ProfileView(UpdateView):
    model = User
    form_class = ProfileForm
    success_url = reverse_lazy('home')
    template_name = 'user/commons/profile.html'
    def get(self, request, *args, **kwargs):
        form = self.form_class()
        return render(request, self.template_name, {'form': form})

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)
        if form.is_valid():

            user = form.save(commit=False)
            user.is_active = False # Deactivate account till it is confirmed
            user.save()

            current_site = get_current_site(request)
            subject = 'Activate Your MySite Account'
            message = render_to_string('user/emails/account_activation_email.html', {
                'user': user,
                'domain': current_site.domain,
                'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                'token': account_activation_token.make_token(user),
            })
            user.email_user(subject, message)

            messages.success(request, ('Please Confirm your new email to change email.'))

            return redirect('login')
        return render(request, self.template_name, {'form': form})

html page :

<button type="button" id="submit"> <a href="{% url 'profile' user.id %}" > edit profile info </a></button>

Upvotes: 0

Views: 982

Answers (1)

Dan Yishai
Dan Yishai

Reputation: 782

You can override the get_object() method to always return the currently logged on user from request.user, then you will not need to provide "pk" variable in your path.

Implement get_object() in your view

class ProfileView(UpdateView):
    model = User
    form_class = ProfileForm
    success_url = reverse_lazy('home')
    template_name = 'user/commons/profile.html'
    
    def get_object(self, queryset=None):
        return self.request.user

Then configure the path without pk

urlpatterns = [
    path('profile/me/', ProfileView.as_view(), name='profile'),
]

Note that you should use login_required() decorator or LoginRequiredMixin on that view to avoid anonymous users accessing this view.

Upvotes: 1

Related Questions