Django-rest-framework: ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๊ฐ€ ๋ณด๊ธฐ ์ปจํ…์ŠคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2015๋…„ 02์›” 13์ผ  ยท  26์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: encode/django-rest-framework

_stackoverflow ์งˆ๋ฌธ IMO๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์‹ค๋ก€ํ•ฉ๋‹ˆ๋‹ค_

์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ v2 ๋ถ„๊ธฐ์—์„œ ๋„ˆ๋ฌด ๋งŽ์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋…ผ์˜ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ ํ•„๋“œ์—์„œ ์„ ํƒํ•œ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

QUERY_PARAMS ์— ์ œ๊ณต๋œ ํ”„๋กœ์ ํŠธ ID ๋ฐ v3-branch์—์„œ ์ง€๊ธˆ์ฒ˜๋Ÿผ perform_create ์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ €์žฅํ•˜๊ธฐ ์ „์— ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ ํ•„๋“œ์— ํ”„๋กœ์ ํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ฒด์— ๋Œ€ํ•œ ๊ธฐ๋ณธ๊ฐ’์„ ์ œ๊ณตํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž๋Š” ํ”„๋กœ์ ํŠธ ๊ฐœ์ฒด์—์„œ ์„ ํƒ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ $#$3$# context ์— get_serializer_context ๋ฅผ ํ”„๋กœ์ ํŠธ ๊ฐœ์ฒด๋กœ ์ฑ„์›๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•˜๋ ค๋ฉด ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์—์„œ __init__ ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๊ฐ€ __init__ context ๋˜๋Š” parent ๋ฅผ ์ˆ˜์‹ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ๋ฅผ ์ „ํ˜€ ์ˆ˜์‹ ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค! ๋”ฐ๋ผ์„œ pull-request 497 ์ดํ›„ ํšŒ๊ท€์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ์ƒ๊ฐ์—๋Š” ํšŒ๊ท€๊ฐ€ ์•„๋‹ˆ๋ผ ๋””์ž์ธ ๋ณ€๊ฒฝ๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ serizliser ๋™์ž‘์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์œผ๋ ค๋ฉด ์ปจํ…์ŠคํŠธ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค!

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

ํ•œ ๊ฐ€์ง€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ํ•„๋“œ ์„ ์–ธ ๋Œ€์‹  ParentSerializer ์˜ __init__ ๋ฉ”์„œ๋“œ์—์„œ ํ•ญ์ƒ ์ค‘์ฒฉ๋œ ChildSerializer ์„ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ปจํ…์ŠคํŠธ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์™€ ๊ฐ™์ด:

class ChildSerializer(serializers.Serializer):
    ...

class ParentSerializer(serializers.Serializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['child'] = ChildSerializer(context=self.context)

์ดˆ๊ธฐ ํ…Œ์ŠคํŠธ์—์„œ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์— ์–ด๋–ค ์บ์น˜๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  26 ๋Œ“๊ธ€

์ปจํ…์ŠคํŠธ๋Š” ๋ถ€๋ชจ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์—์„œ ์„ ์–ธ๋  ๋•Œ ์ดˆ๊ธฐํ™”๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ดˆ๊ธฐํ™” ์‹œ์ ์—์„œ ํ•„๋“œ(๋˜๋Š” ์ค‘์ฒฉ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ)๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์ „๋‹ฌ๋  ์ˆ˜ ์—†์Œ)...

class MySerializer(Serializer):
    child = ChildSerializer()  <--- We've just initialized this.

๊ฐ€์žฅ ์ข‹์€ ๊ฒƒ์€ MySerializer.__init__ ์—์„œ ์ด์™€ ๊ฐ™์€ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด...

def __init__(self, *args, **kwargs):
    super(MySerializer, self).__init__(*args, **kwargs)
    self.fields['child'].default = ...

๊ทธ ์‹œ์ ์—์„œ ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค ๊ถŒํ•œ์ด _do_ ์žˆ์Šต๋‹ˆ๋‹ค.

์ •๋ง๋กœ ์›ํ•œ๋‹ค๋ฉด ํ•„๋“œ๊ฐ€ ๋ถ€๋ชจ์— ๋ฐ”์ธ๋”ฉ๋˜๋Š” ์ง€์ ์—์„œ ๋ช‡ ๊ฐ€์ง€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class ChildSerializer(Serializer):
    def bind(self, *args, **kwargs):
        super(ChildSerializer, self).bind(*args, **kwargs)
        # do stuff with self.context.

์ด๊ฒƒ์€ ๋น„๊ณต๊ฐœ API๋กœ ๊ฐ„์ฃผ๋˜์–ด์•ผ ํ•˜๋ฉฐ ์œ„์— ๋‚˜์—ด๋œ ์ƒ์œ„ __init__ ์Šคํƒ€์ผ์ด ์„ ํ˜ธ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ, ๋‹น์‹ ์ด ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ์ธ์ง€ ์กฐ๊ธˆ ๊นŒ๋‹ค๋กญ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋‚ด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๋ถ€๋ชจ์˜ __ini__ ์— ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ __init__ ๋Š” deepcopy๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒˆ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜์ง€๋งŒ ์ƒ์œ„ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ชฐ๋ž˜ ๋“ค์–ด๊ฐˆ ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค...
๊ทธ๋ž˜์„œ v2์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ํ•„๋“œ์—๋Š” ๋ถ€๋ชจ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ธฐ๋ณธ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ์— ์™„๋ฒฝํ•œ initialize ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ bind ๊ฐ€ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋น„๊ณต๊ฐœ API๋กœ ๊ฐ„์ฃผ๋˜์–ด์•ผ ํ•˜๋ฉฐ ์œ„์— ๋‚˜์—ด๋œ ์ƒ์œ„ __init__ ์Šคํƒ€์ผ์ด ์„ ํ˜ธ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ __init__ ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์—†๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ ๋ณด๊ธฐ์—์„œ ์ƒ์„ฑ๋œ ๋ชจ๋“  ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ™˜๊ฒฝ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ๋ชจ๋“  ๊ฒƒ์ด ์žˆ์„ ๋•Œ ํ•„๋“œ(serializer)์—์„œ ํ˜ธ์ถœ๋˜๋Š” ๊ณต๊ฐœ API ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ฐ€๋Šฅ. initialize ์ฒ˜๋Ÿผ.

DRF 2์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ?

์œ ๊ฐ์Šค๋Ÿฝ๊ฒŒ๋„ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋” ์ด์ƒ ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋กœ ์ „ํŒŒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์œ ๊ฐ์Šค๋Ÿฝ๊ฒŒ๋„ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋” ์ด์ƒ ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋กœ ์ „ํŒŒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋„ˆ ๊ทธ๊ฑฐ ์–ด๋””์„œ ์–ป์—ˆ ๋‹ˆ ? Afaik, ์ปจํ…์ŠคํŠธ๊ฐ€ ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋กœ ์ „ํŒŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

@xordoquy ์ด์ƒํ•ฉ๋‹ˆ๋‹ค. ์ตœ์‹  drf์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ๋งŒ๋“ค์—ˆ๊ณ  ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋”๊ตฌ๋‚˜ ๋‚ด ์ž์‹ ์˜ ์ฝ”๋“œ์— ๋Œ€ํ•ด ์žฌํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ ํ•ด๊ฒฐ๋จ.

@xiaohanyu ์‹ค์ œ๋กœ ๋‹ค์‹œ ํ•œ ๋ฒˆ์ด ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ข€ ์ด์ƒํ•ฉ๋‹ˆ๋‹ค.

>>> serializer
Out[12]: 
# Note there is context passed in constructor
CouponSerializer(<Coupon: Coupon Coupon #0 for offer Offer #0000>, context={'publisher': <User: John ZusPJRryIzYZ>}):
    id = IntegerField(label='ID', read_only=True)
    title = CharField(max_length=100, required=True)
    short_title = CharField(max_length=30)
    offer_details = OfferLimitedSerializer(read_only=True, source='offer'):
        id = IntegerField(label='ID', read_only=True)
        title = CharField(help_text='The Offer Title will be used for the Network, Advertisers and Publishers to identify the specific offer within the application.', read_only=True)       
        status_name = CharField(read_only=True, source='get_status_display')
        is_access_limited = SerializerMethodField()    
    exclusive = BooleanField(required=False)    
    categories_details = OfferCategorySerializer(many=True, read_only=True, source='categories'):
        id = IntegerField(read_only=True)
        category = CharField(read_only=True, source='code')
        category_name = CharField(read_only=True, source='get_code_display')    

# all fields except one got context propagated
>>> [f.field_name for f in serializer.fields.values() if not f.context]
Out[20]: 
['offer_details']

# offer_details is no different than categories_details, both are nested, read only, model serializers..
>>> serializer.fields['categories_details'].context
Out[21]: 
{'publisher': <User: John ZusPJRryIzYZ>}

# lets look inside problematic serializer
>>> offer_details = serializer.fields['offer_details']
>>> offer_details
Out[25]: 

OfferLimitedSerializer(read_only=True, source='offer'):
    id = IntegerField(label='ID', read_only=True)
    title = CharField(help_text='The Offer Title will be used for the Network, Advertisers and Publishers to identify the specific offer within the application.', read_only=True)    
    status_name = CharField(read_only=True, source='get_status_display')
    url = SerializerMethodField()
    is_access_limited = SerializerMethodField()
>>> offer_details.context
Out[23]: 
{}
>>> offer_details._context
Out[24]: 
{}
# ! surprisingly context is available inside fields... but not in the parent
>>> offer_details.fields['is_access_limited'].context
Out[26]: 
{'publisher': <User: John ZusPJRryIzYZ>}

# context is available in all of them!
>>> [x.field_name for x in offer_details.fields.values() if not x.context]
Out[27]: 
[]

@tomchristie ๊ท€์ฐฎ๊ฒŒ ํ•ด์„œ ๋ฏธ์•ˆํ•˜์ง€๋งŒ, ๊ทธ๊ฒŒ ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•œ์ง€ ์•Œ ์ˆ˜ ์žˆ์„๊นŒ์š”?

๊ทธ๋™์•ˆ ๋‚˜๋Š” ์ด ํ•ดํ‚น์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

class Serializer(serializers.Serializer):

    def __init__(self, *args, **kwargs):
        super(Serializer, self).__init__(*args, **kwargs)
        # propagate context to nested complex serializers
        if self.context:
            for field in six.itervalues(self.fields):
                if not field.context:
                    delattr(field, 'context')
                    setattr(field, '_context', self.context)

@pySilver ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์—†์ด๋Š” ํฐ ๋„์›€์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ ์ „ํŒŒ๋ฅผ ์ค‘๋‹จํ•˜๋Š” ์ผ๋ถ€ ์‚ฌ์šฉ์ž ์ •์˜ ์ฝ”๋“œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋Š” ์—ฌ๋Ÿฌ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ํด๋ž˜์Šค๊ฐ€ serializers.Serializer์˜ ์ž์‹์ธ ๋ณต์žกํ•œ mro ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๊ฒƒ

class MyMixin(serializers.Serializer):
   # some code within __init__, calling parent too

class MyModelSerializer(serializers.ModelSerializer):
   # some code within __init__, calling parent too

class MyProblematicSerializer(MyModelSerializer, MyMixin)
    # this one will not receive context somehow.
     pass

์–ด์จŒ๋“  ์ง€์—ญ ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”ผ๋“œ๋ฐฑ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿ‘

@xordoquy @tomchristie ์‹ค์ œ๋กœ ๋ฌธ์ œ๊ฐ€ ์ •๋ง ์ด์ƒํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์šด์ด ์—†์ด fields ์†์„ฑ์—์„œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์ž…๋‹ˆ๋‹ค.

def test_serializer_context(self):
        class MyBaseSerializer(serializers.Serializer):
            def __init__(self, *args, **kwargs):
                super(MyBaseSerializer, self).__init__(*args, **kwargs)
                x = 0
                if self.context.get('x'):
                    x = self.context['x']

        class SubSerializer(MyBaseSerializer):
            char = serializers.CharField()
            integer = serializers.IntegerField()

        class ParentSerializer(MyBaseSerializer):
            with_context = serializers.CharField()
            without_context = SubSerializer()

        serializer = ParentSerializer(data={}, context={'what': 42})
        assert serializer.context == {'what': 42}
        assert serializer.fields['with_context'].context == {'what': 42}
        assert serializer.fields['without_context'].context == {'what': 42}

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ํ†ต๊ณผํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. imho ์žฌ์ •์˜๋œ ๋ฉ”์„œ๋“œ์—์„œ ์ปจํ…์ŠคํŠธ์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์†Œ์Šค์—์„œ ์–ธ๊ธ‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค...

def test_serializer_context(self):
        class MyBaseSerializer(serializers.Serializer):
            <strong i="12">@property</strong>
            def fields(self):
                fields = super(MyBaseSerializer, self).fields
                x = 0
                if self.root.context.get('x'):
                    x = 1
                return fields


        class SubSerializer(MyBaseSerializer):
            char = serializers.CharField()
            integer = serializers.IntegerField()

        class ParentSerializer(MyBaseSerializer):
            with_context = serializers.CharField()
            without_context = SubSerializer()

        serializer = ParentSerializer(data={}, context={'what': 42})
        assert serializer.context == {'what': 42}
        assert serializer.fields['with_context'].context == {'what': 42}
        assert serializer.fields['without_context'].context == {'what': 42}

๋ช…ํ™•ํžˆ ํ•˜์ž๋ฉด, ์—ฌ๊ธฐ์„œ ๋‚ด๊ฐ€ ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์€ ์ปจํ…์ŠคํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•„๋“œ์˜ ๋™์ž‘์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

UPD: ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๋งˆ์ง€๋ง‰ ์ฝ”๋“œ๋„ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋งŒ์ง€๋Š” ์ปจํ…์ŠคํŠธ๊ฐ€ ์œ„ํ—˜ํ•˜๋‹ค๋Š” ๊ฒƒ์ด ๋ฐํ˜€์กŒ์Šต๋‹ˆ๋‹ค.

__init__ ์ปจํ…์ŠคํŠธ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์€ ๋ถˆํ–‰ํ•œ ์ผ์ž…๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ์˜ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์—์„œ ํ•„๋“œ๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์–ด๋””์—์„œ ์ˆ˜ํ–‰ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์œ„์—์„œ ์ œ์•ˆํ•œ ๋Œ€๋กœ bind ์—์„œ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด self.fields['asdf'] = serializers.CharField() . bind ๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ํ•„๋“œ๊ฐ€ ์ด๋ฏธ ํ‰๊ฐ€๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

fields ์†์„ฑ์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ํ•ญ๋ชฉ์ด ๋งŽ์ด ํ˜ธ์ถœ๋˜๊ณ  ์ง€์—ฐ ํ‰๊ฐ€๋กœ ์ธํ•ด self._fields ์— ์บ์‹ฑ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ์žˆ์œผ๋ฏ€๋กœ ๋ณต์ œํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ตฌ์ฒด์ ์ธ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์—์„œ. ๋‚ด๋ถ€์ ์œผ๋กœ ์บ์‹œ๋˜๊ธฐ ์ „์— ํ•„๋“œ๋ฅผ ํ•œ ๋ฒˆ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ง๋ ฌํ™”๊ธฐ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ํ•„๋“œ๋กœ ์ค‘์ฒฉ์„ ์ˆ˜ํ–‰ํ–ˆ๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด์™€ ๊ฐ™์ด:

class ChildSerializer(serializers.Serializer):
    ...

class ParentSerializer(serializers.Serializer):
    child = serializers.NestedField(serializer=ChildSerializer)

๊ทธ๋Ÿฌ๋ฉด ChildSerializer ParentSerializer ์˜ ํ•„๋“œ ์„ ์–ธ์—์„œ ์ง์ ‘ ์ธ์Šคํ„ด์Šคํ™”๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— __init__ ์˜ ์ปจํ…์ŠคํŠธ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปจํ…์ŠคํŠธ์˜ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์—์„œ ํ•„๋“œ๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์–ด๋””์—์„œ ์ˆ˜ํ–‰ํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

๊ตฌ์ฒด์ ์ธ ์˜ˆ์˜ ๋งฅ๋ฝ์—์„œ ์ด์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฉ‹์ง„ ๊ฐ„๋‹จํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ƒ๊ฐํ•ด ๋‚ด๊ณ  ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ง๋ ฌํ™”๊ธฐ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ํ•„๋“œ๋กœ ์ค‘์ฒฉ์„ ์ˆ˜ํ–‰ํ–ˆ๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์‹œ๋„ํ•ด๋ณด์‹ญ์‹œ์˜ค. ์šฐ๋ฆฌ๊ฐ€ ๊ทธ ๊ธธ์„ ๊ฐˆ ๊ฒƒ ๊ฐ™์ง€๋Š” ์•Š์ง€๋งŒ. ์ด๊ฒƒ์€ ํ˜„์žฌ ์šฐ๋ฆฌ๊ฐ€ ํ•˜๋Š” ์ผ์— ํฐ ๋ณ€ํ™”๋ฅผ ๊ฐ€์ ธ์™”์œผ๋ฉฐ, ๋˜ํ•œ ์ž์‹ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์— ์ธ์ˆ˜๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ์Šคํƒ€์ผ์— ํƒ€๋‹นํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์ด ์‹œ์ ์—์„œ ์šฐ๋ฆฌ๊ฐ€ ํŠน๋ณ„ํžˆ ๋ณ€ํ•˜๋Š” ๊ฒƒ์„ ๋ณด์ง€๋Š” ๋ชปํ•ฉ๋‹ˆ๋‹ค.

@tomchristie ๋‹ต๋ณ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์ง€๊ธˆ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ•œ ๊ฐ€์ง€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์˜ ์†์„ฑ์— ๋”ฐ๋ผ ์ค‘์ฒฉ๋œ ์ž์‹ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์—์„œ ๋‘ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ํ•„๋“œ ์ง‘ํ•ฉ ์‚ฌ์ด๋ฅผ ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

Type A ์‚ฌ์šฉ์ž๋Š” Type B ์‚ฌ์šฉ์ž์™€ ๊ด€๋ จ๋œ ํ•„๋“œ๋ฅผ ์ ˆ๋Œ€ ๋ณผ ์ˆ˜ ์—†์œผ๋ฉฐ ๊ทธ ๋ฐ˜๋Œ€์˜ ๊ฒฝ์šฐ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ž…๋‹ˆ๋‹ค.

class ChildSerializer(serializers.Serializer):
  # relevant for all users
  name = serializers.CharField()

  # only relevant for users of Type A
  phone = serializers.CharField()

  # only relevant for users of Type B
  ssn = serializers.CharField()

๊ทธ๋Ÿฌ๋‚˜ ์ €๋Š” drf ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ ๋ฐ/๋˜๋Š” django ์–‘์‹์„ ์‚ฌ์šฉํ•˜์—ฌ api ๋ฐ html ์–‘์‹ ๋ชจ๋‘์—์„œ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ํ•„๋“œ๋ฅผ ์ •๊ธฐ์ ์œผ๋กœ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ๋™์ ์œผ๋กœ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , ํ•„๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ , ์†์„ฑ์„ ์ˆ˜์ •ํ•˜๋Š” ์œ„์˜ ์˜ˆ๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด์ „์— ์ค‘์ฒฉ๋œ ์ž์‹์—์„œ ๊ทธ๊ฒƒ์„ ํ•  ํ•„์š”๊ฐ€ ์—†์—ˆ๊ณ  ์ด๊ฒƒ์— ์™„์ „ํžˆ ๋‹นํ™ฉํ–ˆ์Šต๋‹ˆ๋‹ค.

@tomchristie ๋‚ด ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ์ปจํ…์ŠคํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•„๋“œ๊ฐ€ ํ•„์š”ํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹๊ฒƒ์ž…๋‹ˆ๋‹ค(์‚ฌ์šฉ์ž ๋ฐ ๊ด€๋ฆฌ์ž๋ฅผ ์œ„ํ•œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋ฅผ ์ƒ์ƒํ•ด ๋ณด์‹ญ์‹œ์˜ค. ์—ฌ๊ธฐ์„œ ์ปจํ…์ŠคํŠธ๋ฅผ ํ†ตํ•ด ์ „๋‹ฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž ID๋ฅผ ์ œ๊ณตํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.) ์ด ์Šค๋ ˆ๋“œ์˜ ์ด์ „ ๊ฒŒ์‹œ๋ฌผ์—์„œ ์†”๋ฃจ์…˜์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

ํ•œ ๊ฐ€์ง€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ํ•„๋“œ ์„ ์–ธ ๋Œ€์‹  ParentSerializer ์˜ __init__ ๋ฉ”์„œ๋“œ์—์„œ ํ•ญ์ƒ ์ค‘์ฒฉ๋œ ChildSerializer ์„ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ปจํ…์ŠคํŠธ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์™€ ๊ฐ™์ด:

class ChildSerializer(serializers.Serializer):
    ...

class ParentSerializer(serializers.Serializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['child'] = ChildSerializer(context=self.context)

์ดˆ๊ธฐ ํ…Œ์ŠคํŠธ์—์„œ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์— ์–ด๋–ค ์บ์น˜๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฐ™์€ ์ œ์•ˆ์„ ํ•˜๋ ค๊ณ  ํ–ˆ์–ด, ๋„ค.

๊ธ€์Ž„, ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์ €์—๊ฒŒ ํšจ๊ณผ๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๋‹ค์ค‘ ์ƒ์† ๋•Œ๋ฌธ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

2016๋…„ 10์›” 12์ผ ์ˆ˜์š”์ผ ์˜คํ›„ 2์‹œ 56๋ถ„ +0200์— "Tom Christie" [email protected] ์ด ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ™์€ ์ œ์•ˆ์„ ํ•˜๋ ค๊ณ  ํ–ˆ์–ด, ๋„ค.

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ๋ณด๊ฑฐ๋‚˜ ์Šค๋ ˆ๋“œ๋ฅผ ์Œ์†Œ๊ฑฐํ•˜์„ธ์š”.

default ์†์„ฑ(๋‚ด ๊ฒฝ์šฐ์—๋Š” CurrentUserDefault() ๊ฐ’ ํฌํ•จ)์„ ์ฒ˜๋ฆฌํ•˜๋Š” __init__ ๋ฉ”์„œ๋“œ๋ฅผ ์„œ๋ธŒํด๋ž˜์‹ฑํ•œ (์ค‘์ฒฉ) ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ ํ•„๋“œ๋กœ ์„ค์ •ํ•  ๋•Œ๋„ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. self.context ์†์„ฑ์—์„œ KeyError $๋Š” ์ปจํ…์ŠคํŠธ์—์„œ request ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค(์•„๋ฌด ๊ฒƒ๋„ ํฌํ•จํ•˜์ง€ ์•Š์Œ, ์ฆ‰ ์ƒ์œ„์—์„œ ์ „๋‹ฌ๋˜์ง€ ์•Š์Œ).
์˜ˆ์ œ ์ฝ”๋“œ:

class UserSerializer(serializers.ModelSerializer):
# ...
    def __init__(self, *args, **kwargs):
        kwargs.pop('fields', None)
        super().__init__(*args, **kwargs)
        if 'list' in self.context: # Once I remove this, it will work
            self.fields['friend_count'] = serializers.SerializerMethodField()
# ...

class CommentSerializer(serializers.ModelSerializer):
    person = UserSerializer(read_only=True, default=serializers.CurrentUserDefault())
# ...

์˜ค๋ฅ˜ ๊ธฐ๋ก:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/api/comments/98/

Django Version: 1.9.7
Python Version: 3.4.3
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.sites',
 'rest_framework',
 'rest_framework.authtoken',
 'generic_relations',
 'decorator_include',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'allauth.socialaccount.providers.facebook',
 'allauth.socialaccount.providers.google',
 'phonenumber_field',
 'bootstrap3',
 'stronghold',
 'captcha',
 'django_settings_export',
 'main']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'stronghold.middleware.LoginRequiredMiddleware']



Traceback:

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  149.                     response = self.process_exception_by_middleware(e, request)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/views.py" in dispatch
  466.             response = self.handle_exception(exc)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/views.py" in dispatch
  463.             response = handler(request, *args, **kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/generics.py" in post
  246.         return self.create(request, *args, **kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/mixins.py" in create
  20.         serializer.is_valid(raise_exception=True)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/serializers.py" in is_valid
  213.                 self._validated_data = self.run_validation(self.initial_data)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/serializers.py" in run_validation
  407.         value = self.to_internal_value(data)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/serializers.py" in to_internal_value
  437.                 validated_value = field.run_validation(primitive_value)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/serializers.py" in run_validation
  403.         (is_empty_value, data) = self.validate_empty_values(data)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/fields.py" in validate_empty_values
  453.             return (True, self.get_default())

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/fields.py" in get_default
  437.                 self.default.set_context(self)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/fields.py" in set_context
  239.         self.user = serializer_field.context['request'].user

Exception Type: KeyError at /api/comments/98/
Exception Value: 'request'

์ถ”๊ฐ€๋œ ํ•„๋“œ์—๋Š” ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๊ฐ€ ๋ฉ”ํƒ€ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์ˆ˜ํ–‰ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ž‘์—…์ด ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ๋“ค์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ๋‹น์‹ ์—๊ฒŒ ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„์—์„œ ์ด๋ฏธ ๋งํ–ˆ๋“ฏ์ด __init__ ๋ฉ”์„œ๋“œ์—์„œ ์ปจํ…์ŠคํŠธ ๊ฒ€์ƒ‰์„ ์ œ๊ฑฐํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์ด ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ•„๋“œ ์„ค์ •์€ ํ™•์‹คํžˆ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ๋ก€.

๋งž์•„, ๋‚ด ์ „ํ™”์— ์žˆ์—ˆ๋‹ค, ๊ทธ ๋ถ€๋ถ„์„ ๋ˆˆ์น˜ ์ฑ„์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ ๋‹ค์Œ ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๊ฐ€ ์ตœ์ƒ์œ„ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋ณด๋‹ค ํ›จ์”ฌ ์ „์— ์ธ์Šคํ„ด์Šคํ™”๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ •์ƒ์ž…๋‹ˆ๋‹ค.
์ปจํ…์ŠคํŠธ์˜ ๋ชฉ์ ์€ ์‹ค์ œ๋กœ ์ธ์Šคํ„ด์Šคํ™”๊ฐ€ ๋ฐœ์ƒํ•œ ํ›„์— ์ปจํ…์ŠคํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ init์—์„œ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ๋†€๋ผ์šด ์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๊ดœ์ฐฎ์•„. ๋งˆ์ง€๋ง‰ ์ฐธ๊ณ ๋กœ, ์˜ค๋ฅ˜ ๋กœ๊ทธ๊ฐ€ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ __init__ ๋ฉ”์„œ๋“œ์— ๋‚˜ํƒ€๋‚˜์ง€ ์•Š๊ณ  CurrentUserDefault() ๊ฐœ์ฒด( set_context ๋ฐฉ๋ฒ•). ๊ทธ๋Ÿฌ๋‚˜ ์ปจํ…์ŠคํŠธ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์ง์ ‘ ํ˜ธ์ถœ์ด ์žˆ๋Š” ๊ฒฝ์šฐ, ์ฆ‰ ์กด์žฌ๋ฅผ ํ™•์ธํ•˜์ง€ ์•Š๊ณ  __init__ ์—๋„ ํ‘œ์‹œ๋˜๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค(์ „์ฒด ์ปจํ…์ŠคํŠธ๊ฐ€ ๋น„์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ „๋‹ฌ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค).
๋˜ํ•œ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์œ„์—์„œ ๊ฒฐ๋ก ์„ ๋‚ด๋ฆฐ ๊ฒƒ์„ ๋ฐ˜๋ณตํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ค‘์ฒฉ์ด ์—†๋Š” ๊ฒฝ์šฐ(๊ทธ๋ฆฌ๊ณ  ์ปจํ…์ŠคํŠธ๊ฐ€ ์ธ์Šคํ„ด์Šคํ™” ๋ฐฉ๋ฒ•์— ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ) ๋ชจ๋“  ๊ฒƒ์ด ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ปจํ…์ŠคํŠธ๋ฅผ ์–ด๋ฆฐ์ด์—๊ฒŒ ์ „ํŒŒํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. https://github.com/encode/django-rest-framework/pull/5304 ์—์„œ ํ•ด๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค None ์บ์‹ฑ๊ณผ ๊ด€๋ จ๋œ ๋งŽ์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ตœ๊ทผ์— ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ•œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

class MyBaseSerializer(serializers.HyperlinkedModelSerializer):

    def get_fields(self):
        '''
        Override get_fields() method to pass context to other serializers of this base class.

        If the context contains query param "omit_data" as set to true, omit the "data" field
        '''
        fields = super().get_fields()

        # Cause fields with this same base class to inherit self._context
        for field_name in fields:
            if isinstance(fields[field_name], serializers.ListSerializer):
                if isinstance(fields[field_name].child, MyBaseSerializer):
                    fields[field_name].child._context = self._context

            elif isinstance(fields[field_name], MyBaseSerializer):
                fields[field_name]._context = self._context

        # Check for "omit_data" in the query params and remove data field if true
        if 'request' in self._context:
            omit_data = self._context['request'].query_params.get('omit_data', False)

            if omit_data and omit_data.lower() in ['true', '1']:
                fields.pop('data')

        return fields

์œ„์—์„œ get_fields() ๋ฅผ ์žฌ์ •์˜ํ•˜๊ณ  ๋™์ผํ•œ ๊ธฐ๋ณธ ํด๋ž˜์Šค๊ฐ€ ์žˆ๋Š” ์ž์‹ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์— self._context ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ ๊ธฐ๋ณธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ListSerializers์˜ ๊ฒฝ์šฐ ์ปจํ…์ŠคํŠธ๋ฅผ ์ž์‹์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ฟผ๋ฆฌ ๋งค๊ฐœ๋ณ€์ˆ˜ "omit_data"๋ฅผ ํ™•์ธํ•˜๊ณ  "data" ํ•„๋“œ๊ฐ€ ์š”์ฒญ๋˜๋ฉด ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

์—ฌ์ „ํžˆ ์ด์— ๋Œ€ํ•œ ๋‹ต๋ณ€์„ ์ฐพ๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์—๊ฒŒ ์ด๊ฒƒ์ด ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์˜ค๋ž˜๋œ ์Šค๋ ˆ๋“œ๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ __init__ ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๊ณ  ๋‚ด ์‚ฌ์šฉ์ž ์ง€์ • ๋ฏน์Šค์ธ์— ๋ฐ”์ธ๋”ฉํ•˜์—ฌ ์š”์ฒญ(์ปจํ…์ŠคํŠธ์—์„œ)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฟผ๋ฆฌ ์„ธํŠธ๋ฅผ ํ•„ํ„ฐ๋งํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊ณต์œ ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฏน์Šค์ธ์€ get_objects_for_user ๋ฉ”์†Œ๋“œ๊ฐ€ ์ฟผ๋ฆฌ ์„ธํŠธ์— ์กด์žฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ฑฐ๋‚˜ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด Guardian.shortcuts.get_objects_for_user๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. POST ๋˜๋Š” PATCHing ์‹œ์—๋„ ์ค‘์ฒฉ๋œ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์— ๋Œ€ํ•ด ๋งค์šฐ ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰