TastyPie数据验证问题

时间:2014-02-06 13:46:08

标签: django validation tastypie

我想知道使用TastyPie验证的正确方法是什么。 我有以下资源和模型:

from tastypie.resources import ModelResource

class Station(models.Model):
    name = models.CharField(max_length=20)
    city = models.ForeignKey(City)

class StationResource(ModelResource):
    city = fields.ForeignKey(CityResource, 'city')

    class Meta:
        queryset = caModels.Station.objects.all()
        resource_name = 'Station'
        authorization = Authorization()
        validation=FormValidation(form_class=StationForm)
        max_limit = None    

我还想使用ModelForm来验证数据:

class StationForm(forms.ModelForm):    

    class Meta:
        model = caModels.Station

    def clean_city(self):
        return self.cleaned_data['city']

以下查询正常工作:

curl --dump-header - -H "Content-Type: application/json" -X POST --data '{"city": "/resources/City/89/", "name": "station_1", <and other fields here>}' "http://localhost:8000/resources/Station/?format=json"

HTTP/1.0 201 CREATED
Date: Thu, 06 Feb 2014 13:10:14 GMT
Server: WSGIServer/0.1 Python/2.7.4
Vary: Accept, Cookie
Content-Type: text/html; charset=utf-8
Location: http://localhost:8000/resources/Station/3/

但是当我从请求中移除城市(但需要此字段)而不是消息“此字段是必需的”时,我得到以下追溯:

Traceback (most recent call last):
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 77, in wrapped_view
return view_func(*args, **kwargs)
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/tastypie/resources.py", line 217, in wrapper
response = callback(request, *args, **kwargs)
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/tastypie/resources.py", line 459, in dispatch_list
return self.dispatch('list', request, **kwargs)
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/tastypie/resources.py", line 491, in dispatch
response = method(request, **kwargs)
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/tastypie/resources.py", line 1357, in post_list
updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kwargs))
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/tastypie/resources.py", line 2149, in obj_create
bundle = self.full_hydrate(bundle)
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/tastypie/resources.py", line 909, in full_hydrate
value = field_object.hydrate(bundle)
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/tastypie/fields.py", line 732, in hydrate
value = super(ToOneField, self).hydrate(bundle)
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/tastypie/fields.py", line 165, in hydrate
elif self.attribute and getattr(bundle.obj, self.attribute, None):
  File "/home/ak/venv/main_env/local/lib/python2.7/site-packages/django/db/models/fields/related.py", line 389, in __get__
raise self.field.rel.to.DoesNotExist
DoesNotExist

甚至在我可以验证表单中的数据之前就会发生此错误(验证是保存过程的第一个过程)。

.../tastypie/resources.py:

def obj_create(self, bundle, **kwargs):
    """
    A ORM-specific implementation of ``obj_create``.
    """
    bundle.obj = self._meta.object_class()

    for key, value in kwargs.items():
        setattr(bundle.obj, key, value)

    self.authorized_create_detail(self.get_object_list(bundle.request), bundle)
    bundle = self.full_hydrate(bundle)
    return self.save(bundle)

def save(self, bundle, skip_errors=False):
    self.is_valid(bundle)
    ...

有人可以指出我错在哪里,或者可能是我错过了什么,从TastyPie的角度来看,这种验证方式是完全错误的吗?

1 个答案:

答案 0 :(得分:0)

我认为你的问题非常有趣 我决定在主题中挖掘一下..

这是我发现的。

  1. 文档: blank
    我们看到这个描述与我们从Django已经知道的很相似。

  2. 代码库: hydrate 如果你没有明确说明Tastypie会“期望”这个领域在那里。

  3. 简短的结论:我认为资源类似于模型之外的东西,Meta可能会对需求有很大的不同,这可以为您提供更多的灵活性。

    潜在的解决方案:

    1. 对Tastypie说,如果它的空白则传递给它。无论如何模型验证都不会通过它。

      class StationResource(ModelResource):
           city = fields.ForeignKey(CityResource, 'city', blank=True)
      
    2. 或者添加默认水合物。

      class StationResource(ModelResource):
          city = fields.ForeignKey(CityResource, 'city')
      
          def hydrate(self, bundle):
              if not hasattr(bundle, 'city'):
                  bundle.data['city'] = None
              return bundle
      
    3. 结论:这实际上很容易引起误解,但另一方面Tastypie仍处于开发阶段,也许文档会更好地覆盖它,或者这会改变,或者有计划改变它。

      如果您对此感兴趣,可以在github上讨论许多问题:类似于您的问题:issue