μλ νμΈμ, μμ μ λ°λΌ 리μμ€μ λν΄ λ€λ₯Έ νλλ₯Ό νμν μ μμ΅λκΉ?
λ΄κ° μνλ μ΄μ λ 리μμ€μ ν¬ν¨λ λͺ¨λ has_many νλλ‘ μΈλ±μ€ μμ μ λΆλ΄μ νΌνκΈ° μν¨μ λλ€.
μλ₯Ό λ€μ΄ μ μ μμΈ λ³΄κΈ°μμλ κ·Έμ μ΄λ¦λ§ λ°ννκ³ μΆμ§λ§ νμ μμ μ κ²½μ° λͺ¨λ μ± λ¦¬μμ€λ₯Ό ν¬ν¨νκ³ μΆμ΅λλ€.
κ°μ¬ ν΄μ,
보μ
+1
λλ μ΄ κΈ°λ₯μ κ°μ ν λ°λΌκ³ μλ€: "detail field"μ "list field"λ λΆλ¦¬λ μ μλ€
+1(#44μμ 볡μ λ₯Ό ν΅ν΄)
μΈλ±μ€ μμ μμ λ°μ΄ν°μ νμ μ§ν©μ λ μ½κ² κ°μ Έμ¬ μ μλ λ κ°μ§κ° μλ κ² κ°μ΅λλ€.
λ©ν:
index_exclude_fields = ['some_m2m_field']
μ΄λ κ² νλ©΄ μΌλΆ db 쿼리λ₯Ό μ μ₯ν μ μμ΅λλ€.
λλ 1. μΊμ±μ μν₯μ λ―ΈμΉ κ²μ΄λΌκ³ νκ°νμ§ μμμ΅λλ€.
μ΄λ»κ² μκ°νλμ?
λν #48μμ μμμ§λ§ κ° λ¬Έμ μλ κ°μΉ μλ μΈ‘λ©΄μ΄ μμ΅λλ€.
κ°λ₯νλ©΄ μ΄ κΈ°λ₯μ ν΄μ νκ³ μΆμμ§λ§ μ΄λ ₯μ΄ λΆμ‘±νμ΅λλ€. μ΄μ¨λ λ λμ νμΌ μ§μμ μν΄ κ±°κΈ°μ μμ΄μΌ νλ―λ‘ ν΄κ²°ν΄μΌ ν©λλ€. μ΄μ λν΄ 1.0μ λμμΌλ‘ ν©λλ€.
μ΄μ λν λ΄ μ¬μ© μ¬λ‘λ₯Ό μ‘°κΈ λ μ‘°μ¬ν ν 보기/λͺ©λ‘ λ³΄κΈ°λ³΄λ€ λ μ μ°ν κ²μΌλ‘ ꡬννλλ‘ μ μνκ³ μΆμ΅λλ€. λ΄κ° μ λ§λ‘ ν μ μμ΄μΌ νλ κ²μ λ€μκ³Ό κ°μ 쿼리μ€νΈλ§ νλκ·Έλ₯Ό μ·¨νλ κ²μ λλ€.
&shape=[μ 체|λ¨μ|μμ]
μΆλ ₯μ΄ μ¬μ©μκ° μ νν μΈλΆ μμ€μ λ°μνλλ‘ ν©λλ€. μ΄λ₯Ό ν΄νΉν λ°©λ²μ μ°Ύμμ§λ§ ModelResource ν΄λμ€κ° μμ±λ λ νλκ° ν¬ν¨/μ μΈλκΈ° λλ¬Έμ λμ€μ μλ΅ μ£ΌκΈ°μμ μ¬μ©ν μ μλ κ²μ λ³κ²½ν μ μλ λ°©λ²μ μ°Ύμ§ λͺ»νμ΅λλ€. λμ±μ΄ μ΄λ¬ν κ²°μ μ λ΄λ¦¬κ³ μ νλ νλ‘μΈμ€μ λ¨κ³μμ μμ² κ°μ²΄λ₯Ό μ¬μ©ν μ μμ΅λλ€.
+1
μ΄ λ¬Έμ μ κ΄λ ¨μ΄ μλ κ² κ°κΈ° λλ¬Έμ μ¬κΈ°μμ λ¨Όμ μ΄ μκ°μ μΈκΈνκ² μ΅λλ€. κ·Έλ¬λ μ체μ μΌλ‘ λΆλ¦¬ν΄μΌ ν μλ μμ΅λλ€.
λ€λ₯Έ νλλ₯Ό νμνλ λ©μ»€λμ¦μ΄ κ°λ°λλ©΄ μΈμ¦κ³Όλ ν΅ν©λ μ μλ€λ©΄ μ μ©ν κ²μ λλ€. λ λ§κ±°λ μ μ νλλ₯Ό λ ΈμΆν μ μλ€λ κ²μ μ¬μ©μμ κΆνμ λ°λΌ λ§€μ° κ°λ ₯ν κ²μ λλ€. μ΄κ²μ΄ μ΄λ―Έ κ°λ₯νλ€λ©΄ κ·Έμ λν μΈκΈμ μ°Ύμ μ μμ΅λλ€.
+1
+1
+1
+1
+1
+1
+1
λͺ©λ‘/μΈλΆ μ 보 μΈμλ λ©μλ(POST, PUT, GET)λ³λ‘ νμλλ νλ(νλ λλ μ μΈ μ¬μ©)λ₯Ό μ μ΄ν μ μκΈ°λ₯Ό κΈ°λν©λλ€.
ν΄κ²° λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€. μλ μλ₯Ό μ°Έμ‘°νμΈμ. μλ³Έ λͺ¨λΈμ 리μμ€ λͺ¨λΈ(μμ μμλ UserResource)μμ μ무 κ²λ μ μΈνμ§ μμΌλ―λ‘ μΈλ±μ€ 보기μμ κ°λ μ°¨κ² λ©λλ€. νμ λͺ¨λΈμ ν¬ν¨νλ modelresourceμ νμ λ°©λ²(BlogPostResourceμλ μμ±μκ° ν¬ν¨λ¨)μΌλ‘ μ΄λνκ³ λ²λ€μ μμλ§ μμ ν΄μΌ ν©λλ€.
μμ:
class BlogPostResource(ModelResource):
author = fields.ForeignKey(UserResource, 'author', full=True)
....
class Meta:
...
def dehydrate(self, bundle):
del bundle.data['author'].data['field_you_dont_wanna_show_here']
del bundle.data['author'].data['field_you_dont_wanna_show_here']
return bundle
λ°λΌμ μ¬μ©μλ₯Ό λμ΄νλ €λ κ²½μ° μ¬μ ν λͺ¨λ νλλ₯Ό κ°μ Έμ€μ§λ§ λΈλ‘κ·Έ κ²μλ¬Όμ λμ΄ν λ μλ₯Ό λ€μ΄ μμ±μμ μ΄λ¦κ³Ό μ±μ κ°μ Έμ¬ μ μμ΅λλ€.
μ΄λ»κ² μκ°νλμ?
λ§€μ° λλ¬μ΄ ν΄κ²° λ°©λ²μ μ: list_viewμ νλ‘μ νΈ νλλ₯Ό νμνμ§ μμ§λ§ 리μμ€ μ체μ μ‘μΈμ€ν νμ μμ΄ detail_viewμμλ νμλ©λλ€. νλμ½λ© μμ΄ URL μ체λ₯Ό κ°μ Έμ€λ κ²μ κ°λ₯ν΄μΌ νμ§λ§ νμΈν μκ°μ΄ μμμ΅λλ€. :
class CompanyResource(ModelResource):
"""
Tastypie resource for Company
"""
projects = fields.ToManyField('api.resources.ProjectResource',
'projects',full=True)
class Meta:
queryset = Company.objects.all()
resource_name = 'companies'
def dehydrate(self, bundle):
if bundle.request.path == "/api/v1/companies/":
del bundle.data['projects']
return bundle
+1
+1
+1
λλ λν κΈ°μ°¨λ₯Ό νλ©΄ μ’κ² μ§ λ§
def dehydrate(self, bundle):
if self.get_resource_uri(bundle) == bundle.request.path:
print "Detail"
if self.get_resource_uri(bundle) != bundle.request.path:
print "Not Detail - Could be list or reverse relationship."
return bundle
κ·Έλμ λλ μ΄κ²μ λν΄ μ’ λ μκ°νκ³ @bmihelac μ΄ μ°Ύκ³ μλ€κ³ μκ°νλ μΌμ ν μ μλλ‘ νλ λ° κ±°μ κ·Όμ ν 무μΈκ°λ₯Ό μκ°ν΄
μ 곡λ @ashwoods μμ λ₯Ό μ¬μ©νμ¬ μΈλΆ μλ΅μΈ κ²½μ°μλ§ νλ‘μ νΈ νλλ₯Ό νμνλ €κ³ νλ€κ³ κ°μ ν©λλ€.
class CompanyResource(ModelResource):
"""
Tastypie resource for Company
"""
class Meta:
queryset = Company.objects.all()
resource_name = 'companies'
additional_detail_fields = {'projects': fields.ToManyField('api.resources.ProjectResource', 'projects',full=True)}
def dehydrate(self, bundle):
# detect if detail
if self.get_resource_uri(bundle) == bundle.request.path:
# detail detected, include additional fields
bundle = self.detail_dehydrate(bundle)
return bundle
# detail_dehydrate is basically full_dehydrate
# except we'll loop over the additional_detail_fields
# and we won't want to do the dehydrate(bundle) at the end
def detail_dehydrate(self, bundle):
"""
Given a bundle with an object instance, extract the information from it
to populate the resource.
"""
# Dehydrate each field.
# loop over additional_detail_fields instead
#for field_name, field_object in self.fields.items():
for field_name, field_object in self._meta.additional_detail_fields.items():
# A touch leaky but it makes URI resolution work.
if getattr(field_object, 'dehydrated_type', None) == 'related':
field_object.api_name = self._meta.api_name
field_object.resource_name = self._meta.resource_name
bundle.data[field_name] = field_object.dehydrate(bundle)
# Check for an optional method to do further dehydration.
method = getattr(self, "dehydrate_%s" % field_name, None)
if method:
bundle.data[field_name] = method(bundle)
# dehydrating the bundle will create an infinite loop
#bundle = self.dehydrate(bundle)
return bundle
+1, μ§κΈμ @dericcragoμ μμ μ¬νμ μ¬μ©ν©λλ€.
+1
+1
# 526μ λΆλΆ ꡬν, λͺ¨λ κ²μ΄ ν맀λκ³ μλμ§ νμ€νμ§ μμΌλ©° ν μ€νΈ/λ¬Έμκ° λΆμ‘±ν©λλ€.
λ°©κΈ μ΄ ν°μΌμ 보μκ³ ... λν μμ onyxfishκ° μΈκΈν 'λͺ¨μ' μ κ·Ό λ°©μκ³Ό μ μ¬ν©λλ€.
μ¬λλ€μ΄ λ€λ₯Έ κ²½μ°μ λ€λ₯Έ 'λͺ¨μ'μ μν κ²½μ°λ₯Ό λλΉνμ¬ #526μ μ루μ μ΄ μ½κ° μ νμ μ΄λΌκ³ μκ°νμ΅λλ€...
νμ ν νλλ₯Ό μ κ±°νλΌλ μ μμ ... λ΄ λͺ¨λ μ΄μ λ μ²μμ κ°μ κ³μ°νμ§ μλ κ²μ λλ€.
κ·Έλ¬λ 쑰건λΆλ‘ λ λ§μ μΈλΆ μ 보λ₯Ό μΆκ°ν μ μλλ‘ νλ detail_dehydrate νν¬μ λν μμ΄λμ΄κ° λ§μμ λλλ€.
ν
μ€νΈμ λ¬Έμλ₯Ό ν¬ν¨νμ¬ λ κ°μ§ κ°λ₯ν ꡬνμ΄ κ°λ₯ν κ² κ°μ΅λλ€. #569μ νλλ₯Ό μμ±νκ³ #538λ μ μ¬ν κΈ°λ₯μ μνν©λλ€(#538μ use_in
κ° νΈμΆ κ°λ₯νλ―λ‘ μ’ λ μ μ°νκ² νμ©ν©λλ€). λ΄ κ΅¬νμ μ΄ κΈ°λ₯μ μ μ΄νκΈ° μν΄ meta
μμ±μ μΆκ°νλ λ°λ©΄(νμ¬ fields
μμ±κ³Ό μΌμΉν¨) #538μ νλμ μμ±μ μΆκ°ν©λλ€. λ λ€ μ ν¨ν κ²μΌλ‘ 보μ΄λ©° μ΄λ€ λ°©ν₯μΌλ‘ κ° κ²μΈμ§μ λν μ€κ³ κ²°μ μΌ λΏμ
λλ€. μΌλΆ νλλ μλμΌλ‘ μμ±λ μ μκ³ μ΄κΈ°ν 맀κ°λ³μλ₯Ό μμ νλ κ²μ΄ λΆκ°λ₯ν μ μλ€λ μ μ κ°μν λ λ©νμ μΆκ°νλ κ²μ΄ μΌκ΄μ± μλ κ²μΌλ‘ 보μ΄λ©° μ¬μ©νκΈ° λ μ½μ΅λλ€. λ λ€λ₯Έ λμμ λ pull μμ²μ κ²°ν©νκ³ meta
μμ±μ κΈ°λ°μΌλ‘ use_in
맀κ°λ³μκ° μλμΌλ‘ μ€μ λλλ‘ νμ©νλ κ²μ΄μ§λ§, μ΄λ APIμ νμν κ²λ³΄λ€ λ 볡μ‘ν¨μ μΆκ°νλ κ²μΌλ‘ 보μ
λλ€. κ΄λ ¨ pull μμ²μ μ§μ ν΄ μ£Όμ @issackelly μκ² κ°μ¬λ립λλ€.
[#538μ μλ μμΈμ λ΄ #526μ μ 리νλ κ²μ΄λ―λ‘ μ리λ₯Ό μ§λ₯΄μμμ€.]
λ§μ μλ―Έκ° μμ΅λλ€ ... Meta μ κ·Ό λ°©μμ μ€μ λ‘ ModelResource λ±μ λν μ μΈ λͺ©λ‘μ μ¬μ©νμ¬ μ €λ¦¬λ₯Ό λ§λ€ κ²μ
λλ€ ...
λ€λ₯Έ ν°μΌμμ λ§νλ―μ΄, μ΄μ κ°μ "λ¨μν" μ루μ μ IMHO, 1.0 릴리μ€μ μΆ©λΆν©λλ€... "ν΄λΌμ΄μΈνΈ μ ν κ°λ₯ν 'λͺ¨μ'"κ³Ό κ°μ λ 볡μ‘ν μ루μ μ μ΄ν 릴리μ€μ λ°λμ§ν μ μμ΅λλ€. .
@funkybob νμ€ν λ 볡μ‘ν μ루μ μ΄ ν΄λΌμ΄μΈνΈ μΈ‘μμ λμμ΄ λ κ²μ΄λΌλ λ° λμνμ§λ§ 1.0μ΄ λ¦΄λ¦¬μ€λκΈ° μ μ μ¬μ©ν μ μλλ‘ μ΄ κΈ°λ₯μ μ΅λν 빨리 ν¬ν¨νλ κ²μ΄ μ’μ΅λλ€.
μ€μ λ‘ νλ‘λμ μ ν리μΌμ΄μ μμ PRμ μ¬μ©νλ©΄μ #538μμ μ 곡νλ μ½λ°±μ μ μ°μ±μ΄ μ λ§ λ§μμ λλλ€. κΆνμ λ°λΌ λ°νμμ 리μμ€λ₯Ό μ¨κ²¨μΌ νλ λͺ κ°μ§ μ¬μ© μ¬λ‘κ° μμ΅λλ€.
μ΄κ²μ # 569λ₯Ό μ¬μ©νμ¬ λΆκ°λ₯ν κ²μ λλ€.
μλ νμΈμ, μ΄λ€ μμμ΄ μμ΅λκΉ? κ·Έ PRμ μΆμ ν¨μ¬ λ μ½κ² λ§λλλ€. κ°μ¬ν©λλ€!
@dericcragoμμ μ 곡νλ ν΄νΉμΌλ‘ μ§ν
+1
λ΄κ° μ¬μ©νλ κ°λ¨ν ν΄κ²° λ°©λ²μ μ΄λ¬ν νλλ₯Ό νΈμ§νκΈ° μν΄ get_detail
& get_list
λ©μλλ₯Ό μ¬μ μνλ κ²μ
λλ€.
μ΄λ κ² νλ©΄ μ€μ λ‘ νλμ λν λ°μ΄ν°λ₯Ό κ°μ Έμ¨ λ€μ λ²λ€μμ μμ νλ μ€λ²ν€λκ° μ μ½λμ§λ§ μ΄ λ©μλκ° μ€λ λλ‘λΆν° μμ νμ§λ νμ€νμ§ μμ΅λλ€. 리μμ€ κ°μ²΄κ° λͺ¨λ API νΈμΆμμ μμ±λμ§ μλ κ²μ²λΌ 보μ΄κΈ° λλ¬Έμ
λλ€.
λκ΅°κ°κ° μ΄κ²μ λν΄ λ
Όνν μ μλ€λ©΄ μ’μ κ²μ
λλ€.
μ½λλ λ€μκ³Ό κ°μ΅λλ€.
class ArticleResource(BaseModelResource):
owner = fields.ToOneField(UserResource, 'owner', full=True)
class Meta:
resource_name = "articles"
def get_list(self, request, **kwargs):
self.fields.pop("comments", None)
return super(ArticleResource, self).get_list(request, **kwargs)
def get_detail(self, request, **kwargs):
self.fields["comments"] = fields.ToManyField(CommentResource, 'comments', full=True)
return super(ArticleResource, self).get_detail(request, **kwargs)
+1
λ λ€λ₯Έ ν΄κ²° λ°©λ²μ μΈλΆ μ 보 λ° λͺ©λ‘ 보기μ λν΄ λ€λ₯Έ 리μμ€λ₯Ό μ¬μ©νλ κ²μ λλ€.
from tastypie.resources import ModelResource
from django.contrib.auth.models import User
# detail will show everything except password
class UserResourceDetail(ModelResource):
class Meta:
queryset = User.objects.all()
excludes = ('password',)
resource_name = 'user'
# list will only show username & date_joined (and exclude password)
class UserResource(UserResourceDetail):
class Meta(UserResourceDetail.Meta):
fields = ('username', 'date_joined')
get_detail = UserResourceDetail().get_detail
# ... register & use UserResource
+1
@dnozay ν΄κ²° λ°©λ²μ λν΄ +1
+1 @dnozay , κ΅μ₯ν΄
get_resource_uri
κ° μ¬μ©μ μΈλΆ μ 보 보기μμ μ¬λ°λ₯΄κ² μλνλλ‘ νλ €λ©΄ UserResource
κ° μ μλ νμ λ€μμ μΆκ°ν΄μΌ ν©λλ€.
UserResourceDetail.get_resource_uri = UserResource().get_resource_uri
κ·Έλ μ§ μμΌλ©΄ resource_uri
λ λͺ¨λ μΈλΆ μλ΅μμ λΉμ΄ μμ΅λλ€.
κ΄λ ¨ κ°λ₯μ±: #1265
κ°μ₯ μ μ©ν λκΈ
λ΄κ° μ¬μ©νλ κ°λ¨ν ν΄κ²° λ°©λ²μ μ΄λ¬ν νλλ₯Ό νΈμ§νκΈ° μν΄
get_detail
&get_list
λ©μλλ₯Ό μ¬μ μνλ κ²μ λλ€.μ΄λ κ² νλ©΄ μ€μ λ‘ νλμ λν λ°μ΄ν°λ₯Ό κ°μ Έμ¨ λ€μ λ²λ€μμ μμ νλ μ€λ²ν€λκ° μ μ½λμ§λ§ μ΄ λ©μλκ° μ€λ λλ‘λΆν° μμ νμ§λ νμ€νμ§ μμ΅λλ€. 리μμ€ κ°μ²΄κ° λͺ¨λ API νΈμΆμμ μμ±λμ§ μλ κ²μ²λΌ 보μ΄κΈ° λλ¬Έμ λλ€.
λκ΅°κ°κ° μ΄κ²μ λν΄ λ Όνν μ μλ€λ©΄ μ’μ κ²μ λλ€.
μ½λλ λ€μκ³Ό κ°μ΅λλ€.