Python 在基于类的视图中限制已验证用户的“UpdateView”数据集
我有一个Django项目,在这个项目中,我使用OneToOneField扩展了用户配置文件。我正在使用CBV UpdateView,它允许用户更新他们的个人资料。他们为此访问的URL是../profile/user/update。我遇到的问题是,如果用户键入其他用户名,他们可以编辑其他人的个人资料。如何限制UpdateView,以便经过身份验证的用户只能更新其配置文件。我试图做一些事情来确保user.get_username==profile.user,但运气不好 Models.pyPython 在基于类的视图中限制已验证用户的“UpdateView”数据集,python,django,django-views,Python,Django,Django Views,我有一个Django项目,在这个项目中,我使用OneToOneField扩展了用户配置文件。我正在使用CBV UpdateView,它允许用户更新他们的个人资料。他们为此访问的URL是../profile/user/update。我遇到的问题是,如果用户键入其他用户名,他们可以编辑其他人的个人资料。如何限制UpdateView,以便经过身份验证的用户只能更新其配置文件。我试图做一些事情来确保user.get_username==profile.user,但运气不好 Models.py from
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})
Views.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
管理员
from django.contrib import admin
from models import Profile
class ProfileAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('user',), }
admin.site.register(Profile, ProfileAdmin)
配置文件应用程序的url.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'),
)
来自django.conf.url导入模式,url
从django.contrib.auth.decorators导入所需的登录名
从profiles.views导入ProfileDetail,ProfileUpdate
urlpatterns=模式(“”,
url(r'^(?P[-\uw]+)/$,需要登录(ProfileDetail.as\u view()),name='profile-detail'),
url(r'^(?P[-\uw]+)/update/$,需要登录(ProfileUpdate.as\u 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">×</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 %}
{%extends“base.html”%}{%load bootstrap%}
{%block content%}
{%if user.u经过身份验证%}
更新您的个人资料
&时代;
抬起头如果您有完整的配置文件,其他用户会发现您更容易使用。
{%csrf_令牌%}
{{form | bootstrap}}
{%else%}
您无法更新其他人的个人资料。
{%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)
在本例中,用户被重定向到默认登录URL。但是你可以很容易地改变它。将用户重定向到他们自己的配置文件。类似这样的内容如何:
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)
在本例中,用户被重定向到默认登录URL。但是你可以很容易地改变它。将用户重定向到他们自己的配置文件。- 您的template.html:
- 您的template.html:
为了避免在使用基于类的视图(CBV)时访问与所连接用户无关的数据,您可以使用动态筛选并在
模型
属性上定义queryset
如果您在auth.models.user
上有一个带有ForeignKey
(此处命名为user
)的book.models
,您可以轻松地限制如下访问:
# views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView
from books.models import Book
class BookList(LoginRequiredMixin, ListView):
def get_queryset(self):
return Book.objects.filter(user=self.request.user)
请参阅文档中有关的更多说明
指定model=Publisher
实际上只是表示queryset=Publisher.objects.all()
的简写。但是,通过使用queryset定义对象的筛选列表,您可以更具体地了解视图中可见的对象
[……]
方便的是,ListView
有一个我们可以覆盖的get\u queryset()
方法。以前,它只是返回queryset属性的值,但是现在我们可以添加更多的逻辑。
这项工作的关键部分是,当调用基于类的视图时,各种有用的东西都存储在self
上;除了请求(self.request
)之外,还包括根据URLconf捕获的位置(self.args
)和基于名称的(self.kwargs
)参数
为了避免在使用基于类的视图(CBV)时访问与所连接用户无关的数据,您可以使用动态筛选并在
模型
属性上定义queryset
如果您在auth.models.user
上有一个带有ForeignKey
(此处命名为user
)的book.models
,您可以轻松地限制如下访问:
# views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView
from books.models import Book
class BookList(LoginRequiredMixin, ListView):
def get_queryset(self):
return Book.objects.filter(user=self.request.user)
请参阅文档中有关的更多说明
指定model=Publisher
实际上只是表示queryset=Publisher.objects.all()
的简写。但是,通过使用queryset定义对象的筛选列表,您可以更具体地了解视图中可见的对象
[……]
方便的是,ListView
有一个我们可以覆盖的get\u queryset()
方法。以前,它只是返回queryset属性的值,但是现在我们可以添加更多的逻辑。
这项工作的关键部分是,当调用基于类的视图时,各种有用的东西都存储在self
上;除了请求(self.request
)之外,还包括根据URLconf捕获的位置(self.args
)和基于名称的(self.kwargs
)参数
先生,您真是太棒了。先生,您真是太棒了。您只需返回
super().get\u queryset().filter(user=self.request.user)
,就可以实现这一点。您可以不知道正在使用的模型,甚至可以将其用作mixin,如果您正在使用它的所有模型的用户字段都命名为user
。您只需返回super().get_queryset().filter(user=self.request.user)
,就可以轻松实现这一点。您可以不知道正在使用的模型,甚至可以将其用作mixin,如果您正在使用它的所有模型的用户字段都命名为user
。