From cbf879885f1f4c1697aec5b0ec29a334d3a9e75d Mon Sep 17 00:00:00 2001 From: Hironsan Date: Tue, 26 Jun 2018 06:21:57 +0900 Subject: [PATCH] Add serializers --- doccano/app/app/settings.py | 12 +++++++++++ doccano/app/app/urls.py | 4 ++++ doccano/app/db.sqlite3 | Bin 233472 -> 233472 bytes doccano/app/server/models.py | 2 +- doccano/app/server/serializers.py | 34 ++++++++++++++++++++++++++++++ doccano/app/server/urls.py | 10 +++++++++ doccano/app/server/views.py | 19 +++++++++++++++++ 7 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 doccano/app/server/serializers.py diff --git a/doccano/app/app/settings.py b/doccano/app/app/settings.py index 2db098c7..0f93c003 100644 --- a/doccano/app/app/settings.py +++ b/doccano/app/app/settings.py @@ -39,6 +39,8 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'server.apps.ServerConfig', 'widget_tweaks', + 'rest_framework', + 'django_filters' ] MIDDLEWARE = [ @@ -105,6 +107,16 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] +REST_FRAMEWORK = { + # Use Django's standard `django.contrib.auth` permissions, + # or allow read-only access for unauthenticated users. + 'DEFAULT_PERMISSION_CLASSES': [ + 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' + ], + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', + 'PAGE_SIZE': 2, + 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) +} # Internationalization # https://docs.djangoproject.com/en/2.0/topics/i18n/ diff --git a/doccano/app/app/urls.py b/doccano/app/app/urls.py index d394ab8e..84cc3ac4 100644 --- a/doccano/app/app/urls.py +++ b/doccano/app/app/urls.py @@ -16,6 +16,7 @@ Including another URLconf from django.contrib import admin from django.urls import path, include from django.contrib.auth.views import LoginView, PasswordResetView, LogoutView +from server.urls import router urlpatterns = [ @@ -25,4 +26,7 @@ urlpatterns = [ redirect_authenticated_user=True), name='login'), path('logout/', LogoutView.as_view(), name='logout'), path('password_reset/', PasswordResetView.as_view(), name='password_reset'), + path('api-auth/', include('rest_framework.urls')), + path('api/', include(router.urls)), + ] diff --git a/doccano/app/db.sqlite3 b/doccano/app/db.sqlite3 index ff72ec3d2248eba0021f21a29bbde948df77e5df..de5f7a585a84b009d79b46bc7fb4e428089c217b 100644 GIT binary patch delta 1231 zcmah}TTEO<7@mJ-cMoT8vtV&SO80QJSm9iDm%X5cjV*={gcV6-)$GMx=;C&F1!|)EoxHiVE*gGYlwL;tzQozV7iWQmd@(|C@vRbkV3Ubc0c4n9$&N2N`H zp~T>8i9tz{T;b@k;Y?VOWUthyxWlqbmNpmlQe(a17G#%Smi)52L6KdG)0h9W>_wfv znWkteUm@MGmQx=p$3xm^hwYHzR5X@Ig~ORtyddWgtAWoQ66>HimlnMc%3T(phoWoJ zYKF>AzwGn7oei?0xSUe{+xKc)j6gRK-JrkHA9J>~Y<_HQjOq#Dd1D?Te>g5?ZCbyU z)!8oVS|CC~mb;8wgg3C|u6lYAdM&xG?{t_8sXu%OrI>`Q&5XMWd2DS~Z(N0w76_?_ zK7;G$R9zQ&ld5OJ_?Yc)$@OhXbu5d=sJhXKbCjJCaocmrRC0Kv&y4lRPN5@{PK+GI zMW9DDl%g7}EEbE%Xr_{X{ zunf9_OJHEZIb2a>=-hN0p~;8ZIeUi)lOEQ)fMs?v1{T(L0bAMP0zOc-k2NRr+UQP4O0n|7`BvbIu=%Tndnoy84d!mqIGs^7T2?zZ{x2Fo}j_r zUh@xm&%bzzr)%f#Bb;b_>p!&QU0Plid>1!6kbNsBdw{cdYdQIn>3HJxDMu$~uc?7) zU;_y#hq~=cT1Y?-C-gki7VJ69qUUi-Zrr$st-OOdCiX);dpHJ%Rnt8Fjaamx#N3Lk zpPO4P)A*f(7;7N7xQqVssYKS^5oC^M#RV%4Sz^O?5TtfdA8B zw^nfNc7!EFzo$#|3oXJNWlO8rv2Py3945vfSX3U0#=Gv{&Q43f&sl#RB)SqF#TRbe0r4wQJw}n!Fln YHB_lWgxsM7*^tU*$?t#7CdfMd6P*THBme*a delta 9367 zcmcgyZHygN8NM@jx7%&Iom~l3EYN97No(MC`$5}24Vd(N5J z#l(Mx-p=X0Gv~Y?&-=X3Im7*D7TaKd%dDqP>AADnRw>MO{)J@-i%)Q7hygj{a?d8t=>5;W- zoC~JwYqvOir=MJVmoxCp;ERzrxapdW8?V_gSh{-Cx}l-XGp~L9it85?`U?f`UGMMS zpQroJH)f8UKjL-wVx|Q%&i?n8eY4SzKhHF}`k(B&-q~N=+xMrm=Zy1U=bAK(jlGl0oZnxcUR{EE$)H%{{ zk9Y|!)dz3cjDLD>d9U}q`+xken-_z{pYBWMPc1{-dmYCu77EV4G3@Qd;IC%zM>9BY z2EQ?bUzx#A&EQ!xm@$KIo545C;4w3Jm<99 zgR9NpN;6n#1|Knl0Ujh+e!l*y@V*)R!wlXsgEu5Dg;(|UC4K#+zWzjCpVikN=<8GZ zdRAY*qOT|QHF-!6j_T`Y^|ht1Rei1K>pp$GLtk&v*AbJ$!Zmg@sDE3nuZ4wh$8n0? z^XE;~DC@nw8++zWHDuV=y|Cc9#|qv@7a!?+WzpRWf8O)vg0Y_6#kYDsH1FkkJKba5 zGu@ZC$L75}v#$RWZs*tu_n@=jfu%R~ELpY6dGNmUyQketQ~#v9H2uSA_v*AwqkT`f zE7Gr4oc{FM31?&a+PHJs#r~dKcZ}^BUDI=OVPMJ5wa(P$uwGGzW7WCjQFoowHPw4_ zPdawWU7o&u(p`|AJL!JX-Td+NYmd8|ibI=s&|uA}({5kymigZ*AbEvCXLst3ImItK zPp4lv;a-)#^qBjL^yIXA*ZeE}71dx|Ri_UvSds3VcGo*=(y`O-b^Q*pPGM@vaLf|Ko1Ay>WF)|Lj}gua*_> z4l64@+?}YcN*O?jEf7DA)oO4%Q4sTceuXWN_&be3gc`smwvjy*W-dXPj%y7y} z&%Wp`y9_fdTR*sN%T`fsN|2D+hac{m)mhrZ-s3S*S@QvskG~RS)4t9H@qZU3D|$(AV2|0QS~ZS;a9D(F(`mRihatlVJskF8R0O z=K#)^+l>%$Alubp4oTpL)hbdJ)=T~vj0}B5F^uXea}%-JLm`Euk}mB>nfyJ}hBa`w z22*ekmWdISkg=pLq|EI$VGODvf)KRRU#~1)lmL4$5{pNK6aWQt;|qAH$lxe$5t39O z=#c;-T=1+yz6LGaY%@{wYk^)f&OJ@2LP!++Mmj_Mvb}vEz@*J~Qll>^(2ZuGVnhir zqkQ;bBc^!7h>;Wpd=Tg>gcy*Z@Yhw1vuA4wHD+KzOW_u{i|Hx`a2C9PJAO`J7+hs* z!-HWp?+a(s`lhq4am&%!6*Pf4L|x!tM;1_eI&ZKaE;8^BmsJC|h44ElhgDQcBLYGQ z^GTLZPCT4dNC8U2cujNCTu1^ewVuPLK(HE?TY*%X&rs0NXTQwK5(-o{f=&~1ZZTy! z5%91V##KTKkYt6kJ;1MHD}O{$i1xzR)5EJt_t2fF~)Bt7p6$XSlteRyGD@X)C5$$p!br%^P zM~o&_Qg3l0W^-0R+yQtPL|}q8S_r0Lo@d92$Bd^i)V2f_WmfS+C4X10v`vH42uc_j z>TsTo%TcolW)CIMVZ_)M>gC21a7cp~{D44d;s#exL(~?>lox~{IT&7TO$ zXmtn>zM}ez;!@%dS2XoXFXIqPzc!QM2TGSMy{6)ZNZpg#as{;2L{XIdZNg+xxg4l6 z0L@0Q!^C7iqH_qK`$J4anH=9 zz$Vo9sM_dhN{pm~+G&D*nnzDCZY|7vLk}@<>2awyAsW+ffOME3fkYweMoo=Sq>xAn zRF@S#%=sgU$Pgs5PJqYk(w9hffafwNggD`fX+5I5OkbSUgtnDtiVv&2LF zjm{=2g**I46_pBzu@t3cs8$GGMnVG{R`Fq>SyV^B=fWYu)sX^c8~)eSWI0A+mPZv79Pc8C zK18(Tc+4~?u7MF!uL5O};if#HLT3p>G=Kz(3k?9mUb`mkkMKmCNBl+~BcdoG=$s^L z3>)OFU~C}%bJ$Cq#-^o-4GIH*zaa!As5gUo7>5bS#yQW6G{$c*3GierkZj=GNl-YV z@>_1dV(Lb=6DC!PQ$;NpTN7|17PNZ|bgxWi!V~5+T+Oq*pR(19A0(A?4Av^b)|_w^ zi|kp->DDkI7G{;0NgfjqRHV!<{GEEvI>juru zv?msvwgt&oO*+gbA^wFB*8G&;>s%_{d5 znqC6!EEEh)rRTFdYT1J17zxS_4f9Bw>evhNESI$M*laS<<)x(^ zqMbc2fZmN}W%HHe{VYCq@546eLPMR2M$#MWIZcxZ9;+o(XaZ%n2)&$jt2w#J2@5HI z+Kg}|V*$PMzzj4CR;PogOzYUGF)5wo@D?y%T^J|k=!Wk>_Dn}a*qNz~G%%Q=1T(~K zOi=V=ESGh~pmuNuBS$bq0FqvlAC?@On8iWlIR#^M-rAblC6%()-7F1%-8+}rR9 zTEIaR9wr^@1?diw&wR?6sZubWRhhf(kloq&xJtn6{)wa+LS65)O`vWs)h&X z&@e}WEDiFIcL2e~DiVN_iZ90U}c1`5ALlVE{_i57mgv+?HWdU}HC9&;GoF96e zSONIAy}?2kJ^|enwrY?tSHNouSndosuuafnRErNRDd!y=AA}5PiLp~2hPkxU<1K>T z=hGTiH%NM^uw<9YE+u#nwu(|QfkNTv(^Ipl!BHqwh5-ao;|_SHkMs>Ba6DoUOJq~T z0H+jE&qI<}4;n4Rx5zQ2&MfXUXSuvXv3>1MR>ZKAaLAlQtquP+F(B*Y0MORo9^7r- zL*$O?q~^GAVG)i=dC2ov^8pAVS^^_SkdBz_yd&Cc{K!;GiDTzXqS!uC;y8=oKb*)9LW<-r)L4yz-7_tJd2^dAzR$Ynmo`$qB2~65= z>DLdY`H+qh(r0cKkFuT!&W57~f%2<9MWw0H3xskKPNmknx|%5CQvY~P(9A)zdJkXE zO%*x84MrcqwlN;&=`UD+5^8p{2Rl2Y~t^f#Z zxr>A`4`X9wX~l>bBeI15WoLtT19apEgDjWJhE(2l2%%${gDhM$wc%8X-f&9fVwhx) z8F1W2??|YSW#^IU-R!+UGs&|-mS)5ouMPR+LI7d*2y_cYGuML*NPOG8;6gtBa~hBR zCm|%smoXzoq8ga3EfFyF)P`?)xcCc^nL@eWWIw{jHh?qw)6^c_IDr@vU5oV-}C+hQ9R36 diff --git a/doccano/app/server/models.py b/doccano/app/server/models.py index 113128d9..a42cfe82 100644 --- a/doccano/app/server/models.py +++ b/doccano/app/server/models.py @@ -16,7 +16,7 @@ class Project(models.Model): class Label(models.Model): text = models.CharField(max_length=100, unique=True) shortcut = models.CharField(max_length=10, unique=True) - project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True) + project = models.ForeignKey(Project, on_delete=models.CASCADE) def as_dict(self): return {'id': self.id, diff --git a/doccano/app/server/serializers.py b/doccano/app/server/serializers.py new file mode 100644 index 00000000..49fe01d3 --- /dev/null +++ b/doccano/app/server/serializers.py @@ -0,0 +1,34 @@ +from rest_framework import serializers + +from .models import Label, Project, Document, Annotation + + +class ProjectSerializer(serializers.ModelSerializer): + + class Meta: + model = Project + fields = ('id', 'name', 'description', 'created_at', 'updated_at', 'users') + + +class LabelSerializer(serializers.ModelSerializer): + + class Meta: + model = Label + fields = ('id', 'text', 'shortcut') + + +class AnnotationSerializer(serializers.ModelSerializer): + label = LabelSerializer() + + class Meta: + model = Annotation + fields = ('id', 'prob', 'label') + + +class DocumentSerializer(serializers.ModelSerializer): + project = ProjectSerializer() + annotations = AnnotationSerializer(many=True) + + class Meta: + model = Document + fields = ('id', 'text', 'project', 'annotations') diff --git a/doccano/app/server/urls.py b/doccano/app/server/urls.py index 13ab724b..6ddf6fa4 100644 --- a/doccano/app/server/urls.py +++ b/doccano/app/server/urls.py @@ -3,6 +3,16 @@ from django.urls import path from .views import IndexView from .views import AnnotationAPIView, ProgressAPI, SearchAPI, InboxView from .views import ProjectListView, ProjectAdminView, RawDataAPI, LabelAPI, DataDownloadAPI +from rest_framework import routers +from .views import LabelViewSet, ProjectViewSet, DocumentViewSet + + +router = routers.DefaultRouter() +router.register(r'labels', LabelViewSet) +router.register(r'projects', ProjectViewSet) +router.register(r'documents', DocumentViewSet) +#router.register(r'users', UserViewSet) + urlpatterns = [ path('', IndexView.as_view(), name='index'), diff --git a/doccano/app/server/views.py b/doccano/app/server/views.py index b3767c02..0abf3f29 100644 --- a/doccano/app/server/views.py +++ b/doccano/app/server/views.py @@ -1,13 +1,16 @@ import json +import django_filters from django.http import JsonResponse, HttpResponse from django.shortcuts import render from django.views import View from django.views.generic.list import ListView from django.views.generic.detail import DetailView from django.core.paginator import Paginator +from rest_framework import viewsets, filters from .models import Annotation, Label, Document, Project +from .serializers import LabelSerializer, ProjectSerializer, DocumentSerializer class IndexView(View): @@ -195,3 +198,19 @@ class DataDownloadAPI(View): response['Content-Disposition'] = 'attachment; filename=annotation_data.json' return response + + +class LabelViewSet(viewsets.ModelViewSet): + queryset = Label.objects.all() + serializer_class = LabelSerializer + filter_fields = ('text', 'project') + + +class ProjectViewSet(viewsets.ModelViewSet): + queryset = Project.objects.all() + serializer_class = ProjectSerializer + + +class DocumentViewSet(viewsets.ModelViewSet): + queryset = Document.objects.all() + serializer_class = DocumentSerializer