2016-07-05 1 views
0

맞춤 URL을 사용하여 리소스를 삭제하려고합니다. 따라서 기본 리소스 인 Tastypie url에 DELETE를 허용하는 대신 새 리소스를 정의했습니다. 삭제 기능은 작동하지만 여전히 코드에 누락 된 부분이 있기 때문에 오류가 발생합니다. 삭제를 수행하는 기능은 cancel_ride_request입니다.Tastypie : 사용자 정의 URL에 리소스 삭제를 구현합니다.

class DemandResource(ModelResource): 
""" 
Handles ride requests resources. In particular: 
    - Offers information about the logged user's ride requests 
    - Allows new ride requests creation 
""" 

user = fields.ForeignKey(UserResource, 'passenger') 
origin = fields.ForeignKey(NodeResource, 'origin', full=True) 
destination = fields.ForeignKey(NodeResource, 'destination', full=True) 

potential_drivers = fields.ListField(readonly=True) 

class Meta: 
    queryset = api.models.Demand.objects.all() 
    resource_name = _Helpers.demand_resource_name 
    list_allowed_methods = ['get'] 
    detail_allowed_methods = ['get', 'put', 'patch'] 
    authentication = BasicAuthentication() 

def prepend_urls(self): 
    return [ 
      url(r"^(?P<resource_name>%s)/register%s" % (self._meta.resource_name, trailing_slash()), 
       self.wrap_view('register_ride_request'), name="api_ask_ride"), 
      url(r"^(?P<resource_name>%s)/(?P<pk>.*?)/cancel%s" % (self._meta.resource_name, trailing_slash()), 
       self.wrap_view('cancel_ride_request'), name="api_cancel_ride_request"), 
      ] 

@classmethod 
def dehydrate_potential_drivers(cls, bundle): 
    return _Helpers.serialise_passengerships_passenger(bundle.obj.passengership_set.select_related().all()) 

def hydrate(self, bundle): 
    bundle.data['user'] = bundle.request.user 

    #extract orign and destination ID 
    bundle.data['origin'] = api.models.Node.objects.get(id=bundle.data['origin']['id']) 
    bundle.data['destination'] = api.models.Node.objects.get(id=bundle.data['destination']['id']) 

    bundle.data['arrival_time'] = datetime.strptime(bundle.data['arrival_time'], _Helpers.date_time_format) 
    tz = pytz.timezone('Europe/Brussels') #TODO get the user time zone 
    bundle.data['arrival_time'] = tz.localize(bundle.data['arrival_time']) 
    bundle.data['arrival_time_tolerance_early'] = timedelta(minutes=int(bundle.data['arrival_time_tolerance_early'])) 
    bundle.data['arrival_time_tolerance_late'] = timedelta(minutes=int(bundle.data['arrival_time_tolerance_late'])) 

    return bundle 

def register_ride_request(self, request, **kwargs): 
    self.method_check(request, ['post', ]) 
    self.is_authenticated(request) 
    data = json.loads(request.body) 
    bundle = self.build_bundle(data=data, request=request) 
    bundle = self.hydrate(bundle) 
    demand = api.models.Demand(passenger=bundle.request.user, 
           origin=bundle.data['origin'], 
           destination=bundle.data['destination'], 
           arrival_time=bundle.data['arrival_time'], 
           arrival_time_tolerance_early=bundle.data['arrival_time_tolerance_early'], 
           arrival_time_tolerance_late=bundle.data['arrival_time_tolerance_late']) 
    demand.save() 
    return HttpResponse(status=201) 

""" 
Handling demand deletion, making sure the request type is a DELETE and the user is authenticated 
""" 
def cancel_ride_request(self, request, **kwargs): 
    self.method_check(request, ['delete', ]) 
    self.is_authenticated(request) 
    return api.models.Demand.objects.filter(pk=kwargs['pk']).delete() 

""" 
Makes sure that only the owner of a demand is able to delete it 
""" 
def delete_detail(self, object_list, bundle): 
    return bundle.obj.passenger == bundle.request.user 

나는 또한 내가 기능 register_ride_request와 자원 생성을 구현 한 방법은 최적이 아닌 생각합니다. 그것은 작동하지만 이상한 나는 수동으로 HTTPResponse 코드를 반환해야합니다. 더 좋은 방법이 없을까요? 한 게시물에 두 가지 질문에 대해 고마워하며 미안하지만 관련이 있다고 느낍니다.

답변

0

그래서 결국 해결책을 찾았습니다. 심지어 가장 좋은 접근 방식인지 확신 할 수 없기 때문에 누군가가 의견을 말하면 더 행복합니다. 나는 다른 사람의 사이에서, 다음과 같은 방법을 가지고있는 사용자 정의 인증 클래스를 구현했습니다 :

class UserObjectsOnlyAuthorization(Authorization) 

    def delete_detail(self, bundle): 
     return self.request_is_from_owner(bundle) 

    def request_is_from_owner(self, bundle): 
     if hasattr(bundle.obj, "passenger"): 
      return bundle.obj.passenger.pk == bundle.request.user.member.pk 
     elif hasattr(bundle.obj, "driver"): 
      return bundle.obj.driver == bundle.request.user.member 
     return bundle.obj.user == bundle.request.user.member 

이 클래스는 개체의 소유자 만이 그것을 삭제할 수 있는지 확인하는 데 사용됩니다. 그런 다음 내 DemandResource 클래스에서 resouce 삭제가 맞춤 URL에서 발생하기 때문에 obj_delete 메소드를 덮어 썼습니다.

def prepend_urls(self): 
    return [ 
      url(r"^(?P<resource_name>%s)/register%s" % (self._meta.resource_name, trailing_slash()), 
       self.wrap_view('register_ride_request'), name="api_ask_ride"), 
      url(r"^(?P<resource_name>%s)/(?P<pk>.*?)/cancel%s" % (self._meta.resource_name, trailing_slash()), 
       self.wrap_view('cancel_ride_request'), name="api_cancel_ride_request"), 
      ] 

def cancel_ride_request(self, request, **kwargs): 
    """ 
    Handling demand deletion, making sure the request type is a DELETE and the user is authenticated 
    :param request: the HTTP request data 
    """ 
    self.method_check(request, ['delete', ]) 
    self.is_authenticated(request) 
    # call the delete, deleting the obj from the database 
    try: 
     # get an instance of the bundle.obj that will be deleted 
     obj = api.models.Demand.objects.get(pk=kwargs['pk']) 
    except ObjectDoesNotExist: 
     raise NotFound("The object does not exist.") 
    bundle = Bundle(request=request, obj=obj) 
    if self._meta.authorization.delete_detail(bundle): 
     try: 
      print "Entered" 
      self.obj_delete(bundle, **kwargs) 
      return http.HttpNoContent() 
     except NotFound: 
      return http.HttpNotFound() 
    else: return HttpResponse(status=401) #unauthorized 

def obj_delete(self, bundle, **kwargs): 
    try: 
     # get an instance of the bundle.obj that will be deleted 
     api.models.Demand.objects.get(pk=kwargs['pk']).delete() 
    except ObjectDoesNotExist: 
     raise NotFound("The object does not exist.") 
: 나는 사용자 정의 URL에 대한 코드를 보여 아래, 확인하기 위해 사용자 정의 인증 클래스를 사용하여 요청과 덮어 obj_delete 방법을 응답 함수는 요청은 (모든 클래스 DemandResource에) 허가
관련 문제