0

私はモデルを持っています: course と中間結合モデルの coursetag を持つタグ (多対多の関係用)。

私の API では、TagResource はコースの数とともにタグを表示します。次に、ユーザーが (API を介して) 特定のタグを要求すると、指定されたタグを持つすべてのコースのリストが取得されます。これはすべて正常に機能しています...ただし、ユーザーに応じてコースをフィルタリングできるようにする必要があります (user.is_staff が True に設定されているかどうか)。

タグ リスト API でコースの正しい数を表示するようにこれを機能させることができますが、特定のタグが選択されたときにコースをフィルター処理する方法を理解するのに問題があります。

私のAPIリソースは次のとおりです。

class TagResource(ModelResource):
    count = fields.IntegerField(readonly=True)
    courses = fields.ToManyField('oppia.api.resources.CourseTagResource', 'coursetag_set', related_name='tag', full=True)

    class Meta:
        queryset = Tag.objects.filter(courses__isnull=False).distinct().order_by("name")
        resource_name = 'tag'
        allowed_methods = ['get']
        fields = ['id','name']
        authentication = ApiKeyAuthentication()
        authorization = ReadOnlyAuthorization() 
        always_return_data = True
        include_resource_uri = False
        serializer = TagJSONSerializer()

    def dehydrate_count(self,bundle):
        if bundle.request.user.is_staff:
            count = Course.objects.filter(tag__id=bundle.obj.id).count()
        else:
            count = Course.objects.filter(tag__id=bundle.obj.id, staff_only=False).count()
        return count 

class CourseResource(ModelResource):

    class Meta:
        queryset = Course.objects.all()
        resource_name = 'course'
        allowed_methods = ['get']
        fields = ['id', 'title', 'version', 'shortname']
        authentication = ApiKeyAuthentication()
        authorization = ReadOnlyAuthorization() 
        serializer = CourseJSONSerializer()
        always_return_data = True
        include_resource_uri = True

class CourseTagResource(ModelResource):
    course = fields.ToOneField('oppia.api.resources.CourseResource', 'course', full=True)
    class Meta:
        queryset = CourseTag.objects.all()
        allowed_methods = ['get']
        fields = ['id','course','tag']
        include_resource_uri = False
        authentication = ApiKeyAuthentication()
        authorization = ReadOnlyAuthorization()
        always_return_data = True  

サンプルのリクエスト/レスポンスは次のとおりです。

タグのリスト (例: http://localhost/python/api/v1/tag/?username=XXXetc) については、期待どおりの応答が得られます。

{"meta": {"limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 10}, "tags": [{"count": 1, "id": 8, "name": "34343434"}, {"count": 2, "id": 2, "name": "Education"}, {"count": 1, "id": 7, "name": "Engineering"}, {"count": 1, "id": 13, "name": "Ethiopia"}, {"count": 1, "id": 10, "name": "health"}, {"count": 5, "id": 1, "name": "Healthcare"}, {"count": 1, "id": 11, "name": "phone"}, {"count": 1, "id": 12, "name": "PNC"}, {"count": 1, "id": 6, "name": "Solar"}, {"count": 1, "id": 9, "name": "test"}]}

ただし、特定のタグ (例: http://localhost/python/api/v1/tag/13/?username=XXXetc) については、正しいカウント (1 コース) を取得しますが、間違ったコース リスト (2 コース) を取得します。

{"count": 1, "courses": [{"id": 2, "resource_uri": "/python/api/v1/course/2/", "shortname": "pnc", "title": {"en": "Postnatal Care"}, "url": "http://localhost/python/api/v1/course/2/download/", "version": "20131105085218"}, {"id": 30, "resource_uri": "/python/api/v1/course/30/", "shortname": "anc2", "title": {"en": "Antenatal Care v2"}, "url": "http://localhost/python/api/v1/course/30/download/", "version": "20131106162547"}], "id": 13, "name": "Ethiopia"}

ここで与えられたものと同様のアプローチを使用しようとしました: Request.user によって django-tastypie の ToManyField をフィルター処理する方法は? しかし、user.is_staff.

また、CourseResource と CourseTagResource に認可制限を設定しようとしましたが、これも違いはないようです。

情報については、tastypie 0.9.16 と Django 1.5 を使用しています。

ヘルプ/ポインターは大歓迎です。正しいアプローチを取っているかどうかについてのアドバイスは役に立ちます-代わりにコースモデルのアクセス許可を確認する必要があるかどうかわかりませんでしたか?

ありがとう

4

1 に答える 1

0

私は最終的に私が望んでいたことを達成する方法を考え出しました...それはきれいではなく、確かにこのアプローチをお勧めしませんが、それは私にとってはうまくいきます。

最終的に TagResource の ToManyField を削除し、次を使用して API 詳細 URI をオーバーライドしました。

def prepend_urls(self):
    return [
        url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('tag_detail'), name="api_tag_detail"),
        ]

def tag_detail(self, request, **kwargs): 
    self.is_authenticated(request)
    self.throttle_check(request)

    pk = kwargs.pop('pk', None)
    try:
        tag = self._meta.queryset.get(pk = pk)
    except Tag.DoesNotExist:
        raise NotFound(_(u'Tag not found'))

    if request.user.is_staff:
        courses = Course.objects.filter(tag=tag, is_archived=False).order_by("title")
    else:
        courses = Course.objects.filter(tag=tag, is_archived=False,is_draft=False).order_by("title")

    course_data = []
    cr = CourseResource()
    for c in courses:
        bundle = cr.build_bundle(obj=c,request=request)
        d = cr.full_dehydrate(bundle)
        course_data.append(bundle.data)

    response = HttpResponse(content=json.dumps({'id':pk,'count':courses.count(),'courses':course_data,'name':tag.name}),content_type="application/json; charset=utf-8")
    return response

誰かがより良いアプローチを持っているなら、私は聞いてうれしいです...

于 2013-11-15T12:23:17.760 に答える