Skip to main content
 首页 » 编程设计

python之在基于类的 View 中限制经过身份验证的用户的 `UpdateView` 数据集

2025年05月04日10虾米哥

我有一个 Django 项目,我在其中扩展了用户以使用 OneToOneField 拥有一个配置文件。我正在使用 CBV UpdateView,它允许用户更新他们的个人资料。他们为此访问的 URL 是 ../profile/user/update。我遇到的问题是,如果用户输入另一个用户名,他们可以编辑其他人的个人资料。我如何限制 UpdateView 以便经过身份验证的用户只能更新他们的个人资料。我试图做一些事情来确保 user.get_username == profile.user 但没有运气。

模型.py

from django.db import models 
from django.contrib.auth.models import User 
from django.db.models.signals import post_save 
from django.core.urlresolvers import reverse 
 
class Profile(models.Model): 
    # This field is required. 
    SYSTEM_CHOICES = ( 
        ('Xbox', 'Xbox'), 
        ('PS4', 'PS4'), 
    ) 
    system = models.CharField(max_length=5, 
                                    choices=SYSTEM_CHOICES, 
                                      default='Xbox') 
    user = models.OneToOneField(User) 
    slug = models.SlugField(max_length=50) 
    gamertag = models.CharField("Gamertag", max_length=50, blank=True) 
    f_name = models.CharField("First Name", max_length=50, blank=True) 
    l_name = models.CharField("Last Name", max_length=50, blank=True) 
    twitter = models.CharField("Twitter Handle", max_length=50, blank=True) 
    video = models.CharField("YouTube URL", max_length=50, default='JhBAc6DYiys', help_text="Only the extension!", blank=True) 
    mugshot = models.ImageField(upload_to='mugshot', blank=True) 
 
    def __unicode__(self): 
            return u'%s' % (self.user) 
 
    def create_user_profile(sender, instance, created, **kwargs): 
        if created: 
            Profile.objects.create(user=instance, slug=instance) 
 
    post_save.connect(create_user_profile, sender=User) 
 
    def get_absolute_url(self): 
        return reverse('profile-detail', kwargs={'slug': self.slug}) 

View .py

from django.shortcuts import render 
from django.views.generic import DetailView 
from django.views.generic.edit import UpdateView 
from django.views.generic.list import ListView 
 
from profiles.models import Profile 
 
 
class ProfileDetail(DetailView): 
 
    model = Profile 
 
    def get_context_data(self, **kwargs): 
        context = super(ProfileDetail, self).get_context_data(**kwargs) 
        return context 
 
class ProfileList(ListView): 
    model = Profile 
    queryset = Profile.objects.all()[:3] 
 
    def get_context_data(self, **kwargs): 
        context = super(ProfileList, self).get_context_data(**kwargs) 
        return context 
 
class ProfileUpdate(UpdateView): 
    model = Profile 
    fields = ['gamertag', 'system', 'f_name', 'l_name', 'twitter', 'video', 'mugshot'] 
    template_name_suffix = '_update' 
 
    def get_context_data(self, **kwargs): 
        context = super(ProfileUpdate, self).get_context_data(**kwargs) 
        return context 

管理员.py

from django.contrib import admin 
from models import Profile 
 
class ProfileAdmin(admin.ModelAdmin): 
    prepopulated_fields = {'slug': ('user',), } 
 
admin.site.register(Profile, ProfileAdmin) 

Profiles 应用程序的 Urls.py

from django.conf.urls import patterns, url 
from django.contrib.auth.decorators import login_required 
from profiles.views import ProfileDetail, ProfileUpdate 
 
urlpatterns = patterns('', 
    url(r'^(?P<slug>[-_\w]+)/$', login_required(ProfileDetail.as_view()), name='profile-detail'), 
    url(r'^(?P<slug>[-_\w]+)/update/$', login_required(ProfileUpdate.as_view()), name='profile-update'), 
) 

Profile_update.html

{% extends "base.html" %} {% load bootstrap %} 
 
{% block content %} 
 
{% if user.is_authenticated %} 
 
  <h1>Update your profile</h1> 
 
  <div class="col-sm-4 col-sm-offset-4"> 
    <div class="alert alert-info alert-dismissible" role="alert"> 
      <button type="button" class="close" data-dismiss="alert" aria-label="Close"> 
        <span aria-hidden="true">&times;</span> 
      </button> 
      <strong>Heads up!</strong> Other users can find you easier if you have a completed profile. 
    </div> 
    <form enctype="multipart/form-data" method="post" action="">{% csrf_token %} 
      {{ form|bootstrap }} 
      <input class="btn btn-default" type="submit" value="Update" /> 
    </form> 
  </div> 
 
 
{% else %} 
<h1>You can't update someone elses profile.</h1> 
{% endif %} 
 
{% endblock %} 

请您参考如下方法:

这样的事情怎么样:

from django.contrib.auth.views import redirect_to_login 
 
 
class ProfileUpdate(UpdateView): 
    [...] 
 
    def user_passes_test(self, request): 
        if request.user.is_authenticated(): 
            self.object = self.get_object() 
            return self.object.user == request.user 
        return False 
 
    def dispatch(self, request, *args, **kwargs): 
        if not self.user_passes_test(request): 
            return redirect_to_login(request.get_full_path()) 
        return super(ProfileUpdate, self).dispatch( 
            request, *args, **kwargs) 

在此示例中,用户被重定向到默认的 LOGIN_URL。但是你可以很容易地改变它。将用户重定向到他们自己的个人资料。