drf_身份认证和权限
1、修改模型:增加owner,highlight字段和save方法。其中owner字段将用于表示创建代码段的用户。highlight字段将用于存储代码的突出显示的HTML表示。
from django.db import models from pygments.lexers import get_all_lexers from pygments.styles import get_all_styles from pygments.lexers import get_lexer_by_name from pygments.formatters.html import HtmlFormatter from pygments import highlight LEXERS = [item for item in get_all_lexers() if item[1]] LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS]) STYLE_CHOICES = sorted((item, item) for item in get_all_styles()) class Snippet(models.Model): created = models.DateTimeField(auto_now_add=True) title = models.CharField(max_length=100, blank=True, default='') code = models.TextField() linenos = models.BooleanField(default=False) language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100) style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100) owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE) highlighted = models.TextField() class Meta: ordering = ('created',) def save(self, *args, **kwargs): """ Use the `pygments` library to create a highlighted HTML representation of the code snippet. """ lexer = get_lexer_by_name(self.language) linenos = 'table' if self.linenos else False options = {'title': self.title} if self.title else {} formatter = HtmlFormatter(style=self.style, linenos=linenos, full=True, **options) self.highlighted = highlight(self.code, lexer, formatter) super(Snippet, self).save(*args, **kwargs)
2、更新数据库模型:
rm -f db.sqlite3 rm -r snippets/migrations python manage.py makemigrations snippets python manage.py migrate
3、序列化User 模型,并添加snippets
from django.contrib.auth.models import User class UserSerializer(serializers.ModelSerializer): snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all()) class Meta: model = User fields = ('id', 'username', 'snippets')
4、修改view.py,增加用户视图
from django.contrib.auth.models import User from snippets.serializers import UserSerializer class UserList(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer class UserDetail(generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = UserSerializer
5、将user视图添加到urls中
url(r'^users/$', views.UserList.as_view()), url(r'^users/(?P<pk>[0-9]+)/$', views.UserDetail.as_view()),
6、将snippet和user关联起来
在view.py snippetlist类中添加perform_create方法。用户不是作为序列化表示的一部分发送的,而是传入请求的属性,因此需要在保存的时候将用户属性也保存起来。
def perform_create(self, serializer): serializer.save(owner=self.request.user)
7、修改序列化器中的SnippetSerializer,增加owner属性,ReadOnlyField只读属性将用于序列化表示形式,但不会被用于更新模型它们被反序列化的实例。source控制显示的具体字段。
注意,应该在Meta类的fields中增加owner
class SnippetSerializer(serializers.ModelSerializer): owner = serializers.ReadOnlyField(source='owner.username') class Meta: model = Snippet fields = ('id', 'title', 'code', 'linenos', 'language', 'style','owner')
8、修改权限,在views.py中为SnippetList和SnippetDetail添加允许权限。IsAuthenticatedOrReadOnly,这将确保经过身份验证的请求获得读写访问权限,未经身份验证的请求将获得只读访问权限。
from snippets.models import Snippet from snippets.serializers import SnippetSerializer from rest_framework import generics from django.contrib.auth.models import User from snippets.serializers import UserSerializer from rest_framework import permissions class SnippetList(generics.ListCreateAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (permissions.IsAuthenticatedOrReadOnly,) def perform_create(self, serializer): serializer.save(owner=self.request.user) class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
9、添加登陆到Browsable API,
在项目urls中增加:
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
from django.conf.urls import url, include from rest_framework import routers from tutorial.quickstart import views router = routers.DefaultRouter() router.register(r'users', views.UserViewSet) router.register(r'groups', views.GroupViewSet) # Wire up our API using automatic URL routing. # Additionally, we include login URLs for the browsable API. urlpatterns = [ url(r'^', include('snippets.urls')), url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) # url(r'^api-auth/', include('rest_framework.urls')), ]
这样在左上角将出现login 标签。在创建一些实例后,导航到'/ users /'端点,并注意该表示包含每个用户的“snippets”字段中与每个用户关联的代码段ID列表。
10、创建对象级权限,在snippets目录下创建permissions.py,任何人都有读的权限,只有拥有者具有所有权限。
from rest_framework import permissions class IsOwnerOrReadOnly(permissions.BasePermission): """ Custom permission to only allow owners of an object to edit it. """ def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request, # so we'll always allow GET, HEAD or OPTIONS requests. if request.method in permissions.SAFE_METHODS: return True # Write permissions are only allowed to the owner of the snippet. return obj.owner == request.user
同时在view中修改对应的权限:在SnippetDetail中增加IsOwnerOrReadOnly权限限制。
from snippets.models import Snippet from snippets.serializers import SnippetSerializer from rest_framework import generics from django.contrib.auth.models import User from snippets.serializers import UserSerializer from rest_framework import permissions from snippets.permissions import IsOwnerOrReadOnly class SnippetList(generics.ListCreateAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (permissions.IsAuthenticatedOrReadOnly,) def perform_create(self, serializer): serializer.save(owner=self.request.user) class SnippetDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,) class UserList(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer class UserDetail(generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = UserSerializer
再次打开浏览器,如果您以创建代码片段的同一用户身份登录,则会发现“DELETE”和“PUT”操作仅出现在代码段实例端点上。
浙公网安备 33010602011771号