Jude Molloy
Jude Molloy

Reputation: 193

Django Update Profile View - Only allow logged in users to edit their own accounts

I have a Django model that is a AbstractBaseUser, I have made an update form where users can update their profile information, however, I am unable to find a way to let logged in users edit their own profile. If anyone has any idea on how to solve this problem please let me know. Thanks in advance. :)

Please let me know if you require viewing any more code than is provided.

UpdateProfile view (note: There are 2 versions of the 'same' view, I am just looking for a solution for either of them. I would rather user the CBV if possible, however, I don't mind using the FBV)

class UpdateProfile(generic.UpdateView):
    model = Designer
    form_class = UserUpdateForm
    success_url = reverse_lazy('home')
    template_name = 'main/profile_update.html'

def update_profile(request):

    user = request.user
    form = UserUpdateForm(request.POST, instance=user)
    form.actual_user = request.user
    if request.method == 'POST':
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('update_profile_success'))
    else:
        form = UserUpdateForm()

    context = {'form': form, }
    return render(request, 'main/profile_update.html', context)

model

class Designer(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=25, unique=True)
    display_name = models.CharField(max_length=25)
    twitter = models.CharField(max_length=15)
    bio = models.TextField(max_length=145, blank=True, default="")
    avatar = models.ImageField(upload_to='img', default='img/default_profile_pic.jpg')
    up_votes = models.IntegerField(default=0)
    available = models.BooleanField(default=False)
    thumbnail_price = models.FloatField(null=True)
    channel_art_price = models.FloatField(null=True)
    monthly = models.BooleanField(default=False)
    promoted = models.BooleanField(default=False)
    date_joined = models.DateTimeField(default=timezone.now)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["display_name", "username"]

form

class UserUpdateForm(forms.ModelForm):
    class Meta:
        fields = ('username', 'email', 'avatar', 'display_name', 'twitter', 'bio', 'available',
              'monthly', 'thumbnail_price', 'channel_art_price')
        model = get_user_model()     

Thanks. All help is appreciated :)

Upvotes: 1

Views: 2294

Answers (1)

Alasdair
Alasdair

Reputation: 308849

Your function-based view should just about work. If you use the login_required decorator to make sure the user is logged in, then setting instance=request.user should be enough. You don't need the form.actual_user = request.user line

from django.contrib.auth.decorators import login_required

@login_required
def update_profile(request):
    user = request.user
    form = UserUpdateForm(request.POST, instance=user)

    if request.method == 'POST':
       ...

For the class based view, use LoginRequiredMixin (requires Django 1.9+) to make sure that the user is logged in, then override get_object to use self.request.user

from django.contrib.auth.mixins import LoginRequiredMixin

class UpdateProfile(LoginRequiredMixin, generic.UpdateView):
    model = Designer
    form_class = UserUpdateForm
    success_url = reverse_lazy('home')
    template_name = 'main/profile_update.html'

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

Upvotes: 4

Related Questions