Django— Allowing Users to only edit their profile

2020-07-31 03:26发布

问题:

I want to allow User to only edit their profile. This is my URL:

url(r'^profile/(?P<pk>[0-9]+)/$', views.UserUpdate.as_view(), name='profile')

Now when the user click on 'my profile' they will get their own profile which they can edit but if they manually edit the urlpath in browser and enter other user's id like below, they can view and edit other User's profile

http://127.0.0.1:8000/profile/1/

this is my view

class UserUpdate(UpdateView):
model = Profile
fields = ['personal_info','job_title','department', 'location','expertise', 'user_photo','phone_number','contact_facebook','contact_linkedin','contact_skype']
template_name = 'user_form.html'
success_url = reverse_lazy('index')

Now in user_form.html I have checked if the user is authenticated so that only logged in user can view the profile page but still logged in User can view other user's profile.

{% if user.is_authenticated %}
                    <h3> {{ user.first_name }}'s Profile</h3>
                    <form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
                    {% csrf_token %}
                    {% include 'form-template.html' %}
                    <div class="form-group">
                        <div class="col-sm-offset-2 col-sm-10">
                            <button type = "submit" class="btn btn-success">Submit</button>
                            <a href={%  url 'index' %}><input type="button" class = " col-sm-offset-2 btn btn-warning " name="cancel" value="Cancel" /></a>
                        </div>
                    </div>
                    </form>

This is my model:

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
personal_info = models.TextField(blank=True)
job_title = models.CharField(max_length=100, blank=True)
department = models.CharField(max_length=100, blank=True)
location = models.CharField(max_length=100, blank=True)
expertise = models.TextField(blank=True)
phone_regex = RegexValidator(regex=r'^\+?1?\d{5,15}$', message="Phone number must be entered in the format: '+123456'. Between 5 and 15 digits allowed.")
phone_number = models.CharField(validators=[phone_regex], max_length=16, blank=True)
contact_skype = models.URLField(null=True, blank=True)
contact_facebook = models.URLField(null=True, blank=True)
contact_linkedin = models.URLField(null=True, blank=True)
user_photo = models.ImageField(upload_to='../media/img', blank=True)

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

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

How can I restrict logged in user to only edit their profile? I know there are lot of similar questions and possible duplicate in stack overflow but none seemed to help my case.

Thanks in advance

回答1:

You can just remove the pk from your url like so

url(r'^profile/$', views.UserUpdate.as_view(), name='profile')

And then only fetch the user's profile

class UserUpdate(UpdateView):
    model = Profile
    fields = ['personal_info','job_title','department', 'location','expertise', 'user_photo','phone_number','contact_facebook','contact_linkedin','contact_skype']
    template_name = 'user_form.html'
    success_url = reverse_lazy('index')

    def get_object(self):
        return self.request.user.profile

That way you ensure, that the profile view is only ever loaded with the user's own profile.

On an additional note, you then might want to restrict the view to only allow logged in users.