问题陈述很简单, 2型号:UserGames,UserHost
用户发出帖子请求以加入游戏,然后在UserGames中创建记录,如果在请求中传递了Hosting参数,则创建UserGames和UserHost记录。 UserHost具有对UserGames的外键引用。
我可以在**
中创建UserGames记录**但我需要记录UserGames对象ID才能在UserHost中创建记录。
第二个问题,我需要在输出中返回一个数组UserGames (if user is not hosting
)或else UserGames + UserHost combined array
。
答案 0 :(得分:4)
我尝试使用abstract model实现此功能,然后通过ModelResource
公开。我必须覆盖obj_create
和get_resource_uri
方法。
请查看示例代码(我已在本地计算机上测试过这个代码)。
from django.db import models
from django.contrib.auth.models import User
class UserGame(models.Model):
user = models.ForeignKey(User)
# more fields like name etc.
name = models.CharField("name", max_length=40)
def __unicode__(self):
return self.name
class UserHost(models.Model):
game = models.ForeignKey(UserGame)
# more fields like hostname etc.
hostname = models.CharField("host name", max_length=40)
def __unicode__(self):
return self.hostname
class JoinGame(models.Model):
game = models.ForeignKey(UserGame)
host = models.ForeignKey(UserHost)
class Meta:
abstract = True
from django.contrib.auth.models import User
from tastypie import fields
from tastypie.authentication import (BasicAuthentication, ApiKeyAuthentication,
MultiAuthentication)
from tastypie.authorization import Authorization
from tastypie.resources import Resource, ModelResource
from tastypie.exceptions import BadRequest
from .models import UserGame, UserHost, JoinGame
class UserResource(ModelResource):
class Meta:
resource_name = "user"
# 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 other Resources.
# It needs put/patch 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', 'password']
class UserGameResource(ModelResource):
user = fields.ForeignKey(UserResource, 'user', full=True)
class Meta:
resource_name = "user_game"
authentication = ApiKeyAuthentication()
authorization = Authorization()
# Because this can be updated nested under the other Resources.
# It needs put/patch to be able to handle partial updates.
allowed_methods = ['get', 'post', 'patch', 'put']
always_return_data = True
queryset = UserGame.objects.all()
class UserHostResource(ModelResource):
resource_name = "user_host"
user_game = fields.ForeignKey(UserGameResource, 'game', full=True)
class Meta:
authentication = ApiKeyAuthentication()
authorization = Authorization()
# Because this can be updated nested under the other Resources.
# It needs put/patch to be able to handle partial updates.
allowed_methods = ['get', 'post', 'patch', 'put']
always_return_data = True
queryset = UserHost.objects.all()
class JoinGameResource(Resource):
game = fields.ForeignKey(UserGameResource, "game", null=True, full=True)
host = fields.ForeignKey(UserHostResource, "host", null=True, full=True)
class Meta:
resource_name = "join_game"
object_class = JoinGame
authentication = ApiKeyAuthentication()
authorization = Authorization()
# Because this can be updated nested under the other Resources.
# It needs put/patch to be able to handle partial updates.
list_allowed_methods = ['post']
detail_allowed_methods = []
fields = ["game", "host"]
always_return_data = True
def hydrate(self, bundle):
if "game" not in bundle.data:
raise BadRequest("Must provide 'game' when joining a game.")
return bundle
def obj_create(self, bundle, **kwargs):
try:
game = bundle.data.get("game")
game_bundle = self.build_bundle(obj=UserGame(), data=game,
request=bundle.request)
updated_game_bundle = UserGameResource().obj_create(
game_bundle, **kwargs)
bundle.obj.game = updated_game_bundle.obj
except KeyError:
raise BadRequest("Must provide 'game' when joining a game.")
try:
host = bundle.data.get("host")
host_bundle = self.build_bundle(obj=UserHost(), data=host,
request=bundle.request)
updated_host_bundle = UserHostResource().obj_create(
host_bundle, game=updated_game_bundle.obj, **kwargs)
bundle.obj.host = updated_host_bundle.obj
except KeyError:
pass
#raise BadRequest("Must provide 'host' when joining a host.")
return bundle
def get_resource_uri(self, updated_bundle):
# Since JoinGame is abstract model, pk won't be available
# So, get_resource_uri method of ModelResource will raise exception
# Let's override that
return None
from .api import (
UserResource, UserGameResource, UserHostResource, JoinGameResource)
from django.conf.urls import patterns, include
from tastypie.api import Api
# Create an empty pattern so that we can just build it using +=
urlpatterns = patterns(None)
#==============================================================================
# API Resources
#==============================================================================
v1_api = Api(api_name='v1')
v1_api.register(UserResource())
v1_api.register(UserGameResource())
v1_api.register(UserHostResource())
v1_api.register(JoinGameResource())
urlpatterns += patterns(
'',
(r'^api/', include(v1_api.urls)),
)
{
"game": {
"name": "New Game",
"user": "/api/v1/user/1/"
},
"host": {
"hostname": "New Host name"
}
}
{
"game": {
"id": 15,
"name": "New Game",
"resource_uri": "/api/v1/user_game/15/",
"user": {
"email": "psjinx@example.com",
"first_name": "",
"id": 1,
"last_name": "",
"resource_uri": "/api/v1/user/1/",
"username": "psjinx"
}
},
"host": {
"hostname": "New Host name",
"id": 13,
"resource_uri": "/api/v1/userhost/13/",
"user_game": {
"id": 15,
"name": "New Game",
"resource_uri": "/api/v1/user_game/15/",
"user": {
"email": "psjinx@example.com",
"first_name": "",
"id": 1,
"last_name": "",
"resource_uri": "/api/v1/user/1/",
"username": "psjinx"
}
}
},
"resource_uri": null
}