django-tastypie を使用して POST 経由でユーザー リソースを作成しようとしています。
モデル:
- ユーザープロフィール
- ユーザー (django.contrib.auth.models から)
資力:
- CreateUserResource
- ユーザーリソース
- UserProfileResrouce
エラーが発生し続けます
キーワード 'city' をフィールドに解決できません。選択肢: api_key、date_joined、email、first_name、groups、id、is_active、is_staff、is_superuser、last_login、last_name、logentry、password、profile、rating、user_permissions、username
私は django-tastypie を初めて使用しますが、コードのトレースまたは django/tastypie コードでエラーを見つけることができません。なぜこれを行うのですか?私のコードは、次のブログ投稿に基づいています: http://psjinx.com/programming/2013/06/07/so-you-want-to-create-users-using-djangotastypie/
よろしくお願いします!
モデル.py
from django.utils.translation import ugettext as gtext
class UserProfile(models.Model):
"""
A Model to store extra information for each user
"""
user = models.OneToOneField(User, related_name='profile')
gender = models.CharField(gtext("gender"), max_length=10)
city = models.CharField(gtext("city"), max_length=20)
def __unicode__(self):
return self.user.get_full_name()
Api.py
class CreateUserResource(ModelResource):
user = fields.ForeignKey('RecommenuAPI.api.UserResource', 'user', full=True)
class Meta:
allowed_methods = ['post']
always_return_data = True
authentication = Authentication()
authorization = Authorization()
queryset = UserProfile.objects.all()
resource_name = "create_user"
always_return_data = True
def hydrate(self, bundle):
"""
Makes sure all required fields in UserProfile
and User are fulfilled. Custom error message returned if not
"""
REQUIRED_USER_PROFILE_FIELDS = ( "city", "gender", "user")
for field in REQUIRED_USER_PROFILE_FIELDS:
if field not in bundle.data["user"]:
raise CustomBadRequest(
code = "missing_key",
message = "Must provide {missing_key} when creating a user."
.format(missing_key=field))
REQUIRED_USER_FIELDS = ("username", "email", "first_name", "last_name", "raw_password")
for field in REQUIRED_USER_FIELDS:
if field not in bundle.data["user"]:
raise CustomBadRequest(
code = "missing_key",
message="Must provide {missing_key} when creating a user."
.format(missing_key=field))
return bundle
def obj_create(self, bundle, **kwargs):
"""
Creates new user. Checks for existing password
and email match.
"""
try:
email = bundle.data["user"]["email"]
username = bundle.data["user"]["username"]
if User.objects.filter(email=email):
raise CustomBadRequest(
code = "duplicate_exception",
message = "That email is already used.")
if User.objects.filter(username=username):
raise CustomBadRequest(
code = "duplicate_exception",
message = "That username is already used")
except KeyError as missing_key:
raise CustomBadRequest(
code = "missing_key",
message = "Must provide {missing_key} when creating a user."
.format(missing_key=missing_key))
except User.DoesNotExist:
pass
#setting resource_name to 'user_profile' here because we want
#resource_uri in response to be same as UserProfileResource resource
self._meta.resource_name = UserProfileResource._meta.resource_name
return super(CreateUserResource, self).obj_create(bundle, **kwargs)
class UserResource(ModelResource):
# We need to store raw password in a virtual field because hydrate method
# is called multiple times depending on if it is a POST/PUT/PATCH request
raw_password = fields.CharField(attribute=None, readonly=True, null=True, blank=True)
class Meta:
# For authentication, allow both basic and api key so that the key
# can be grabbed, if needed
authentication = MultiAuthentication(
BasicAuthentication(),
ApiKeyAuthentication())
authorization = Authorization()
# Because this can be updated nested under the UserProfile, it needed
# 'put'. No idea why, since patch is supposed to be able to handle
# partial updates
allowed_methods = ['get', 'patch', 'put']
always_return_data = True
queryset = User.objects.all().select_related("api_key")
excludes = ['is_active', 'is_staff', 'is_superuser', 'date_joined', 'last_login']
def authorized_read_list(self, object_list, bundle):
return object_list.filter(id=bundle.request.user.id).select_related()
def hydrate(self, bundle):
if "raw_password" in bundle.data:
# Pop our raw_password and validate it
# This will prevent re-validation because hydrate is called multiple times
# "Cannot resolve keyword 'raw_password' into field." wont occur
raw_password = bundle.data.pop["raw_password"]
#Validate password
if not validate_password(raw_password):
if len(raw_password) < MINIMUM_PASSWORD_LENGTH:
raise CustomBadRequest(
code="invalid_password",
message=(
"Your password should contain at least {length} "
"characters.".format(length=
MINIMUM_PASSWORD_LENGTH)))
raise CustomBadRequest(
code="invalid_password",
message=("Your password should contain at least one number"
", one uppercase letter, one special character,"
" and no spaces."))
bundle.data["password"] = make_password(raw_password)
return bundle
def dehydrate(self, bundle):
bundle.data["key"] = bundle.obj.api_key.key
try:
#Don't return 'raw_password' in response
del bundle.data["raw_password"]
except KeyError:
pass
return bundle
class UserProfileResource(ModelResource):
user = fields.ForeignKey(UserResource, 'user', full=True)
class Meta:
# For authentication, allow both basic and api key so that the key
# can be grabbed, if needed
authentication = MultiAuthentication(
BasicAuthentication(),
ApiKeyAuthentication())
authorization = Authorization()
always_return_data = True
allowed_methods = ['get', 'patch', ]
detail_allowed_methods = ['get', 'patch', 'put']
queryset = UserProfile.objects.all()
resource_name = 'user_profile'
def authorized_read_list(self, object_list, bundle):
return object_list.filter(user=bundle.request.user).select_related()
## Since there is only one user profile object, call get_detail instead
def get_list(self, request, **kwargs):
kwargs["pk"] = request.user.profile.pk
return super(UserProfileResource, self).get_detail(request, **kwargs)
[編集] トレースの追加
Traceback (most recent call last):
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/resources.py\", line 217, in wrapper
response = callback(request, *args, **kwargs)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/resources.py\", line 459, in dispatch_list
return self.dispatch('list', request, **kwargs)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/resources.py\", line 491, in dispatch
response = method(request, **kwargs)
File \"/Users/Carlos/.virtualenvs/recommenu/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 \"/Users/Carlos/PycharmProjects/RecommenuBackend/RecommenuAPI/api.py\", line 82, in obj_create
return super(CreateUserResource, self).obj_create(bundle, **kwargs)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/resources.py\", line 2149, in obj_create
bundle = self.full_hydrate(bundle)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/resources.py\", line 909, in full_hydrate
value = field_object.hydrate(bundle)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/fields.py\", line 737, in hydrate
return self.build_related_resource(value, request=bundle.request)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/fields.py\", line 661, in build_related_resource
return self.resource_from_data(self.fk_resource, value, **kwargs)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/fields.py\", line 605, in resource_from_data
return fk_resource.obj_update(fk_bundle, skip_errors=True, **data)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/resources.py\", line 2205, in obj_update
bundle.obj = self.obj_get(bundle=bundle, **lookup_kwargs)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/tastypie/resources.py\", line 2125, in obj_get
object_list = self.get_object_list(bundle.request).filter(**kwargs)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/django/db/models/query.py\", line 655, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/django/db/models/query.py\", line 673, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File \"/Users/Carlos/.virtualenvs/recommenu/lib/python2.7/site-packages/django/db/models/sql/query.py\", line 1266, in add_q
can_reuse=us(