1

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

MessitÖzil
  • 1,298
  • 4
  • 13
  • 23

1 Answers1

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.

dan_kaufhold
  • 637
  • 5
  • 16
  • @dan_kaufhold but this won't fill the profile form with current data. I want fields to be filled with their current values – MessitÖzil Jun 08 '17 at 19:34
  • @user3612693 when you use this, the template will have the `{{ object }}` variable you can reference for fields of the profile and the `{{ form }}` variable to render a form with all the fields you defined. They will then have the initial values of the loaded objects. – dan_kaufhold Jun 08 '17 at 19:37