今天的实作内容主要根据教学网站进行。
在Day22时,我们实作了身份验证功能,部分功能要求使用者必须登入网站才可使用;Day23整合社群登入,提供使用者可选择以Google帐号进行登入。
截至Day23的内容,我们开发了小说追踪功能,所有登入者都可以将小说加入追踪;并提供Book List,所有的登入者都可以看到目前追踪的小说。
今天我们将实作权限管理,透过权限管理,让不同的登入者可以使用不同的功能,并在Book List提供仅该登入者追踪的小说。
我们将使用Django内建的User和Group,透过对於Group授予权限、并将User分配到该Group,来达到此目的。
为了记录每个使用者各自追踪的小说,我们新增了User_Book来记录使用者和小说之间的关系。
class User_Book(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True)
notify = models.BooleanField(default=True)
class Meta:
ordering = ['book']
unique_together = [['book', 'user']]
Django的signal模组,可支援物件中信息的传递。使用此模组,当接收到User建立时,create_user_profile()会将该User加入'Track Members'群组。
from django.contrib.auth.models import User, Group
from django.db.models.signals import post_save
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
instance.groups.add(Group.objects.get(name='Track Members'))
Django提供了很多预设权限可以做选择,在教学网站中也提供了客制权限的方法。
当我们想要用'can_track'这个权限来控制使用者是否可使用「加入追踪」功能,只要於Model中的Meta设定permissions,再重新migrate资料库,就会自动新的权限。
class User_Book(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True)
notify = models.BooleanField(default=True)
class Meta:
ordering = ['book']
unique_together = [['book', 'user']]
permissions = (('can_track', 'Can Track'),)
但依照此方法,每个权限需要与Model进行绑定,这样会导致该权限会被Model展开,在实际操作时会容易混乱且不方便管理。
举例来说,对於加入追踪功能而言,需要同时有Author、Book、User_Book三个Model的权限,若在三个类别各自的Meta下做permission设定,在Group的管理画面上会出现:
对於此问题,可以建立一个空的类别,让客制权限统一集中在这边管理。
class RightsSupport(models.Model):
class Meta:
# No database table creation or deletion operations will be performed for this model.
managed = False
# disable "add", "change", "delete" and "view" default permissions
default_permissions = ()
permissions = ( ('can_track', 'Can Track'), )
登入http://127.0.0.1:8000/admin/,新增「Track Member」Group,并授予「track | rights support | Can Track」权限。
在template中,使用者的权限储存在「perms」变数中,可以透过此变数来检查使用者是否有特定权限:
{% if perms.track.can_track %}
<p>有此功能权限。</p>
{% else %}
<p>无此功能权限。</p>
{% endif %}
根据view是function类型、或class类型,在权限管理上有不同的做法。
使用合成方法,加入LoginRequiredMixin类别,以设定permission_required属性;并修改get_queryset()方法,仅查询当前user加入追踪的资料。
from django.contrib.auth.mixins import LoginRequiredMixin
class BookListView(LoginRequiredMixin, generic.ListView):
permission_required = ('track.can_track')
model = Book
template_name = 'book_list.html'
def get_queryset(self):
return Book.objects.filter(user_book__user=self.request.user, istrack=True)
使用修饰词进行权限检查。
但使用@permission_required()时,若使用者无权限,会自动导到登入画面,对於已登入的使用者来说此流程比较诡异。 (此问题尚未完成替代方法)
from django.contrib.auth.decorators import login_required, permission_required
@login_required
@permission_required('track.can_track')
def TrackBook(request):
pass
<<: Swift 新手-运用 Bluetooth Low Energy
>>: Day 21 中场休息,来做点酷东西(重构 class)
您的订阅是我制作影片的动力 订阅点这里~ 影片程序码 library(naniar) data(ir...
陈述式(Statement) JavaScript 语句类型,用於命令执行指定一系列操作,最大的特徵...
单元对齐跟留白的部分今天会继续,定位的问题基本上不出乱子的话就如同昨天说明的。当然,如果再加上对齐跟...
InnoDB将索引分成Cluster Index & Secondary Index,认识...
虚拟机的建置与操作已经来到基本使用的程度了,对於各种应用修改与尝试後可能伴随虚拟机被搞砸的风险。 ...