2011-11-18 5 views
9

Mam model strony z GFK.Django tastypie i GenericForeignKey

class Page(models.Model): 
    title = models.CharField(max_length=200) 
    content_type = models.ForeignKey(ContentType,null=True,blank=True) 
    object_id = models.CharField(max_length=255,null=True,blank=True) 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 

i

class TextContent(models.Model): 
    content = models.TextField(null=True, blank=True) 
    pages = generic.GenericRelation(Page) 

zrobić Page.objects.get (pk = 1) .content_object i mam go.

Proszę mi pomóc, aby pokazać link (lub wynik do JSON), który zakotwiczony obiekt w REST.

class PageResource(ModelResource): 
    content_object = fields.????? 

    class Meta: 
     queryset = Page.objects.all() 
     resource_name = 'page' 

Jak zrobić to dobrze?

Dzięki!

Vitaliy

+1

Czy kiedykolwiek działałaś tak, nie stosując łatek do smaku? –

Odpowiedz

7

Obecnie nie łatwy sposób za pomocą relacji generycznych w tastypie. Niektóre łatki zostały przesłane pod numer tastypie github page, ale nie zostały scalone po tym pisaniu.

Najprostszym sposobem, aby to zrobić, zdefiniuj zasób contenttype i użyj go dla zasobów o relacji ogólnej. Coś w rodzaju:

class ContentTypeResource(ModelResource): 
    class Meta: 
     queryset = ContentType.objects.all() 
     resource_name = "contrib/contenttype" 
     fields = ['model'] 
     detail_allowed_methods = ['get',] 
     list_allowed_methods = ['get'] 

class PageResource(ModelResource): 
    content_object = fields.ToOneField('myresources.ContentTypeResource', 'content_object') 


    class Meta: 
     queryset = Page.objects.all() 
     resource_name = 'page' 

Mam nadzieję, że to pomoże.

+0

Próbuję wprowadzić to teraz. Czy możesz podać trochę więcej kontekstu, aby pomóc mi zrozumieć. Mam dodatek, który ma ogólny stosunek do atrybutów. Chciałbym uzyskać wszystkie atrybuty dla danego dodatku. w twoim przykładzie, do czego odnoszą się 'myresources, "contrib/contenttype", "model". Dzięki. –

+0

Uwaga na coś, co mnie wkurzyło podczas implementacji tego: jeśli używasz odwrotnych relacji ogólnych, nie możesz zapomnieć użyć pól. ToManyField w modelu, który uzyskuje dostęp do zasobu ogólnego. – Wilerson

5

Rzecz "myresources" to aplikacja, która zawiera ContentTypeResource. Jeśli jest w tej samej aplikacji co inne zasoby, nie musisz tego kwalifikować. Usunięto w poniższym kodzie.

"contrib/contenttype" to nazwa zasobu. Ustawienie własnego imienia jest opcjonalne. Tastypie utworzy dla Ciebie, jeśli go nie określisz. Usunąłem go w poniższym kodzie aktualizacji.

Sekcja fields = ['model'] ogranicza dostępne pola z modelu reprezentowanego przez ten zasób. Jeśli spojrzysz na definicję modelu ContentType w kodzie Django, zobaczysz, że ma pole o nazwie "model".

Myślę, że oryginalna odpowiedź zawierała pomieszane nazwy pól. Próbujesz utworzyć nowy zasób dla content_type i podpiąć go do klucza obcego typu content_type w swoim modelu. Powyższy kod to sortuje.

class ContentTypeResource(ModelResource): 
    class Meta: 
     queryset = ContentType.objects.all() 
     fields = ['model'] 
     detail_allowed_methods = ['get',] 
     list_allowed_methods = ['get'] 

class PageResource(ModelResource): 
    content_type = fields.ToOneField('ContentTypeResource', 'content_type') 

    class Meta: 
     queryset = Page.objects.all() 
     resource_name = 'page' 

Będziesz także musiał zarejestrować ContentTypeResource w urls.py jak masz ze wszystkimi innymi zasobami:

from myapp.api import ContentTypeResource 

v1_api = Api(api_name='v1') 
v1_api.register(ContentTypeResource()) 

W „myapp” bit jest ponownie aplikacja z api kod zawierający ContentTypeResource.

Mam nadzieję, że to wszystko wyjaśni. Właśnie zrobiłem to działa ...

1

Daje to pole content_object jako obiekt zagnieżdżony. To proste, działa i jest (niestety) tak wydajne, jak pozwoli na to technologia.

class PageResource(ModelResource): 

    def full_dehydrate(self, bundle): 
     new_bundle = super(PageResource, self).full_dehydrate(bundle) 
     new_bundle.data['content_object'] = get_serializable(bundle.obj.content_object) 
     return new_bundle 

    class Meta: 
     queryset = Page.objects.all() 


def get_serializable(model): 

    data = {'type': model.__class__.__name__} 
    for field in model._meta.fields: 
     data[field.name] = getattr(model, field.name) 
    return data 
0

Zdołaliśmy get URI obiektu zawartości, gdyby miał odpowiednią ModelResource:

class ContentTypeResource(ModelResource): 

    class Meta: 
     queryset = ContentType.objects.all() 
     resource_name = 'content_type' 
     allowed_methods = ['get',] 

class PageObjectResource(ModelResource): 

    content_object_uri = fields.CharField() 

    content_type = fields.ToOneField(
     ContentTypeResource, 
     attribute = 'content_type', 
     full=True) 

    class Meta: 
     queryset = models.PageObject.objects.all() 
     resource_name = 'page_object' 
     allowed_methods = ['get',] 

    def dehydrate_content_object_uri(self, bundle): 
     for resource in api._registry.values(): 
      if resource._meta.object_class == bundle.obj.content_object.__class__: 
       return resource.get_resource_uri(bundle.obj.content_object) 
     return '' 
2

Mamy pęknięty kod!

class ContentTypeResource(ModelResource): 

    class Meta: 
     queryset = ContentType.objects.all() 
     resource_name = 'content_type' 
     allowed_methods = ['get',] 

class PageObjectResource(ModelResource): 

    content_object = fields.CharField() 

    content_type = fields.ToOneField(
     ContentTypeResource, 
     attribute = 'content_type', 
     full=True) 

    class Meta: 
     queryset = models.PageObject.objects.all() 
     resource_name = 'page_object' 
     allowed_methods = ['get',] 

    def dehydrate_content_object(self, bundle): 
     for resource in api._registry.values(): 
      if resource._meta.object_class == bundle.obj.content_object.__class__: 
       return resource.full_dehydrate(resource.build_bundle(obj=bundle.obj.content_object, request=bundle.request)).data 
     return '' 

co skutkuje czymś takim:

"page_objects": [ 
{ 
"content_object": { 
"id": "186", 
"look_stills": [ 
{ 
"_image": "/static/media/uploads/looks/DSC_0903_PR_MEDIUM_QUALITY_RGB_FA.jpg", 
"aspect": "front", 
"id": "186", 
"look_still_icons": [ 
{ 
"colour_code": "58", 
"enabled": true, 
"id": "186", 
"in_stock_only": true, 
"look_product": { 
"colour_code": "58", 
"enabled": true, 
"id": "186", 
"resource_uri": "/api/look_product/186/", 
"style_code": "420215" 
}, 
"resource_uri": "/api/look_still_icon/186/", 
"x_coord": 76, 
"y_coord": 5 
} 
], 
"ordering": 1, 
"resource_uri": "/api/look_still/186/" 
} 
], 
"resource_uri": "/api/look_still_set/186/", 
"slug": "" 
}, 
"content_type": { 
"app_label": "looks_beta", 
"id": "97", 
"model": "lookstillset", 
"name": "look still set", 
"resource_uri": "/api/content_type/97/" 
}, 
"id": "2", 
"object_id": 186, 
"resource_uri": "/api/page_object/2/" 
} 
], 
"page_order": 3, 
"page_template": "look_still", 
"resource_uri": "/api/page/2/", 
"slug": "", 
"spread_number": 2, 
"title": "" 
}, 
0

one w rzeczywistości dodano wsparcie dla tego jak sugeruje Mario. Ponieważ trwało to wiecznie, aby dowiedzieć się, myślałem, że może to pomóc niektórym osobom. Oto przykład przy użyciu modeli komentarz wbudowane w Django, gdzie mogę dostać odwrotną relację do uwag komentowanym obiektu:

Dodaj do tego modelu, że komentarze przywiązywać do:

class CmntedObject(models.Model): 
    comments = generic.GenericRelation(Comment, 
          content_type_field='content_type', 
          object_id_field='object_pk') 

i zasobów wygląda tak:

class UserResource(ModelResource): 
    what ever you need here.... 

class CmntedObjectResource(ModelResource): 
    comments = fields.ToManyField('path.to.api.CmntedObjectResource', 'comments', full=True, null=True) 
    class Meta: 
     queryset = CmntedObject.objects.all() 
     resource_name = 'cmntedobject' 
     allowed_methods = ['get', 'post', 'delete'] 
     authorization = DjangoAuthorization() 

class CommentResource(ModelResource): 
    user = fields.ToOneField('path.to.api.UserResource', 'user', full=True) 
    content_type_id = fields.CharField(attribute = 'content_type_id') 
    site_id = fields.CharField(attribute = 'site_id') 
    content_object = GenericForeignKeyField({ 
         CmntedObject: CmntedObjectResource, #shown above 
         OtherCmntedObject: OtherCmntedObjectResource, #optional 
        }, 'content_object', null=True) 

    class Meta: 
     queryset = Comment.objects.all() 
     resource_name = 'cmnt' 
     allowed_methods = ['get', 'post', 'delete'] 
     authorization = DjangoAuthorization() 

    def obj_create(self, bundle, **kwargs): 
     #here we get the current authenticated user as the comment user. 
     bundle = super(CmntResource, self).obj_create(bundle, user=bundle.request.user) 
     return bundle