ジャンゴRESRframework奇数変態トリック

ジャンゴRESRframework

ミックスイン、ビューセットとに関連して使用ルータ

Mixins5つのクラスがあります。

  • CreateModelMixin
  • ListModelMixin
  • RetrieveModelMixin
  • UpdateModelMixin
  • DestroyModelMixin

彼らは、対応する操作、書き込みロジックは同じコードを繰り返して行く必要はないされ、それらを使用することの利点を削除し、データベース、検索、変更の増加に対応しており、それぞれがあるためmixins、内部で論理的対応書かれている、のみ設定する必要がありますそれquerysetserializer_classそれ

ViewSetまた、5種類あります。

  • ViewSetMixin
  • ViewSet
  • GenericViewSet
  • ReadOnlyModelViewSet
  • ModelViewSet

一般的な言葉だけを使用する必要がありGenericViewSet、十分に、それは継承ViewSetMixinし、generics.GenericAPIViewそれを設定することで、我々はすべて知っている機能querysetserializer_classフォーカスと性質、ViewSetMixin

ViewSetMixin

それは上書きされますas_view、これは私たちが登録することを可能にする、メソッドをurl使用している方法がある、非常に簡単になりinitialize_request、この方法は、主にされたactionプロパティの割り当て、このプロパティは、動的に設定されているserializerpermission巨大な利点がありますが!

だから、〜書きAPIView、次のようにコードを

from rest_framework import mixins
from rest_framework import viewsets

class XXXViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):

    queryset = Model.objects.all()
    serializer_class = ModelSerializer

次のステップは、設定することですurl

from appname.views import XXXViewSet

models = XXXViewSet.asview({
    'get': 'list',
    'post': 'create'
})

urlpattrtns = [
    url(r'apiAddress/$',models, name="models"),

あなたがすることができるようsetにバインドするために要求しlist、上記の方法、post要求がバインドされているcreat方法で、あなたは実際には、上記の構成、それらを書き換えるに行く必要はありませんurl方法も容易になることがあるのでrouter〜それをデビューさせるであろう

from rest_framework.routers import DefaultRouter
from appname.views import XXXViewSet

router = DefaultRouter()
router.register(r'apiAddress', XXXViewSet, base_name='apiAddress')

urlpattrtns = [
    # 这个已经不需要了
    # url(r'apiAddress/$',models, name="models"),
    url(r'^', include(router.urls)),
]

後でに追加しましたurl唯一の時間必要がrouter内側のリストに登録され、urlpattrtnsリストは変更する必要はありません。これが完了するRESTful API創造、合理的な試合になることができmixinsViewSet及びrouterS 3、あなたは超高速の多数を開発することができますRESTful API

ジャンゴRESTframeworkフィルタリングを使用します

単純なフィルタ機能、例えば、ユーザクエリのリストは、ファンの数のみが100より大きい返します。

class XXXViewSet(mixins.ListModelMixin,mixins.CreateModelMixin,viewsets.GenericViewSet):
    
    serializer_class = ModelSerializer
    def get_query(self):
        fans_nums = self.request.quer_params.get("fans_min",0)
        if fans_nums:
            return User.object.filter(fans_num__gt=int(fans_min))
        return User.objects.all()

この方法では、書き込みフィルタフィールドがあまりにも多く、繰り返される冗長なコードの多くを書くために必要であれば、上記必要ですので、する必要がありますdjango-filter行うこと

最初は、インストールされるpip install django-filter、その後django-filterに追加INSTALLED_APPS行きます

コードは以下の通りであります:

from rest_framework import mixins
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend
from django.contrib.auth import get_user_model

User = get_user_model()

class UserViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):

    queryset = User.objects.all()
    serializer_class = ModelSerializer
    filter_backends = (DjangoFilterBackend,)
    # 设置过滤字段,这里设置过滤用户的名字和粉丝数
    filter_fields = ('name', 'fans_num')

次に、ブラウザ開く127.0.0.1:8000あなたは、対応するノードビューを見ることができますが、(このメソッドは、ルーティング登録を使用する必要があります)

未定義

この方法では、フィルタインタフェースに表示されますfilter_fields = ('name', 'fans_num')フィルター内部のフィールド条件を設定しました

新しいですfilter.py

import django_filters
from django.contrib.auth import get_user_model

User = get_user_model()

class UserFilter(django_filters.rest_framework.FilterSet):

    min_fans_num = django_filter.NumberFilter(name='fans_num', lookup_expr='gte')
    max_fans_num = django_filters.NumberFilter(name='fans_num', lookup_expr='lt')
    name = django_filters.CharFilter(name='name',lookup_expr='icontains')
    
    class Meta:
        model = User
        fields = ['name', 'min_fans_num', 'max_fans_num']

そして、コードが変更されました前に

from .filter import UserFilter

class UserViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):

    queryset = User.objects.all()
    serializer_class = ModelSerializer
    filter_backends = (DjangoFilterBackend,)
    filter_class = UserFilter

ユーザ名によるフィルタは、その後、実際には、SearchFilterまた、2行のコードを使用して実施することができる十分です

filter_backends = (DjangoFilterBackend, SearchFilter)
serch_fields = ("name",)

より強力な設定もあります。

The search behavior may be restricted by prepending various characters to the search_fields.

'^' Starts-with search.

'=' Exact matches.

'@' Full-text search. (Currently only supported Django's MySQL backend.)

'$' Regex search.

For example:

search_fields = ('=username', '=email')

Djangoのページネーション公式文書

並べ替えもありfilter、ファンの利用者の数に応じて、たとえば、我々は(昇順または降順)ソートしたいです、:

カスタムのページング

from rest_framework.pagination import PageNumberPagination

class UsersPagination(PageNumberPagination):
    # 指定每一页的个数
    page_size = 10
    # 可以让前端来设置page_szie参数来指定每页个数
    page_size_query_param = 'page_size'
    # 设置页码的参数
    page_query_param = 'page'
    

class UserViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
    # 设置分页的class
    pagination_class = UsersPagination

だから、数行のコードを取得するには、リターンでは、json次と前のリンク上のリンクの合計数を追加しました。

私たちがコードを確認する前に、UserViewSetそこにこのクラス、単にコードの7行を書き、それが完了しています

  • ユーザーのリスト
  • createユーザー
  • ページング
  • 検索
  • 心配
  • ソート
    指定したユーザーのために特定の情報を取得したい場合は、これらの機能は、直接の後継するmixins.RetrieveModelMixin直接良い仕事をします...「」

証明機関

例えば、缶を使用するにはログインするユーザーを必要とするいくつかのAPI関数があり
、私はこのブログを削除するかの例を、私は著者が削除できることを確認する必要があります

ユーザーがログインしていることを確認します

from rest_framework.permissions import IsAuthenticated

class XXXViewSet(mixins.CreateModelMixin, mixins.DestroyModelMixin):
    
    permission_classes = (IsAuthenticated,)
    

あなたは、動作を確認する必要がある場合permission

permission.py

from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):

    def has_object_permission(self, request, view, object):
        if request.method in permissions.SAFE_METHODS:
            return True

        return object.user == request.user

permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)

##使用JWTユーザ認証モード

  1. インストールpip install djangorestframework-jwt
  2. url.py設定
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
 ...
 url(r'^api-token-auth/', obtain_jwt_token),
 ...
]
  1. 所望でjwt認証ViewSetクラスの内部に設けられています
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.authentication import SessionAuthentication

class XXXViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
  authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)

プラスSessionAuthenticationは、サイト上のデバッグに便利です。

二つの方法は、サインイン今すぐサインアップ:

  1. ユーザ登録は、ログインページのログインにジャンプすることが許可された後、
  2. 登録後、ユーザーは自動的に彼を助けるためにログインしている
    し、我々は他の操作を行う必要はありません。最初のケースを、第二の場合は、我々はユーザー登録後に返す必要がありますjwttoken前に、フィールドなので、2つの手順を実行します。

フィールドが返されているのでmixins、私たちは良い仕事を助けるために、私たちはリターンフィールドを変更するために、対応するメソッドを書き換える必要があり
確認する必要がdjangorestframework-jwt生成見つけるために、ソースコードをjwt tokenメソッドを

from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler

class UserViewSet(CreateModelMixin, RetrieveModelMixin,UpdateModelMixin,viewsets.GenericViewSet):
    # 重写create方法
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = self.perform_create(serializer)
        
        # 在新建用户保存到数据库之后
        tmp_dict = serializer.data
        # 生成JWT Token
        payload = jwt_payload_handler(user)
        tmp_dict['token'] = jwt_encode_handler(payload)

        headers = self.get_success_headers(serializer.data)
        return Response(tmp_dict, status=status.HTTP_201_CREATED, headers=headers)

もっとJWT関連の操作は、ドキュメントを表示することができます

ダイナミックserializers
の使用前に、これは言っactionプロパティを簡単に達成することができます

class UserViewSet(CreateModelMixin, RetrieveModelMixin,UpdateModelMixin,viewsets.GenericViewSet):
    
    # 这个就不需要了
    #serializer_class = XXXSerializer

    def get_serializer_class(self):
        if self.action == 'create':
            return XXXSerializer
        elif self.action == 'list':
            return XXXSerializer
        return XXXSerializer

いくつかの実用的なSerializer fields
例として、私は(ユーザー)をアップロードしたい、この記事を公開するid関連付ける機能と、この記事で、私たちは、アップロードするためにフロントを持つことはできません

serializer.py

class XXXSerializer(serializers.ModelSerializer):
    # user默认是当前登录的user
    user = serializers.HiddenField(
        default = serializers.CurrentUserDefault()
    )

返された論理的なフィールドは、より複雑ながある場合は、()は、例えば、行われserializer.SerializerMethodFieldを使用することができます。

class XXXSerializer(serializers.ModelSerializer):
    xxx = serializer.SerializerMethodField()
    
    # 把逻辑写在get_的前缀加xxx(字段名),然后返回
    def get_xxx(self, obj):
        # 完成你的业务逻辑
        return 

カスタムユーザー認証は
Django、ログイン伝わってくるusernamepasswordログを行いますが、現在多くのウェブサイトやappユーザ認証をカスタマイズする必要性に電話番号がアカウントとして使用されるように、この時間:

from django.contrib.auth.backends import ModelBackend

class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(username=username)|Q(mobile=username))
            # 验证密码是否正确
            if user.check_password():
                return user
        except Exception as e:
            return None

あなたがバックグラウンドで見た場合に、プレーンテキストで保存するときに直接ModelSerializerが明確に保存されているので、ユーザー登録時には、この問題を解決するために、次のとおりです。

serializer.py

class UserRegSerializer(serializers.ModelSerializer):
    
    #重写create方法
    def create():
        user = super(UserRegSerializer,self).create(validated_data=validated_data)
        user.set_password(validated_data["password"])
        user.save()
        return user

セマフォ、あるいはまたジャンゴ解決することができます

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth import get_user_model
User = get_user_model()

@receiver(post_save, sender=User)
def create_user(sender, instance=None, created=False, **kwargs):
    if created:
        password = instance.password
        instance.set_password(password)
        instance.save()

その後も、コンフィギュレーション内app.py

from django.apps import AppConfig


class UsersConfig(AppConfig):
    name = 'users'
    
    def ready(self):
        import users.signals  

おすすめ

転載: www.cnblogs.com/Dr-wei/p/11686264.html