ํธ์ง: ๋ฌธ์ ์ ํ์ฌ ์ํ๋ https://github.com/encode/django-rest-framework/issues/4231#issuecomment -332935943์ผ๋ก ๊ฑด๋๋๋๋ค.
===
DRF๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ ์์ฉํ๋ ์์ฉ ํ๋ก๊ทธ๋จ์์ ๋๊ด์ ๋์์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฅผ ๊ตฌํํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋๋ ๋ ธ๋ ฅํ๊ณ ์์ด :
์ต๊ทผ์ Django ์ ํ๋ฆฌ์ผ์ด์ ์ ๋๊ด์ ๋์์ฑ์ ์ถ๊ฐํ์ต๋๋ค. Wiki ์กฐํ๋ฅผ ์ ์ฅํ๋ ค๋ฉด:
DRF๋ฅผ ํตํด ๋งํ๋ ๋ ๊ฑฐ์ UI๊ฐ ์์์ต๋๋ค. ๋ ๊ฑฐ์ UI๋ ๋ฒ์ ๋ฒํธ๋ฅผ ์ฒ๋ฆฌํ์ง ์์์ต๋๋ค. ์ด๊ฒ์ด ๋์์ฑ ์ค๋ฅ๋ฅผ ์ผ์ผํฌ ๊ฒ์ผ๋ก ์์ํ์ง๋ง ๊ทธ๋ ์ง ์์์ต๋๋ค. #3648์ ๋ ผ์๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ดํดํ๋ค๋ฉด:
๋๋ฝ๋ ๋ฒ์ ID๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ผ์นํ์ง ์์์ผ ํ๋ฉฐ ๋์์ฑ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํด์ผ ํฉ๋๋ค.
๋๋ฝ๋ ๋ฒ์ ID๋ ๋์์ฑ ๊ฒ์ฌ๋ฅผ ํต๊ณผํ๋๋ก DRF์ ์ํด ํ์ฌ ID๋ก ์ฑ์์ง๋๋ค.
์ข์, ๊ณง ์์ 3.4 ๋ฆด๋ฆฌ์ค๊ฐ ์ฐ์ ์์์ด๋ฏ๋ก ์ด ๋งค์ฐ ์ฌ์ธต์ ์ธ ํฐ์ผ์ ์ฆ์ ๊ฒํ ํ ์ ์์ ๊ฒ์ด๋ผ๊ณ ์ฝ์ํ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ฌธ์ ๋ฅผ ํตํด ์์ธํ๊ณ ์ ์๊ฐํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ด๊ฒ์ ๋ฉฐ์น ์ด๋ ๋ช ๋ฌ์ด ์๋๋ผ ๋ช ์ฃผ ๋จ์๋ก ๋ณด๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค. ์งํ ์ํฉ์ด ๋ ์ด์ ์๊ฐ๋๋ฉด ํฐ์ผ์ ์ ๋ฐ์ดํธํ๊ณ ๊ณ์ ์๋ ค์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.
ํ์ธ. ๋ด ๋ฌธ์ ๋ ๋ ๊ฐ์ง ์์์ ์กฐํฉ์ด๋ผ๊ณ ํ์ ํฉ๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก DRF๋ ํ์ฌ(๋ฐ์ดํฐ๋ฒ ์ด์ค) ๊ฐ์ ์ฌ์ฉํ๊ณ ๋์์ฑ ์ ์ด๋ฅผ ์ค๋จํฉ๋๋ค. ๋ฌธ์ ์ ํ๋ฐ๋ถ๋ #3648(์์์๋ ์ธ์ฉ๋จ)์ ํ ๋ก ๊ณผ ๊ด๋ จ์ด ์์ผ๋ฉฐ #1445์๋ ์ฌ์ ํ ๊ด๋ จ์ด ์๋ ๊ฒ์ผ๋ก ๋ณด์ด๋ (3.x ์ด์ ) ํ ๋ก ์ด ์์ต๋๋ค.
๊ธฐ๋ณธ ๋์์ด ๋น๋ค์ด์ง ๊ตฌ์ฒด์ ์ธ(๊ทธ๋ฆฌ๊ณ ์ ์ ๋ ์ผ๋ฐ์ ์ธ) ๊ฒฝ์ฐ๊ฐ ModelSerializer์ "์ด์์ ์ธ" ๋์์ ๋ํ ๋ ผ์๋ฅผ ์ฌ๊ฐํ๊ธฐ์ ์ถฉ๋ถํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ๋ถ๋ช ํ, ๋๋ DRF์ ๋ํด 1์ธ์น๋ฐ์ ์๋์ง๋ง ๋ด ์ง๊ด์ ๋ค์ ๋์์ด ํ์ ํ๋ ๋ฐ PUT์ ์ ํฉํ๋ค๋ ๊ฒ์ ๋๋ค.
์์ ๊ธ๋จธ๋ฆฌ ๊ธฐํธ(1)๋ฅผ ๋ณ๊ฒฝํ ์ ์๊ฑฐ๋ ๊ธฐ๋ณธ๊ฐ์ด ๋ฌด์ฉ์ง๋ฌผ์ด ๋ฉ๋๋ค(๊ธฐ๋ณธ๊ฐ์ ์๊ณ ์์ง๋ง ์ ๋ ฅ์ด ํ์ํจ). ์ฆ, ์์ #2๋ฅผ ๋ณ๊ฒฝํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํฉ๋๋ค. ๋๋ #2683์์ ๋ค์๊ณผ ๊ฐ์ ๋น์ ์ ์ฃผ์ฅ์ ๋์ํฉ๋๋ค.
๋ชจ๋ธ ๊ธฐ๋ณธ๊ฐ์ ๋ชจ๋ธ ๊ธฐ๋ณธ๊ฐ์ ๋๋ค. ์ง๋ ฌ ๋ณํ๊ธฐ๋ ๊ฐ์ ์๋ตํ๊ณ ์ด๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด
Model.object.create()
์ ๋ํ ์ฑ ์์ ์ฐ๊ธฐํด์ผ โโํฉ๋๋ค.
์ด๋ฌํ ๋ฌธ์ ๋ถ๋ฆฌ์ ์ผ๊ด์ฑ์ ์ ์งํ๊ธฐ ์ํด ์ ๋ฐ์ดํธ ๋ ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ (๋ชจ๋ ๊ธฐ๋ณธ๊ฐ์ ๋ชจ๋ธ์ ์์) ์ ์ถ๋ ๊ฐ์ ํด๋น ์ ์ธ์คํด์ค์ ์ ์ฉํด์ผ ํฉ๋๋ค. ๊ทธ ๊ฒฐ๊ณผ #3648์์ ์์ฒญํ ๋์์ด ๋ฐ์ํฉ๋๋ค.
๋ง์ด๊ทธ๋ ์ด์ ๊ฒฝ๋ก๋ฅผ ์ค๋ช ํ๋ฉด ํ์ฌ ๋์์ด ์ผ๋ง๋ ์ด์ํ์ง ๊ฐ์กฐํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์ต์ข ๋ชฉํ๋
๊ทธ ๊น๋ฐ์ ์ด๋ฆ์ ๋ฌด์์
๋๊น? ํ์ฌ ๋ชจ๋ธ ์ง๋ ฌ ๋ณํ๊ธฐ๋ ์ค์ ๋ก required==True and default==None
์กฐ๊ฑด์ ์ถฉ์กฑํ๋ ํ๋๊ฐ ํ์ํ ๋ถ๋ถ ์ง๋ ฌ ๋ณํ๊ธฐ์
๋๋ค. ์ด์ ๋ฒ์ ๊ณผ์ ํธํ์ฑ์ ๊นจ๋จ๋ฆฌ์ง ์๊ณ ๋ partial
ํ๋๊ทธ๋ฅผ ๋ช
์์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ์๋ก์ด(์์์ ์ธ) ํ๋๊ทธ๊ฐ ํ์ํฉ๋๋ค. quasi_partial
๋จ์์ง๋ง ์์์ ์ธ ์๊ตฌ ์ฌํญ required==True and default==None
์ ํํํ ์ ์๊ธฐ ๋๋ฌธ์ ์ด ๋์์ด ์๊ธํ ์ค๋จ๋์ด์ผ ํ๋ค๋ ๊ฒ์ด ๋๋ฌด๋ ๋ถ๋ช
ํฉ๋๋ค.
์ง๋ ฌ ๋ณํ๊ธฐ์ ๋ฉํ์ extra_kwargs
๋ฅผ ์ถ๊ฐํ์ฌ version
๋ฅผ ํ์ ํ๋๋ก ๋ง๋ค ์ ์์ต๋๋ค.
class ConcurrentModelSerializer(serializers.ModelSerializer):
class Meta:
model = ConcurrentModel
extra_kwargs = {'version': {'required': True}}
@anoopmalev๋ ๊ฐ์ฌํฉ๋๋ค. ๊ทธ๊ฒ์ ๋๋ฅผ ์์ฐ ์ง์ ์ ๋จธ๋ฌผ๊ฒ ํ ๊ฒ์ ๋๋ค.
"์๊ณ " ๋ ํ์ ์ฃผ๋ฆ์ด ํ๋ ๋ ์๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค. ๋ด๊ฐ ๋งํ ๋ชจ๋ ๊ฒ์ ์ง๋ ฌ ๋ณํ๊ธฐ์ ํ๋์ ์ ์ฉ๋์ด์ผ ํฉ๋๋ค. ํ๋๊ฐ ์ง๋ ฌ ๋ณํ๊ธฐ์ ํฌํจ๋์ง ์์ ๊ฒฝ์ฐ ์์ ํ๋ฉด ์ ๋ฉ๋๋ค. ์ด๋ฐ ์์ผ๋ก ๋ชจ๋ ์ง๋ ฌ ๋ณํ๊ธฐ๋ ํฌํจ๋์ง ์์ ํ๋์ ๋ํด ๋ถ๋ถ์ ์ ๋๋ค(๊ทธ๋ฆฌ๊ณ ๊ทธ๋์ผ๋ง ํฉ๋๋ค). ์ด๊ฒ์ ์์ "์ ์ธ์คํด์ค ๋ง๋ค๊ธฐ"๋ณด๋ค ์กฐ๊ธ ๋ ๋ณต์กํฉ๋๋ค.
๋๋ ์ด ๋ฌธ์ ๊ฐ ์์ผ๋ก ๋์๊ฐ๊ธฐ ์ํด ๋ ์ ํ์ ์ธ ์ ์์ผ๋ก ์ถ์๋์ด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
ํ์ฌ ์ํ์์ ์คํ ๊ฐ๋ฅํ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค.
์ง๊ธ์ ์ด๊ฒ์ ๋ซ๊ณ ์์ต๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ์ํ๋ ํ๋์ ๋ํ ๊ฐ๊ฒฐํ๊ณ ์คํ ๊ฐ๋ฅํ ์ค๋ช
์ผ๋ก ์ค์ผ ์ ์๋ค๋ฉด ์ฌ๊ณ ํ ์ ์์ต๋๋ค. ๊ทธ๋๊น์ง๋ ๋จ์ํ ๊ด๋ฒ์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ค์์ non-partial serializer์ ๋ํ ๊ฐ๊ฒฐํ ์ ์์ ๋๋ค.
blank
๋ฐ/๋๋ null
์ ์ํด ์์๋ ๊ฐ์ ํฌํจํ์ฌ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฑ์ฐ๊ธฐ๋ช ํ์ฑ์ ์ํด ์ด ํ๋ก์ธ์ค์ ์ต์ข ์ ํ์ ๋ํด ์ ํจ์ฑ ๊ฒ์ฌ๊ฐ ์คํ๋ฉ๋๋ค.
์ฆ, ์
๋ฐ์ดํธ๋ฅผ ์ํด ๋ชจ๋ธ ๊ธฐ๋ณธ๊ฐ์ด ์๋ ์ง๋ ฌ ๋ณํ๊ธฐ ํ๋์ required=True
๋ฅผ ์ค์ ํ์๊ฒ ์ต๋๊น?
๋ด๊ฐ ๋ง์์ด?
์(๋ฐ ๊ทธ ์ด์). ์ด๊ฒ์ด ๋ด๊ฐ partial
(๋ชจ๋ ํ๋๋ ์ ํ ์ฌํญ)์ non-partial
(๋ชจ๋ ํ๋๋ ํ์)์ ๊ตฌ๋ถ์ ์ดํดํ๋ ๋ฐฉ๋ฒ์
๋๋ค. non-partial
์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ํ๋๋ฅผ ํ์๋ก ํ์ง ์๋ ์ ์ผํ ๊ฒฝ์ฐ๋ ๊ธฐ๋ณธ๊ฐ(์ข๊ฑฐ๋ ๊ด๋ฒ์ํ๊ฒ ์ ์๋จ)์ด ์๋ ๊ฒฝ์ฐ์
๋๋ค. ๊ฐ์ด ์ ๊ณต๋์ง ์์ผ๋ฉด ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ํด๋น ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค._
๊ธฐ์ธ์๊ผด ์น์ ์ DRF๊ฐ ํ์ฌ ์ํํ์ง ์๋ ๊ฒ์ด๋ฉฐ ๋ด ์ ์์์ ๋ ์ค์ํ ๋ณ๊ฒฝ ์ฌํญ์ ๋๋ค. ํ์ฌ ๊ตฌํ์ ํ๋๋ฅผ ๊ฑด๋๋๋๋ค.
๋๋ ๋ ๋ฒ์งธ ์ ์์ด ์์ฌ ์์์ง๋ง ์ค์ ๋ก "๊ธฐ๋ณธ๊ฐ"์ด๋ผ๋ ์์ด๋์ด์ ์ผ๋ง๋ ๊ด๋ํ๊ณ ์ถ์์ง์ ๋ํ ๋ณ๋์ ์ง๋ฌธ์
๋๋ค. ํ์ฌ ๋์์ default
๊ทธ๋ ๊ฒ ์ทจ๊ธ๋๋ค๋ ์ ์์ "์๊ฒฉ"ํฉ๋๋ค. ํ์ํ ๋ฐ์ดํฐ์ ์์ _์ ๋ง__ ์ค์ด๊ณ ์ถ๋ค๋ฉด blank=True
ํ๋๋ ์ ํ ์ฌํญ์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค... ๋ถ์ฌ ๊ฐ์ด ๊ณต๋ฐฑ ๊ฐ์ด๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค.
@claytondaley ์ด ๋ฐฉ๋ฒ์ผ๋ก 2๋ฐฐ ์ดํ๋ก DRF์ ํจ๊ป OOL์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
class VersionModelSerializer(serializers.ModelSerializer, BaseSerializer):
_initial_version = 0
_version = VersionField()
def __init__(self, *args, **kwargs):
super(VersionModelSerializer, self).__init__(*args, **kwargs)
# version field should not be required if there is no object
if self.instance is None and '_version' in self.fields and\
getattr(self, 'parent', None) is None:
self.fields['_version'].read_only = True
self.fields['_version'].required = False
# version field is required while updating instance
if self.instance is not None and '_version' in self.fields:
self.fields['_version'].required = True
if self.instance is not None and hasattr(self.instance, '_version'):
self._initial_version = self.instance._version
def validate__version(self, value):
if self.instance is not None:
if not value and not isinstance(value, int):
raise serializers.ValidationError(_(u"This field is required"))
return value
# more code & helpers
๊ทธ๊ฒ์ ๋ชจ๋ ์ข ๋ฅ์ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ์ ์๋ํ๋ฉฐ ์ด๋ค ๋ฌธ์ ๋ ์ผ์ผํค์ง ์์์ต๋๋ค.
์ด ์ผ์ชฝ์ด ์ฌ๊ณ ๋ก ๋ซํ์ต๋๊น? ๋๋ ๊ตฌ์ฒด์ ์ธ ์ง๋ฌธ์ ๋๋ตํ๊ณ ์ ์์ ๋ฌด์์ด ์๋ชป๋์๋์ง ์ด์ ๋ฅผ ๋ฃ์ง ๋ชปํ์ต๋๋ค.
@claytondaley OOL์ด DRF์ ์ผ๋ถ์ฌ์ผ ํ๋ ์ด์ ๋ ๋ฌด์์
๋๊น? ๋ด ์ฝ๋๋ฅผ ํ์ธํ์ญ์์ค โ ํฐ ์ฑ์์ ์ฐพ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค(1400๊ฐ์ ํ
์คํธ). VersionField
๋ IntegerField
์
๋๋ค.
์ง๋ ฌ ๋ณํ๊ธฐ์ OOL์ ํ๋ ์ฝ๋ฉํ์ต๋๋ค. ๊ฒฝ์ ์กฐ๊ฑด์ด ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์๋ชป๋ ์ฅ์์ ๋๋ค. ๋ณ๋ ฌ ์ ๋ฐ์ดํธ(๋์ผํ ์ด์ ๋ฒ์ ์ฌ์ฉ)๋ ๋ชจ๋ ์ง๋ ฌ ๋ณํ๊ธฐ์์ ์ ๋ฌ๋์ง๋ง... ์ ์ฅ ์์ ์์๋ ํ๋๋ง ์น๋ฆฌํฉ๋๋ค.
์ ๋ django-concurrency
๋ฅผ ์ฌ์ฉํ์ฌ OOL ๋
ผ๋ฆฌ๋ฅผ ์ ์ฅ ์์
(์ํด ์๋ ์์น)์ ๋ฃ์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก UPDATE... WHERE version = submitted_version
. ์ด๊ฒ์ ์์์ ์ด๋ฏ๋ก ๊ฒฝ์ ์กฐ๊ฑด์ด ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ง๋ ฌํ ๋
ผ๋ฆฌ์ ๋ค์๊ณผ ๊ฐ์ ๊ฒฐํจ์ด ์์ต๋๋ค.
required=False
๋ฅผ ์ค์ ํฉ๋๋ค. (์ ํจํ) ์์ด๋์ด๋ ์ ์ถ๋ ๊ฐ์ด ์๋ ๊ฒฝ์ฐ DRF๊ฐ ํด๋น ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์
๋๋ค.ํ๋๊ฐ ํ์ํ์ง ์์ ๊ฒฝ์ฐ ์ฌ์ฉํ ๊ธฐ๋ณธ๊ฐ์ด ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋ ๊ฒ ํฉ๋๋ค. DRF๋ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ ํด๋น ๊ณ์ฝ์ ์ดํํ์ง ์์ต๋๋ค. ๊ธฐ์กด ๊ฐ์ ์ฌ์ฉํฉ๋๋ค.
๊ทผ๋ณธ์ ์ธ ๋ฌธ์ ๋ ์ด์ ์ ๋ ผ์๋์์ง๋ง ๋ฉ์ง๊ณ ๊ตฌ์ฒด์ ์ธ ์ฌ๋ก๊ฐ ์์์ต๋๋ค. OOL์ด ๊ทธ ์ด์์ ์ธ ๊ฒฝ์ฐ์ ๋๋ค. ๋ฒ์ ํ๋์ ๊ธฐ์กด ๊ฐ์ ํญ์ OOL์ ์ ๋ฌํ๋ฏ๋ก ๋ฒ์ ์ ์๋ตํ์ฌ ์ ์ฒด OOL ์์คํ ์ ์ฐํํ ์ ์์ต๋๋ค. ๊ทธ๊ฒ์ (๋ถ๋ช ํ) OOL ์์คํ ์ ์ํ๋ ๋์์ด ์๋๋๋ค.
@claytondaley
์ง๋ ฌ ๋ณํ๊ธฐ์ OOL์ ํ๋ ์ฝ๋ฉํ์ต๋๋ค.
๋ด๊ฐ ๊ทธ๋ฌ์ด? ํ๋ ์๊ตฌ ์ฌํญ ์ธ์ ์ง๋ ฌ ๋ณํ๊ธฐ์์ OOL ๋ ผ๋ฆฌ๋ฅผ ์ฐพ์์ต๋๊น?
๊ฒฝ์ ์กฐ๊ฑด์ด ์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์๋ชป๋ ์ฅ์์ ๋๋ค.
Sry, ์ฌ๊ธฐ ๊ฒฝ์ ์กฐ๊ฑด์ด ์ด๋์ ์๋์ง ์ ์ ์์ต๋๋ค.
OOL ๋ ผ๋ฆฌ๋ฅผ ์ ์ฅ ์์ (์ํ ์์น)์ ๋ฃ๋ django-concurrency๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
๋๋ ๋ํ django-concurrency
๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค :) ํ์ง๋ง ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ์๋ ๋ชจ๋ธ ์์ค์
๋๋ค. ์ง๋ ฌ ๋ณํ๊ธฐ ์์ค์์ ๋ค์์ ์ํํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค.
์ค์ ๋ก autor๊ฐ "์์ ํ์ง ์์"์ผ๋ก ํ์๋ ๋ฌธ์ ๋ก ์ธํด django-concurrency
๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ์์ต๋๋ค. obj.save(update_fields=['one', 'two', 'tree'])
๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ชป๋ ๊ดํ์ ๋ฐ๊ฒฌํ์ฌ OOL์ ์ฐํํ๋ฏ๋ก ํจํค์ง๋ฅผ ๋ถ๊ธฐํ์ต๋๋ค.
์ฌ๊ธฐ์ ์์ ์ธ๊ธํ serializer์ ๋๋ฝ๋ save
๋ฉ์๋๊ฐ ์์ต๋๋ค. ๋ชจ๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํฉ๋๋ค.
def save(self, **kwargs):
try:
self.instance = super(VersionModelSerializer, self).save(**kwargs)
return self.instance
except VersionException:
# Use select_for_update so we have some level of guarantee
# that object won't be modified at least here at the same time
# (but it may be modified somewhere else, where select_for_update
# is not used!)
with transaction.atomic():
db_instance = self.instance.__class__.objects.\
select_for_update().get(pk=self.instance.pk)
diff = self._get_serializer_diff(db_instance)
# re-raise exception, so api client will receive friendly
# printed diff with writable fields of current serializer
if diff:
raise VersionException(diff)
# otherwise re-try saving using db_instance
self.instance = db_instance
if self.is_valid():
return super(VersionModelSerializer, self).save(**kwargs)
else:
# there are errors that could not be displayed to a user
# so api client should refresh & retry by itself
raise VersionException
# instance.save() was interrupted by application error
except ApplicationException as logic_exc:
if self._initial_version != self.instance._version:
raise VersionException
raise logic_exc
์ฃ์กํฉ๋๋ค. ๋๋ ๋น์ ์ดํ๊ณ ์๋ ์ผ์ ํ์ ํ๊ธฐ ์ํด ๋น์ ์ ์ฝ๋๋ฅผ ์ฝ์ง ์์์ต๋๋ค. ์๋ฆฌ์ผ๋ผ์ด์ ๋ฅผ ๋ดค์ต๋๋ค. ๋ถ๋ช ํ ์ง๋ ฌ ๋ณํ๊ธฐ๋ฅผ ํดํนํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ง๋ง ๊ทธ๋ด ํ์๋ ์์ต๋๋ค. DRF ๋ ผ๋ฆฌ์ ๊ฒฐํจ์ ๊ทธ ์์ฒด๋ก ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋๋ ๋จ์ง ์์ ์ ์ค๋ช ํ๊ธฐ ์ํด OOL์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ต์ ๋ฒ์ ์ django-concurrency์ ๋ํด ํด๋น ์ฝ๋๋ฅผ ์๋ํด์ผ ํฉ๋๋ค( IGNORE_DEFAULT=False
์ฌ์ฉ). django-concurrency๋ ๊ธฐ๋ณธ๊ฐ์ ๋ฌด์ํ๋๋ฐ ํจ์น๋ฅผ ์ ์ถํ์ต๋๋ค. ์ ์์ ์ธ ๊ฒฝ์ฐ์ ์๋ํ๋๋ก ํ๊ธฐ ์ํด ์ถ์ ํด์ผ ํ๋ ์ด์ํ ์ฝ๋ ์ผ์ด์ค๊ฐ ์์์ต๋๋ค.
ํดํน์ด ์๋๋ผ ๊ธฐ๋ณธ ๊ธฐ๋ฅ ํ์ฅ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ ์ง์์ ์ํ ์ต์ ์ ์ฅ์๋ django-concurrency
ํจํค์ง๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋๋ ์ ์ฒด ๋ฌธ์ ํ ๋ก ์ ๋ค์ ์ฝ์๊ณ ๋น์ ์ ์ ์์ด ๋๋ฌด ๊ด๋ฒ์ํ๊ณ ๋ง์ ๊ณณ์์ ์คํจํ ๊ฒ์ด๋ผ๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค(๋ค๋ฅธ ์กฐ๊ฑด์์ ๋ค๋ฅธ ์์ค์ ๊ธฐ๋ณธ๊ฐ์ ๋ง์ ์ฒ๋ผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์). DRF 3.x๋ 2.x๋ณด๋ค ํจ์ฌ ์ฝ๊ณ ์์ธก ๊ฐ๋ฅํ๋ฏ๋ก ๊ทธ๋๋ก ์ ์งํฉ๋๋ค. :)
์ง๋ ฌ ๋ณํ๊ธฐ(๋ชจ๋ธ์ ๋๋ฌํ๊ธฐ ์ ์)์์ ๊นจ์ก๊ธฐ ๋๋ฌธ์ ๋ชจ๋ธ ๊ณ์ธต์์ ์ด๊ฒ์ ๊ณ ์น ์ ์์ต๋๋ค. OOL์ ์ ์ณ๋๊ณ ... default
๊ฐ ์ค์ ๋ ๊ฒฝ์ฐ ํ๋๊ฐ ํ์ํ์ง ์์ ์ด์ ๋ ๋ฌด์์
๋๊น?
๋ถ๋ถ์ ์ด์ง ์์ ์ง๋ ฌ ๋ณํ๊ธฐ๋ (๊ธฐ๋ณธ์ ์ผ๋ก) ๋ชจ๋ ํ๋๋ฅผ "์๊ตฌ"ํ์ง๋ง ์ฐ๋ฆฌ๋ ์ด๊ฒ์ ์๋ตํฉ๋๋ค. ๋ฒ๊ทธ์ธ๊ฐ์? ์๋๋ฉด ๋ ผ๋ฆฌ์ ์ธ ์ด์ ๊ฐ ์์ต๋๊น?
๋ด ์ฝ๋ ์์ ์์ ๋ณผ ์ ์๋ฏ์ด _version ํ๋๋ ๊ฐ๋ฅํ ๋ชจ๋ ๊ฒฝ์ฐ์ ํญ์ ์ฌ๋ฐ๋ฅด๊ฒ ํ์ํฉ๋๋ค.
btw, ๋ด๊ฐ https://github.com/gavinwahl/django-optimistic-lock ์์ ๋ชจ๋ธ lvl ์ฝ๋๋ฅผ ๋น๋ ธ๊ณ django-concurrency
์์ ๋น๋ฆฐ ๊ฒ์ด ์๋๋ผ ๊ฑฐ์ ์ด์ ์์ด ๋ณต์กํ๋ค๋ ๊ฒ์ด ๋ฐํ์ก์ต๋๋ค.
... ๊ทธ๋์ ๋ฒ๊ทธ๋ "๋น๋ถ๋ถ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ์ผ๋ถ ํ๋๋ฅผ ํ์๊ฐ ์๋ ๊ฒ์ผ๋ก ์๋ชป ์ค์ ํ์ต๋๋ค"์ ๋๋ค. ๊ทธ๊ฒ ๋์์ ๋๋ค. ๊ทธ๊ฒ์ด ๋ถ๋ถ์ ์ด์ง ์์ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ๋ง๋๋ (์์์ ) ์ฝ์์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋๋ ๊ทธ๊ฒ์ ์ธ์ฉํ ์ ์๋ค:
๊ธฐ๋ณธ์ ์ผ๋ก ์ง๋ ฌ ๋ณํ๊ธฐ๋ ๋ชจ๋ ํ์ ํ๋์ ๋ํ ๊ฐ์ ์ ๋ฌํด์ผ ํ๋ฉฐ ๊ทธ๋ ์ง ์์ผ๋ฉด ์ ํจ์ฑ ๊ฒ์ฌ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ด๊ฒ์ ํ์ ์ฌํญ์ ๋ํด ์๋ฌด ๊ฒ๋ ๋งํ์ง ์์ต๋๋ค(๊ธฐ๋ณธ๊ฐ์ด ์ ๊ณต๋๋ ๊ฒฝ์ฐ ์ ์ธ).
(๊ทธ๋ฆฌ๊ณ ๋ ๊ฐ์ง ๋ค๋ฅธ ์์ค์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์๋ค๋ ๊ฒ์ ์์ง๋ง ModelSerializer๋ ํด๋น ๊ฒฐ์ ์ ๋ํ ์ฑ ์์ ์ง์ง ์๋ ๊ฒฝ์ฐ ํ๋๋ฅผ ์๊ตฌํ์ง ์์์ผ ํฉ๋๋ค.)
์์ ์ ์์ ๊ฒ ๊ฐ์์..
(๊ทธ๋ฆฌ๊ณ ๋ ๊ฐ์ง ๋ค๋ฅธ ์์ค์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์๋ค๋ ๊ฒ์ ์์ง๋ง ModelSerializer๋ ํด๋น ๊ฒฐ์ ์ ๋ํ ์ฑ ์์ ์ง์ง ์๋ ๊ฒฝ์ฐ ํ๋๋ฅผ ์๊ตฌํ์ง ์์์ผ ํฉ๋๋ค.)
๊ทธ๊ฒ ๋ฌด์จ ๋ฌธ์ ์ผ?
์๊ฒ ์ต๋๋ค. ๋ค๋ฅธ ๊ฐ๋๋ก ์๋ํด ๋ณด๊ฒ ์ต๋๋ค.
๋์ผํ ๋ฐ์ดํฐ๋ก CREATE ๋๋ UPDATE๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํฉ๋๊น(ID ์ ์ธ)
์ ๋ง ๊ฐ๋จํ ๋ชจ๋ธ ๋ฐ ์ง๋ ฌ ๋ณํ๊ธฐ์ ์คํจ/์์ ๋์์ ๋ณด์ฌ์ฃผ๋ ๋ช ์ค์ ์ฌ์ฉํ์ฌ ์์ด๋์ด๋ฅผ ์ค๋ช ํ ์ ์์ต๋๊น?
์ค๋์ ์๊ฐ์ด ๋ฆ์ด์ ธ์ ๋ด์ผ ์ ๋ฆฌํ๊ฒ ์ต๋๋ค... ํ์ง๋ง ๊น์ด ๋ค์ด๊ฐ์๋ก #3648์ด non-partial serializer์ ๋ ์ ํฉํฉ๋๋ค. ๊ทธ๋์ ModelSerializer๊ฐ ๋ชจ๋ธ์ ๋ชจ๋ ํ๋๋ฅผ ์๊ตฌํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? ๋น์ ์ ๋ ผ๋ฆฌ๊ฐ ๋์ ๋ค๋ฅผ ์๋ ์์ต๋๋ค.
ModelSerializer๋ ๊ฒฝ๊ณ ๋ชจ๋ธ์ ๊ฒ์ฌํ๊ณ ํ์ํ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ์ง ์์ต๋๊น?
๋๋ ๊ธฐ๊ณ์ ์ผ๋ก ๋ฐฉ๋ฒ ์ ์๋ฏธํ์ง ์์ต๋๋ค. non-partial Serializer์ ๊ธฐ๋ณธ ๊ฐ์ ์ ๋ชจ๋ ๊ฒ์ ์๊ตฌํ๋ ๊ฒ์
๋๋ค(์์์ ์ธ์ฉ). get_field_kwargs
๊ฐ ์ด ๊ฐ์ (ํนํ ์ฌ๊ธฐ )์์ ๋ฒ์ด๋ ๊ฒฝ์ฐ์๋ ํ๋นํ ์ด์ ๊ฐ ์์ด์ผ ํฉ๋๋ค. ๊ทธ ์ด์ ๋ ๋ฌด์์
๋๊น?
๋ด๊ฐ ์ ํธํ๋ ๋๋ต์ "์ ์ถ๋ ๊ฐ์ด ์์ผ๋ฉด ํด๋น ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์" ๊ณ์ ์ ๊ณตํ๋ ๊ฒ์ ๋๋ค(๊ทธ๋ฌ๋ DRF๋ ์ค์ ๋ก ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํด์ผ ํจ). ๋ด๊ฐ ๋์น ๋ ๋ค๋ฅธ ๋๋ต์ด ์์ต๋๊น? ๊ธฐ๋ณธ๊ฐ์ด ์๋ ํ๋๊ฐ ํ์ํ์ง ์์ ์ด์ ๋ ๋ฌด์์ ๋๊น?
๋ถ๋ช ํ ์ ๋ "์์ ํ" ์๋ฃจ์ ์ ์ ํธํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋ฒ์งธ ๋ต๋ณ์ด ์์์ ์ธ์ ํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ด๋ฌํ ํ๋๋ฅผ ์๊ตฌํ ์ ์์ต๋๋ค. ๊ทธ๊ฒ์ (ํ์ฌ ์์์ ์ธ) ํน๋ณํ ๊ฒฝ์ฐ๋ฅผ ์ ๊ฑฐํฉ๋๋ค. ์ฝ๋๋ฅผ ๋จ์ํ/์ถ์ํฉ๋๋ค. ๋ด๋ถ์ ์ผ๋ก ์ผ๊ด์ฑ์ด ์์ต๋๋ค. ๋ด ์ฐ๋ ค๋ฅผ ํด๊ฒฐํฉ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก non-partial serializer๋ฅผ non-partial๋ก ๋ง๋ญ๋๋ค.
์ด์ ๋๋ ์ ์ด๋ ๋น์ ์ด ์๋ฏธํ๋ ๋ฐ๋ฅผ ์๊ณ ์์ต๋๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ ModelForm ๋์์ด ๋ฌด์์ธ์ง ํ์ธํ์ต๋๊น? (๋ชจ๋ฐ์ผ์์๋ ์ง์ ํ ์ ์์ต๋๋ค)
Django ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด '๊ณต๋ฐฑ'์ ํ๋๊ฐ ํ์์ธ์ง ์ฌ๋ถ๋ฅผ ์ ์ดํฉ๋๋ค. ์ด ๋ฌธ์ ์๋ ๊ด๋ จ ์๋ ์๊ฒฌ์ด ๋ง์ด ํฌํจ๋์ด ์์ผ๋ฏ๋ก ์ด ๋ฌธ์ ์ ๋ํด ๋ณ๋์ ํฐ์ผ์ ์ฌ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๋ด ์๊ฐ์ modelserializer๋ modelform: ๋น ์ต์ ์ ์ด๊ฐ ํ์ํ๊ณ 'null'์ None์ด ํ์ฉ ๊ฐ๋ฅํ ์ ๋ ฅ์ด๊ณ 'default'๊ฐ ํด๋น ๋ ผ๋ฆฌ์ ์ํฅ์ ๋ฏธ์น์ง ์๋์ง ์๋ ค์ค๋๋ค.
๋ ๋ฒ์งธ ํฐ์ผ์ ์ด ์ํฅ์ด ์์ง๋ง ๊ณต๋ฐฑ์ ๋น์ทํ ์ฝ๋๊ฐ ํ์ํ์ง ๊ฑฑ์ ๋ฉ๋๋ค. django ํ ๋ก ๊ทธ๋ฃน ์์ :
๊ธฐ์กด ๋ชจ๋ธ ์์๊ณผ ์๋ํ๋ ํ ํ๋ฆฟ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ชจ๋ธ์ ์ ํ์ ๋ฌธ์ ํ๋๋ฅผ ์ถ๊ฐํ์ง๋ง HTML ํ ํ๋ฆฟ์ ํด๋น ํ๋๋ฅผ ์ถ๊ฐํ์ง ๋ชปํฉ๋๋ค(์: ์ธ์ ์ค๋ฅ, ํ ํ๋ฆฟ์ ์์ด๋ฒ๋ ธ๊ฑฐ๋ ํ ํ๋ฆฟ ์์ฑ์์๊ฒ ๋ณ๊ฒฝ, ํ ํ๋ฆฟ์ ๋ณ๊ฒฝ์ด ํ์ํ์ง ๊นจ๋ซ์ง ๋ชปํจ), ํด๋น ์์์ด ์ ์ถ๋ ๋ Django๋ ์ฌ์ฉ์๊ฐ ๋๋ฝ๋ ํ๋์ ๋ํด ๋น ๋ฌธ์์ด ๊ฐ์ ์ ๊ณตํ๋ค๊ณ ๊ฐ์ ํ๊ณ ์ด๋ฅผ ๋ชจ๋ธ์ ์ ์ฅํ์ฌ ๊ธฐ์กด ๊ฐ์ ์ง์๋๋ค. .
์ผ๊ด์ฑ์ ์ํด ์ฐ๋ฆฌ๋ ๊ณ์ฝ์ ํ๋ฐ๋ถ๋ฅผ ์ดํํ ์๋ฌด๊ฐ ์์ผ๋ฉฐ ๋ถ์ฌ ๊ฐ์ ๊ณต๋ฐฑ์ผ๋ก ์ค์ ํฉ๋๋ค. ์ด๊ฒ์ ๋ชจ๋ธ์ ๋ํ ์ฐธ์กฐ ์์ด ๊ณต๋ฐฑ์ ์ฑ์ธ ์ ์๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๊ฐ ์ฝ๊ฐ ์ ์ง๋ง ๋งค์ฐ ์ ์ฌํฉ๋๋ค(๋ด ์๊ฐ์ #3648๊ณผ ์ผ์นํจ).
@tomchristie ์ ๋ํด ๊ฐ๋ตํ ์ ๋ณด๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. required
์ํ๊ฐ ๋ชจ๋ธ ํ๋ defaults
์์ฑ์ ์์กดํ๋ ์ด์ ๋ ๋ฌด์์
๋๊น?
ํ์ ์ํ๊ฐ ๋ชจ๋ธ ํ๋ ๊ธฐ๋ณธ ์์ฑ์ ์์กดํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
๊ฐ๋จํ ๋งํด์: ๋ชจ๋ธ ํ๋์ ๊ธฐ๋ณธ๊ฐ์ด ์๋ ๊ฒฝ์ฐ ์ ๋ ฅ์ผ๋ก ์ ๊ณตํ๋ ๊ฒ์ ์๋ตํ ์ ์์ต๋๋ค.
์ฌ์ค ๋๋ ์ด ํ๋์ ๋์ํ๋ค. ์ฝ๋์๋ ๋ถ๊ตฌํ๊ณ ModelForm์ ๋์ผํ ์์ ์ ์ํํฉ๋๋ค(์์ฑ๋ html์ด ๊ธฐ๋ณธ๊ฐ์ ์ ๊ณตํจ). DRF๊ฐ ๋ค๋ฅธ ๋ ผ๋ฆฌ๋ผ๋ฉด '๊ธฐ๋ณธ๊ฐ'์ ์ ๋ ์ ์ฉ๋์ง ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
@pySilver ์ค์ ๋ก ๋ค์์ ModelForm ๋์์ ๋๋ค.
# models.py
from django.db import models
class MyModel(models.Model):
no_default = models.CharField(max_length=100)
has_default = models.CharField(max_length=100, default="iAmTheDefault")
๋ช ํ์ฑ์ ์ํด _update_๊ฐ ๋ถ๋ถ์ ์ด๊ธฐ ๋๋ฌธ์ ๋ฌผ๊ฑด์ ์ด๋ฆ์ ์ฌ์ ํ โโ"๋ถ๋ถ์ "์ ๋๋ค. ๋ํ ์์ ํ("์ ์ฒด") ์ ๋ฐ์ดํธ๋ฅผ ํ ์คํธํ๊ณ ์์์ง๋ง ๋์์ ํ์ํ๋ ๋ฐ ์ฝ๋๊ฐ ํ์ํ์ง ์์์ต๋๋ค.
# in manage.py shell
>>> from django import forms
>>> from django.conf import settings
>>> from form_serializer.models import MyModel
>>>
>>> class MyModelForm(forms.ModelForm):
... class Meta:
... model = MyModel
... fields = ['no_default', 'has_default']
...
>>>
>>> partial = MyModel.objects.create()
>>> partial.id = 2
>>> partial.no_default = "Must replace me"
>>> partial.has_default = "I should be replaced"
>>> partial.save()
>>>
>>>
>>> POST_PARTIAL = {
... "id": 2,
... "no_default": "must change me",
... }
>>>
>>>
>>> form_partial = MyModelForm(POST_PARTIAL)
>>> form_partial.is_valid()
False
>>> form_partial._errors
{'has_default': [u'This field is required.']}
ModelForm์ ๊ธฐ๋ณธ๊ฐ์ด ์๋ค๊ณ ์๊ฐํ๋๋ผ๋ ์ด ์ ๋ ฅ์ด ํ์ํฉ๋๋ค . ์ด๊ฒ์ ๋ด๋ถ์ ์ผ๋ก ์ผ๊ด๋ ๋ ๊ฐ์ง ๋์ ์ค ํ๋์ ๋๋ค.
ํ์ ์ํ๊ฐ ๋ชจ๋ธ ํ๋ ๊ธฐ๋ณธ ์์ฑ์ ์์กดํ๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
๊ฐ๋จํ ๋งํด์: ๋ชจ๋ธ ํ๋์ ๊ธฐ๋ณธ๊ฐ์ด ์๋ ๊ฒฝ์ฐ ์ ๋ ฅ์ผ๋ก ์ ๊ณตํ๋ ๊ฒ์ ์๋ตํ ์ ์์ต๋๋ค.
@tomchristie ๋ ์์น์ ์ผ๋ก ๋์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์์๋๋ ๋์์ ๋ฌด์์ ๋๊น?
์ ๋ฐ์ดํธ์์๋ ๊ธฐ๋ณธ๊ฐ์ ๊ฐ์ ธ์์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค. ๋ถ๋ถ์ ์ด์ง ์์ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ๋ ๊ฒฝ์ฐ์ ๋ค๋ฅด๊ฒ ์๋ํด์ผ ํ๋ ์ด์ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋ถ๋ถ์ ์ด์ง ์๋ค๋ ๊ฒ์ "์์ ํ" ๋ ์ฝ๋๋ฅผ ๋ณด๋ด๊ณ ์์์ ์๋ฏธํฉ๋๋ค. ๋ฐ๋ผ์ ์์ ํ ๊ธฐ๋ก์ ๊ต์ฒดํด์ผ ํฉ๋๋ค.
์ ๋ฐ์ดํธ ์ ๊ฐ์ด ์ ๊ณต๋์ง ์์ผ๋ฉด ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์์ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค. ์์ ์ ์์ง๋ง ๊ธฐ๋ณธ๊ฐ์ผ๋ก ํฌ๋ช ํ๊ฒ ๋ฎ์ด์ฐ๋ ๊ฒ์ ๋ด POV์์ ์ง๊ด์ ์ด์ง ์์ต๋๋ค.
(์ ๊ฐ ์๊ฐํ๊ธฐ์ ๋ชจ๋ ์ ๋ฐ์ดํธ๊ฐ ๋ชจ๋ ํ๋์ ๋ํด ๋ถ๋ถ์ ์๋ฏธ๋ก ์ ๊ฐ๋ ๊ฒ์ด ์ค์ ๋ก ๋ ๋์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ ๊ฒฝ์ฐ - PUT์ ์ฌ์ ํ โโ๋ฉฑ๋ฑ์ฑ์ด๊ณ ์ด๋ ์ค์ํ ์ธก๋ฉด์ด๋ฉฐ ์ฃผ์ด์ง ํ์ฌ ๋์์ ๋ณ๊ฒฝํ๋ ๊ฒ์ด ์ด์ํ ์ ์์ต๋๋ค)
๋๋ ํ์คํ ๋น์ ์๊ฒ ์ ํธ๋๋ฅผ ๊ณต์ ํ์ง ์์ต๋๋ค. ์๋์ ์ผ๋ก ๋ค๋ฅด๊ฒ ๋ง๋ค์ง ์๋ ํ ๋ชจ๋ ์ธํฐํ์ด์ค๊ฐ ์๊ฒฉํ๊ธฐ๋ฅผ ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ PARTIAL ๋ NON-PARTIAL ๊ตฌ๋ถ์ ์ด๋ฏธ (์ด๋ก ์ ์ผ๋ก) ์ฐ๋ฆฌ ๋ ๋ค ์ํ๋ ๊ฒ์ ์ ๊ณตํฉ๋๋ค.
๋๋ ๋ถ๋ถ์ด ๋น์ ์ด ์ํ๋๋๋ก ์ ํํ๊ฒ ํ๋ํ๋ค๊ณ โโ๋ฏฟ์ต๋๋ค.
default
๋ฐ blank
(๋
ผ๋ฆฌ์ ์์ธ)์ ๊ด๋ จํ์ฌ ๋ถ๋ถ์ ์
๋๋ค. ๋ค๋ฅธ ๋ชจ๋ ๊ฒฝ์ฐ์๋ ๋ชจ๋ธ/๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ์ฝ ์กฐ๊ฑด์ด ๋ฐ์ธ๋ฉ๋ฉ๋๋ค.๋น ๋ถ๋ถ ์ง๋ ฌ ๋ณํ๊ธฐ์์ ์ผ๊ด์ฑ์ ์ป์ผ๋ ค๊ณ ํฉ๋๋ค. default
์ ๋ํ ํน์ ์ฌ๋ก๋ฅผ ์ ๊ฑฐํ๋ฉด ๊ธฐ์กด์ ๋ถ๋ถ์ ์ด์ง ์์ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ๋ด๊ฐ ์ํ๋ ์๊ฒฉํ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ๋ฉ๋๋ค. ModelForm๊ณผ๋ ๋๋ฑํฉ๋๋ค.
๋๋ ์ด๊ฒ์ด ํ๋ก์ ํธ ๋ด์์ ์์ ๋ถ์ฐ์์ฑ์ ๋ง๋ ๋ค๋ ๊ฒ์ ์๊ณ ์์ง๋ง ๋๊ตฐ๊ฐ๊ฐ ์ด์ ๊ฐ์ ๋ณ๊ฒฝ์ ํ ๊ฒ์ ์ด๋ฒ์ด ์ฒ์์ด ์๋๋๋ค. ํ์ฌ ๋์์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ํ๋ "๋ ๊ฑฐ์" ํ๋๊ทธ๋ฅผ ์ถ๊ฐํ๊ณ , ๊ฒฝ๊ณ (๊ธฐ๋ณธ ๋์์ด ๋ณ๊ฒฝ๋จ)๋ฅผ ์ถ๊ฐํ๊ณ , ํ์ ์ฃผ์ ๋ฆด๋ฆฌ์ค์์ ๊ธฐ๋ณธ๊ฐ์ ๋ณ๊ฒฝํฉ๋๋ค.
๋ ์ค์ํ ๊ฒ์ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ Django์ ์๋ก์ด ์ฌ์ค์์ ์ญํ ์ ํ๋๋ก ํ๋ ค๋ฉด ๊ฒฐ๊ตญ ์ด ๋ณ๊ฒฝ์ ์ํํด์ผ ํ๋ค๋ ๊ฒ์ ๋๋ค. ModelForm์์ ๋ณํํ๋ ์ฌ๋๋ค์ ์๋ ๊ธฐ์กด ์ฌ์ฉ์ ๊ธฐ๋ฐ์ ํฌ๊ฒ ์ด๊ณผํ ๊ฒ์ด๋ฉฐ ์ต์ํ ์ด๋ฌํ ๋ณํ๋ฅผ ์์ํ ๊ฒ์ ๋๋ค.
๋ด ๋ ์ผํธ ์ฝ์
:
@claytondaley์ ๋์ํ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค. PUT์ ๋ฉฑ๋ฑ์ ๋ฆฌ์์ค ๊ต์ฒด์ด๊ณ PATCH๋ ๊ธฐ์กด ๋ฆฌ์์ค์ ๋ํ ์
๋ฐ์ดํธ์
๋๋ค. ๋ค์ ์๋ฅผ ๋ค์ด๋ณด์ธ์.
class Profiles(models.Model):
username = models.CharField()
role = models.CharField(default='member', choices=(
('member', 'Member'),
('moderator', 'Moderator'),
('admin', 'Admin'),
))
์ ํ๋กํ์๋ ๊ธฐ๋ณธ ๊ตฌ์ฑ์ ์ญํ ์ด ์์ต๋๋ค. ๋ค์ ์์ฒญ์ ๋ฐ์๋ด ์๋ค.
POST /profiles username=moe
PUT /profiles/1 username=curly
PATCH /profiles/1 username=larry&role=admin
PUT /profiles/1 username=curly
ํ์ฌ ์ํ๋ก ์ฒซ ๋ฒ์งธ PUT ์ดํ ํ๋กํ ๋ฐ์ดํฐ์๋ {'username': 'curly', 'role': 'member'}
๊ฐ ํฌํจ๋ฉ๋๋ค. ๋ ๋ฒ์งธ PUT ํ์ {'username': 'curly', 'role': 'admin'}
๊ฐ ๋ฉ๋๋ค. ์ด๊ฒ์ ๋ฉฑ๋ฑ์ฑ์ ๊นจ๋จ๋ฆฌ์ง ์์ต๋๊น? (์์ ํ ํ์คํ์ง ์์ - ํฉ๋ฒ์ ์ผ๋ก ์์ฒญํจ)
ํธ์งํ๋ค:
๋๋ ๋ชจ๋๊ฐ PATCH์ ์๋ฏธ์ ๋ํด ๊ฐ์ ํ์ด์ง์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ ๋ฒ์งธ PUT ํ์๋ {'username': 'curly', 'role': 'admin'}์ด ๋ฉ๋๋ค.
์ ๋ ๊ฐ์ธ์ ์ผ๋ก ์ญํ ์ด ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ค์ ์ ํ๋๋ค๋ฉด ๋๋ ๊ฒ์
๋๋ค replace
์์ง ์ค์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์ด ์์ต๋๋ค.
์ฌ๊ธฐ๋ ๋ง์ฐฌ๊ฐ์ง์ง๋ง ์ง๊ธ๊น์ง ์ฐ๋ฆฌ ํ๋ก์ ํธ๋ PATCH์ ์์กดํ์ต๋๋ค. :)
์ฆ, ๋์์ฑ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๋ชจ๋ธ ๋ฒ์ ๊ด๋ฆฌ๊ฐ ํฌํจ๋ OP์ ์ฌ์ฉ ์ฌ๋ก๋ ๋์๊ฒ ์๋ฏธ๊ฐ ์์ต๋๋ค. PUT์ด ๊ธฐ๋ณธ๊ฐ(๊ฐ์ด ์๋ต๋ ๊ฒฝ์ฐ)์ ์ฌ์ฉํ์ฌ ๋์์ฑ ์์ธ๋ฅผ ๋ฐ์์ํฌ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค.
์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ๋ฐ๋์ RESTful RFC๋ฅผ ๋ฐ๋ฅผ ํ์๋ ์๋ค๋ ์ ์ ์ธ์ ํ๋ ๊ฒ์ผ๋ก ์์ํ๊ฒ ์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ทธ๋ค์ ์ต์ํ ํธํ ๊ฐ๋ฅํ ๋ชจ๋๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ํนํ REST ์ง์์ ์ ๊ณตํ๋ ํจํค์ง์์๋ ๋์ฑ ๊ทธ๋ ์ต๋๋ค.
๋ด ์๋ ์ฃผ์ฅ์ ์ฒซ ๋ฒ์งธ ์์น์์ ๋์จ ๊ฒ์ด์ง๋ง RFC (์น์ 4.3.4)๋ ๊ตฌ์ฒด์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋งํฉ๋๋ค(๊ฐ์กฐ ์ถ๊ฐ๋จ).
POST์ PUT ๋ฉ์๋์ ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด์ ์ ๋๋ด๋ ํํ์ ๋ํ ๋ค๋ฅธ ์๋๋ก ๊ฐ์กฐ๋ฉ๋๋ค. POST ์์ฒญ์ ๋์ ๋ฆฌ์์ค๋ ๋ฆฌ์์ค ์์ฒด์ ์๋ฏธ์ ๋ฐ๋ผ ํฌํจ๋ ํํ์ ์ฒ๋ฆฌํ๊ธฐ ์ํ ๋ฐ๋ฉด PUT ์์ฒญ์ ํฌํจ๋ ํํ ์ ๋์ ๋ฆฌ์์ค์ ์ํ๋ฅผ ๊ต์ฒดํ๋ ๊ฒ์ผ๋ก ์ ์๋ฉ๋๋ค.
...
ํ์ด๋ก๋๊ฐ ๋ถ๋ถ์ ์ธ ์ฝํ ์ธ ์ผ ๊ฐ๋ฅ์ฑ์ด ์์ผ๋ฏ๋ก ์ฃผ์ด์ง ๋์ ๋ฆฌ์์ค์ ๋ํ PUT์ ํ์ฉํ๋ ์ ์๋ฒ๋ Content-Range ํค๋ ํ๋([RFC7233]์ ์น์ 4.2)๋ฅผ ํฌํจํ๋ PUT ์์ฒญ์ ๋ํด 400(์๋ชป๋ ์์ฒญ) ์๋ต์ ๋ณด๋ด์ผ ํฉ๋๋ค.
๋ฐ๋ผ์ PUT์ ๋ถ๋ถ์ ์ด์ด์๋ ์ ๋ฉ๋๋ค( ์ฌ๊ธฐ๋ ์ฐธ์กฐ). ๊ทธ๋ฌ๋ PUT์ ์น์ ๋ ๋ค์๊ณผ ๊ฐ์ด ์ค๋ช ํฉ๋๋ค.
PUT ๋ฉ์๋๋ ๋์ ๋ฆฌ์์ค์ ์ํ๊ฐ ์์ฑ๋๊ฑฐ๋ ์์ฒญ ๋ฉ์์ง ํ์ด๋ก๋์ ํฌํจ๋ ํํ์ ์ํด ์ ์๋ ์ํ๋ก ๋์ฒด๋๋๋ก ์์ฒญํฉ๋๋ค. ์ฃผ์ด์ง ํํ์ ์ฑ๊ณต์ ์ธ PUT์ ๋์ผํ ๋์ ๋ฆฌ์์ค์ ๋ํ ํ์ GET์ด 200(OK) ์๋ต์ผ๋ก ์ ์ก๋๋ ๋๋ฑํ ํํ์ ์ด๋ํ ๊ฒ์์ ์ ์ํฉ๋๋ค.
GET์ ๋ํ ์์ (ํ์๋ ์๋์ง๋ง)์ ๋ด "ํํ" ์๋ฃจ์ ์ ์ฃผ์ฅํฉ๋๋ค. ๊ณต๋ฐฑ/๊ธฐ๋ณธ๊ฐ์ ์ฝ์ ํ๋ ๊ฒ์ ํธ๋ฆฌํ์ง๋ง ์ด ๋์์ ์ ๊ณตํ์ง ์์ต๋๋ค. ๊ด์ ๋ชป์ ์๋ง๋ ์ด ์๋ฃจ์ ์ด ์์ฌ์ ๋ถ๋ฌ์ผ์ผํฌ ๋๋ฝ๋ ํ๋๊ฐ ์๊ธฐ ๋๋ฌธ์ ํผ๋์ ์ต์ํํ๋ค๋ ๊ฒ์ ๋๋ค.
๋ถ๋ช ํ PATCH๋ ๋ถ๋ถ ์ ๋ฐ์ดํธ๋ฅผ ์ํ ์ง์ ์ต์ ์ด์ง๋ง ๋ถ๋ถ PUT์ด ์๋ "์ง์นจ ์ธํธ"๋ก ์ค๋ช ๋์ด ํญ์ ์ฝ๊ฐ ์ง์ฆ์ด ๋ฉ๋๋ค. POST(4.3.3)์ ์น์ ์ ์ค์ ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋งํฉ๋๋ค.
POST ๋ฉ์๋๋ ๋์ ๋ฆฌ์์ค๊ฐ ๋ฆฌ์์ค ๊ณ ์ ์ ํน์ ์๋ฏธ์ ๋ฐ๋ผ ์์ฒญ์ ํฌํจ๋ ํํ์ ์ฒ๋ฆฌํ๋๋ก ์์ฒญํฉ๋๋ค. ์๋ฅผ ๋ค์ด POST๋ ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ฌ์ฉ๋ฉ๋๋ค.
- HTML ์์์ ์ ๋ ฅ๋ ํ๋์ ๊ฐ์ ๋ฐ์ดํฐ ๋ธ๋ก์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ๋ก์ธ์ค์ ์ ๊ณตํฉ๋๋ค.
...
- ๋ฆฌ์์ค์ ๊ธฐ์กด ํํ์ ๋ฐ์ดํฐ ์ถ๊ฐ.
๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ก ๋ถ๋ถ ์ ๋ฐ์ดํธ์ POST๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ํ ์ฃผ์ฅ์ด ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
DRF๊ฐ ์์ ํ ์ค์๋ฅผ ์ด๋งํ์ง ์๋๋ผ๋ ์ฌ์ PUT ์์ (์ฆ, ์ ์ฒด ๊ฐ์ฒด ๊ต์ฒด)๊ณผ ํธํ๋๋ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ํ์ํฉ๋๋ค. ๊ฐ์ฅ ๊ฐ๋จํ(๊ทธ๋ฆฌ๊ณ ๊ฐ์ฅ ํผ๋์ค๋ฌ์ด) ๋๋ต์ ๋ชจ๋ ํ๋๋ฅผ ์๊ตฌํ๋ ๊ฒ์ ๋๋ค. ๋ํ PUT์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ถ๋ถ์ ์ด์ง ์์์ผ ํ๊ณ ๋ถ๋ถ ์ ๋ฐ์ดํธ๋ ๋ค๋ฅธ ํค์๋(PATCH ๋๋ POST)๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๊ณ ์ ์ํฉ๋๋ค.
์ฐ๋ฆฌ ์ฑ์ drf3.4.x๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ๋์ ์ฒซ ๋ฒ์งธ PUT ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒ ๊ฐ์ต๋๋ค. :)
<strong i="6">@cached_property</strong>
def _writable_fields(self):
return [
field for field in self.fields.values()
if (not field.read_only) or (field.default is not empty)
]
์ด๋ ๊ฒ ํ๋ฉด ๋ด .validated_data์ PUT ์์ฒญ์์ ์ ๊ณตํ์ง ์๊ณ ์ง๋ ฌ ๋ณํ๊ธฐ ๋ด์์ ์๋์ผ๋ก ์ ๊ณตํ์ง ์์ ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ฉ๋๋ค. ์ง๋ ฌ ๋ณํ๊ธฐ ์์ค์ default=
์์ ๊ฐ์ ๊ฒ์ํ์ต๋๋ค. ๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก ํน์ ํ๋๋ฅผ ์
๋ฐ์ดํธํ๋ ค๊ณ ํ๋ ๋์ ํด๋น ํ๋ ์ค ์ผ๋ถ๋ฅผ ํ๋์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ฎ์ด์๋๋ค.
์ฌ์ฉ์ ์ง์ ModelSerializer๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฏ๋ก ๋ฌธ์ ๋ฅผ ์ฝ๊ฒ ํด๊ฒฐํ ์ ์์ต๋๋ค.
@pySilver ์ต๊ทผ ๋๊ธ ๋ด์ฉ์ด ์ดํด๊ฐ ๋์ง ์์ต๋๋ค.
@rpkilby "๋ค์ ์์ฒญ์ ๋ฐ์... ๋ฉฑ๋ฑ์ฑ์ด ๊นจ์ง์ง ์๋๊ฐ?"
์๋์, ๊ฐ PUT ์์ฒญ์ ์ฌ๋ฌ ๋ฒ ๋ฐ๋ณต๋์ด ๋์ผํ ์ํ๊ฐ ๋ ์ ์๋ค๋ ์ ์์ ๋ฉฑ๋ฑ์์ ๋๋ค. ๊ทธ๋ ๋ค๊ณ ํด์ ์ํ์ ๋ค๋ฅธ ๋ถ๋ถ์ด ๊ทธ ๋์ ์์ ๋ ๊ฒฝ์ฐ ์ด๋ป๊ฒ๋ ์ฌ์ค์ ๋๋ค๋ ์๋ฏธ๋ ์๋๋๋ค.
๋ค์์ PUT
๋์์ ๋ํ ๋ช ๊ฐ์ง ๋ค๋ฅธ ์ต์
์
๋๋ค.
required=False
๋๋ default
๊ฐ ์๋ ํ๋๋ ํ์์
๋๋ค. (๊ธฐ์กด์)_absolute_ ์ ๋ต์ ์๋ค๋ ์ ์ ๋ถ๋ช ํ ํ์ง๋ง ํ์ฌ๋ก์๋ ๊ฐ์ฅ ์ค์ฉ์ ์ธ ํ๋์ ์ทจํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
POST
์์ฒญ์ ๋ํด ์ ๊ณตํ ํ์๊ฐ ์์ง๋ง ์ดํ์ PUT
์์ฒญ์ ๋ํด ์ ๊ณตํด์ผ ํ๋ ํ๋๊ฐ ์๋ ๊ฒฝ์ฐ ์ผ๋ถ ์ฌ์ฉ ์ฌ๋ก์์ ๋ฌธ์ ๊ฐ ๋ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ํ PUT-as-create
์์ฒด๊ฐ ์ ํจํ ์์
์ด๋ฏ๋ก POST์ ๋ค๋ฅธ "์๊ตฌ ์ฌํญ" ์๋ฏธ ์ฒด๊ณ๊ฐ ์๋ ๊ฒฝ์ฐ์๋ ์ด์ํฉ๋๋ค.
๋๊ตฐ๊ฐ๊ฐ ์ด๊ฒ์ ๋ฐ์ ์ํค๊ณ ์ถ๋ค๋ฉด ๋๋ _๊ฐ๋ ฅํ๊ฒ_ ๋ค์ํ ๊ธฐ๋ณธ ์ง๋ ฌ ๋ณํ๊ธฐ ํด๋์ค๋ฅผ ๊ตฌํํ๋ ํ์ฌ ํจํค์ง๋ก ์์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ง๋ ฌ ๋ณํ๊ธฐ ์ค๋ช ์์์ ํด๋น ํญ๋ชฉ์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. ์ฌ๋ก๊ฐ ์ ๋ง๋ค์ด์ง๋ฉด ๋ฏธ๋์ ์ด๋ ์์ ์์ ๊ธฐ๋ณธ ๋์์ ์กฐ์ ํ๋ ๊ฒ์ ๊ณ ๋ คํ ์ ์์ต๋๋ค.
@tomchristie ๋ด๊ฐ ๋งํ๊ณ ์ถ์ ๊ฒ:
์ฝ๊ธฐ ์ ์ฉ language
ํ๋์ ๋ชจ๋ธ์ด ์๋ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ์์ต๋๋ค.
class Book(models.Model):
title = models.CharField(max_length=100)
language = models.ChoiceField(default='en', choices=(('pl', 'Polish'), ('en', 'English'))
class BookUpdateSerialzier(serializers.ModelSerializer):
# language is readonly, I dont want to let users update that field using this serializer
language = serializers.ChoiceField(default='en', choices=(('pl', 'Polish'), ('en', 'English'), read_only=True)
class Meta:
model = MyModel
fields = ('title', 'language', )
book = Book(title="To be or 42", language="pl")
book.save()
s = BookUpdateSerialzier(book, data={'title': 'Foobar'}, partial=True)
s.is_valid()
assert 'language' in s.validated_data # !!!
assert 'pl' == s.validated_data # AssertionError... here :(
language
๋ฅผ ์ ๋ฌํ์ง ์์๊ณ ๊ฒ์ฆ๋ ๋ฐ์ดํฐ์์ ์ด๊ฒ์ ๋ณผ ๊ฒ์ผ๋ก ๊ธฐ๋ํ์ง ์์ต๋๋ค. update
์ ์ ๋ฌ๋๋ฉด ๊ฐ์ฒด์ ์ด๋ฏธ ๊ธฐ๋ณธ๊ฐ์ด ์๋ ๊ฐ์ด ํ ๋น๋์ด ์์์๋ ๋ถ๊ตฌํ๊ณ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๋ด ์ธ์คํด์ค๋ฅผ ๋ฎ์ด์๋๋ค.validated_data['language']
๊ฐ book.language
์ด๋ฉด ๋ฌธ์ ๊ฐ ๋ํ ๊ฒ์
๋๋ค.@pySilver - ์, ์ค๋ ๋ฐ๋ก https://github.com/tomchristie/django-rest-framework/pull/4346 ์์ ํด๊ฒฐ๋์์ต๋๋ค.
$ ModelField
์ ๊ธฐ๋ณธ๊ฐ์ด ์์ผ๋ฏ๋ก ๊ฐ์ง๊ณ ์๋ ์์ ์ ์ง๋ ฌ ๋ณํ๊ธฐ ํ๋์ default=
์ด ํ์ํ์ง ์์ต๋๋ค.
@tomchristie ์ต์ํ ํ์ฌ PUT ๋์์ด RFC ์ฌ์์ด ์๋๋ผ๋ ๋ฐ ๋์ํ์ญ๋๊น? ๊ทธ๋ฆฌ๊ณ ๋ด ์ ์(๋ชจ๋ ์๊ตฌ ๋๋ ๊ธฐ๋ณธ๊ฐ ์ฝ์ )์ด ๋ชจ๋ ๊ทธ๋ ๊ฒ ํ ๊ฒ์ด๋ผ๊ณ ์?
@tomchristie ์ข์ ์์์ ๋๋ค!
ModelField์ ๊ธฐ๋ณธ๊ฐ์ด ์์ผ๋ฏ๋ก ๊ฐ์ง๊ณ ์๋ ์์ ์ ์ง๋ ฌ ๋ณํ๊ธฐ ํ๋์ default=๊ฐ ํ์ํ์ง ์์ต๋๋ค.
์, ๋ฐ๋ชจ์ฉ์ผ๋ก ๋งค์ฐ ๋ช ์์ ์ผ๋ก ๋ง๋ค๊ณ ์ถ์์ต๋๋ค.
@tomchristie ๊ฐ ์ง๋ ฌ ๋ณํ๊ธฐ ๋์์ ๋ํด ๋ฐ๋ก ๋ ผ์ํ์ง ์๋๋ค๋ ์ ์์ ๋ง์นจ๋ด ๊ฐ๋ผ์๊ณ ์์ต๋๋ค. ๋๋ ๊ทธ์ ๋ฐ๋๊ฐ (์์์ ์ผ๋ก) ๋จ์ผ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ๋ชจ๋ REST ๋ชจ๋๋ฅผ ์ง์ํด์ผ ํ๋ค๋ ์๊ตฌ ์ฌํญ์์ ๋น๋กฏ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ด๊ฒ์ ์๊ฒฉํ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ POST์ ์ํฅ์ ๋ฏธ์น๋ ๋ฐฉ์์ ๋ํ ๊ทธ์ ๋ถ๋ง์์ ๋ํ๋ฉ๋๋ค. REST ๋ชจ๋๋ ํธํ๋์ง ์์ผ๋ฏ๋ก ํ์ฌ ์๋ฃจ์ ์ ๋จ์ผ ๋ชจ๋์ ๋ํ ์ฌ์์ด ์๋ ์ง๋ ฌ ๋ณํ๊ธฐ์ ๋๋ค.
๊ทธ๊ฒ์ด ์ด์ ์ ๊ธฐ์ ์ง์ ํ ๊ทผ์์ด๋ผ๋ฉด ์ ๋ฉด์ผ๋ก ๋ฐ์๋ค์ด๋๋ก ํฉ์๋ค. ๋จ์ผ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ์ด๋ป๊ฒ ๋ชจ๋ REST ๋ชจ๋์ ๋ํ ์ฌ์ ๋์์ ์ ๊ณตํ ์ ์์ต๋๊น? ๋ด ๋๋ต์ PARTIAL ๋ NON-PARTIAL์ด ์๋ชป๋ ์์ค์์ ๊ตฌํ๋๋ค๋ ๊ฒ์ ๋๋ค.
๋ฌธ์ ๋ฅผ ๋ถ๋ฆฌํ๊ธฐ ์ํด ์ง๋ ฌ ๋ณํ๊ธฐ๋ REST ๋ชจ๋๋ฅผ ์์ง ๋ชปํ๋ฏ๋ก ํ์ฌ ์ง๋ ฌ ๋ณํ๊ธฐ๋ก ๊ตฌํํ ์ ์์ต๋๋ค. ๋์ DRF๋ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ง๋ ฌ ๋ณํ๊ธฐ์ ์ ๋ฌํด์ผ ํฉ๋๋ค(๋๋ต replace=True
PUT
). ์ง๋ ฌ ๋ณํ๊ธฐ๋ ์ด๊ฒ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํ ์ ์์ต๋๋ค(๋ชจ๋ ํ๋๊ฐ ํ์ํ๊ฑฐ๋ ๊ธฐ๋ณธ๊ฐ์ ์ฝ์
ํด์ผ ํจ).
๋ถ๋ช ํ ์ด๊ฒ์ ๋๋ต์ ์ธ ์ ์์ด์ง๋ง ๊ต์ฐฉ ์ํ๋ฅผ ๊นจ๋จ๋ฆด ์๋ ์์ต๋๋ค.
๋์ฑ์ด, PUT-as-create๋ ๊ทธ ์์ฒด๋ก ์ ํจํ ์์ ์ด๋ฏ๋ก POST์ ๋ค๋ฅธ "ํ์์ฑ" ์๋ฏธ ์ฒด๊ณ๋ฅผ ๊ฐ๋๋ค๋ฉด ์ด์ํ ๊ฒ์ ๋๋ค.
PUT์ผ๋ก ์์ฑํ ์ ์๋ค๋ ์ ์๋ ๋์ํ์ง๋ง ์๋ฏธ๋ก ์ด ๋์ผํ๋ค๋ ์ ์๋ ๋์ํ์ง ์์ต๋๋ค. PUT
๋ ํน์ ๋ฆฌ์์ค์์ ์๋ํฉ๋๋ค.
PUT ๋ฉ์๋๋ ๋์ ๋ฆฌ์์ค์ ์ํ๊ฐ ์์ฑ๋๊ฑฐ๋ ์์ฒญ ๋ฉ์์ง ํ์ด๋ก๋์ ํฌํจ๋ ํํ์ ์ํด ์ ์๋ ์ํ๋ก ๋์ฒด๋๋๋ก ์์ฒญํฉ๋๋ค.
๋ฐ๋ผ์ ์๋ฏธ ์์ฑ์ด ์ค์ ๋ก ๋ค๋ฅด๋ค๊ณ ์๊ฐํฉ๋๋ค.
/citizen/
์ SSN(์ฌํ ๋ณด์ฅ ๋ฒํธ)์ด ์์ฑ๋ ๊ฒ์ผ๋ก ์์ํฉ๋๋ค./citizen/<SSN>
๋ก ํน์ SSN์ ๋ํ ๋ฐ์ดํฐ๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค. ํด๋น SSN์ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ์์ฑ๋ฉ๋๋ค."id"๋ PUT์ URI์ ํฌํจ๋์ด์ผ ํ๋ฏ๋ก ํ์์ ๋ฐ๋ผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ๋์กฐ์ ์ผ๋ก "id"๋ POST์์ ์ ํ ์ฌํญ์ ๋๋ค.
"id"๋ PUT์ URI์ ํฌํจ๋์ด์ผ ํ๋ฏ๋ก ํ์์ ๋ฐ๋ผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ๋์กฐ์ ์ผ๋ก "id"๋ POST์์ ์ ํ ์ฌํญ์ ๋๋ค.
๋ฌผ๋ก . ๋๋ "PUT์ด _all_ ํ๋๋ฅผ ์๊ฒฉํ ์๊ตฌํ๋๋ก ํ๋ผ"์ ์ ์๋ ๋ณ๊ฒฝ์ด PUT-as-create๊ฐ POST-as-create wrt์ ๋ค๋ฅธ ๋์์ ๊ฐ์ง์ ์๋ฏธํ๋ค๋ ์ฌ์ค์ ๊ตฌ์ฒด์ ์ผ๋ก ์ธ๊ธํ๊ณ ์์์ต๋๋ค. ํ๋๊ฐ ํ์์ธ์ง ์ฌ๋ถ.
PUT-is-strict ํ๋์ ์ต์ ์ ๊ฐ๋ ๊ฐ์น์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค.
(์ด ๊ฒฝ์ฐ _all_ ํ๋๊ฐ ์๊ฒฉํ๊ฒ ํ์์์ ์ ์ฉํ๊ณ , PATCH์์ _no_ ํ๋๊ฐ ํ์์์ ์ ์ฉํ๊ณ , POST์ required=
ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ์ญ์์ค.)
๋จ์ผ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ์ด๋ป๊ฒ ๋ชจ๋ REST ๋ชจ๋์ ๋ํ ์ฌ์ ๋์์ ์ ๊ณตํ ์ ์์ต๋๊น?
์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ์ธ์คํด์คํ๋๋ ๋ฐฉ์์ ๋ฐ๋ผ ์์ฑ, ์ ๋ฐ์ดํธ ๋ฐ ๋ถ๋ถ ์ ๋ฐ์ดํธ๋ฅผ ๊ตฌ๋ณํ ์ ์์ผ๋ฏ๋ก ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค๊ณ ์๊ฐํฉ๋๋ค.
PUT
๋๋ POST
$ ๋ฅผ ์ฌ์ฉํ์ฌ create
ํ ์ ์๋ค๋ ์ ์ ์ด๋ฏธ ์ง์ ํ์ต๋๋ค. ์๋ฏธ ์ฒด๊ณ์ ์๊ตฌ ์ฌํญ์ด ๋ค๋ฅด๋ฏ๋ก create
๋ REST ๋ชจ๋์ ๋ํด ๋ถ๊ฐ์ง๋ก ์ ์ด์ด์ผ ํฉ๋๋ค. ๋๋ ๊ตฌ๋ณ์ด ์ค์ ๋ก is_valid
์ ์ผ๋ถ๋ก ๋ฐ์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ํน์ ์ ํจ์ฑ ๊ฒ์ฌ ๋ชจ๋๋ฅผ ์์ฒญํฉ๋๋ค.
required
ํ๋๊ทธ ๊ธฐ๋ฐ ์ ํจ์ฑ ๊ฒ์ฌ(POST)ํค์๋๋ณ ๋ ผ๋ฆฌ๋ฅผ CRUD ์์ ์์ ์ ์ธํจ์ผ๋ก์จ ์ง๋ ฌ ๋ณํ๊ธฐ์ DRF ๊ฐ์ ๊ฒฐํฉ๋ ์ค์ ๋๋ค. ์ ํจ์ฑ ๊ฒ์ฌ ๋ชจ๋๋ฅผ ๊ตฌ์ฑํ ์ ์๋ ๊ฒฝ์ฐ ์์ ํ ๋ฒ์ฉ์ด ๋ฉ๋๋ค(3๊ฐ์ ํค์๋์ ๋ํด 3๊ฐ์ ํน์ ๊ฒฝ์ฐ๋ง ๊ตฌํํ๋๋ผ๋).
์ด ๊ธฐ๋ฅ์ ๋ํด ์ ์ค๋ช ํ๊ณ ์์ต๋๋ค. :)
.is_valid()๋ฅผ ํธ์ถํ ๋ "์ ํจ์ฑ ๊ฒ์ฌ ๋ชจ๋"๊ฐ ๋ค๋ฅด๋ค๋ ๊ฒ์ ์ผ์ด๋์ง ์์ ๊ฒฉ๋ณ์ ๋๋ค.
์ฐ๋ฆฌ๋ ์๋ง๋ ๊ธฐ์กด์ 'partial=True' ๋จ์ kwarg์ ๋์ํ๋ 'complete=True'๋ฅผ ๊ณ ๋ คํ _์_ ์์ต๋๋ค_. ๊ทธ๊ฒ์ ํ์ฌ ์๋ํ๋ ๋ฐฉ์์ ์ถฉ๋ถํ ์ฝ๊ฒ ๋ง๊ณ "์๊ฒฉํ ํ๋"์ ๊ฒฝ์ฐ๋ฅผ ๊ณ์ ์ง์ํ ๊ฒ์ ๋๋ค.
์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์ ํฉํ ์ฅ์์ ๋๊น? ์ด ์๊ตฌ ์ฌํญ์ REST ํค์๋์ ๋ฐ์ ํ๊ฒ ์ฐ๊ฒฐ๋์ด ์์ผ๋ฏ๋ก ์ ์ฉํ๊ธฐ์ ์ ํฉํ ์์น์ผ ์ ์์ต๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ์ง์ํ๋ ค๋ฉด ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ์ ๋ ฅ์ผ๋ก ํ์ฉํ๋ ํ๋ ๋ชฉ๋ก๋ง ๋ ธ์ถํ๋ฉด ๋ฉ๋๋ค.
์ ์ณ๋๊ณ ... Django์ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ (ํ ๋น)์ ๋ํ ์ข์ ๋ ผ์๊ฐ ์ด๋๊ฐ์ ์์ต๋๊น? "์ ์ ํจ์ฑ ๊ฒ์ฌ๊ฐ ์ง๋ ฌํ์ ์ผ๋ถ์ธ์ง"์ ๊ฐ์ ์ง๋ฌธ์ ๋ํ ๋ต๋ณ์ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ Django ์นํ์ ์ธ ๋ต๋ณ์ผ๋ก ์์ ์ ์ ํํ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. 1.9์ ์ง๋ ฌํ ๋ฌธ์์๋ ์ ํจ์ฑ ๊ฒ์ฌ์ ๋ํ ์ธ๊ธ์กฐ์ฐจ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๊ฒฉํ๊ฒ ์ฒซ ๋ฒ์งธ ์์น์์ ๋ค์๊ณผ ๊ฐ์ด ๋ณด์ ๋๋ค.
์ ํจ์ฑ ๊ฒ์ฌ์ ๋ํ ์ฑ ์์ด ์ฌ๋ผ์ง๋ฉด ์ง๋ ฌ ๋ณํ๊ธฐ๋ 100% ๋ถ๋ถ์ (๊ธฐ๋ณธ์ ์ผ๋ก)์ด ๋ ์ ์์ผ๋ฉฐ "์ฝ๊ธฐ ์ ์ฉ"๊ณผ ๊ฐ์ I/O ๊ท์น์ ํนํ๋ ์ ์์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ผ๋ก ๋น๋๋ ModelSerializer๋ ๋ค์ํ ๋ณด๊ธฐ๋ฅผ ์ง์ํฉ๋๋ค.
์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์ ํฉํ ์ฅ์์ ๋๊น?
์.
1.9์ ์ง๋ ฌํ ๋ฌธ์์๋ ์ ํจ์ฑ ๊ฒ์ฌ์ ๋ํ ์ธ๊ธ์กฐ์ฐจ ์์ต๋๋ค.
Django์ ๊ธฐ๋ณธ ์ ๊ณต ์ง๋ ฌํ๋ Web APIS์ ์ ์ฉํ์ง ์์ผ๋ฉฐ ์ค์ ๋ก ๊ณ ์ ์ฅ์น๋ฅผ ๋คํํ๊ณ ๋ก๋ํ๋ ๋ฐ ์ ํ๋ฉ๋๋ค.
๋น์ ์ Django์ DRF์ ์ํคํ
์ฒ ๊ฐ์ ์ ๋๋ณด๋ค ๋ ์ ์๊ณ ์์ผ๋ฏ๋ก ๋ฐฉ๋ฒ์ ๋ํด์๋ ๋น์ ์๊ฒ ๋งํด์ผ ํฉ๋๋ค. ํ์คํ init
kwarg๋ ๊ทธ๊ฒ์ ๋ํ ์ฌ๋ฐ๋ฅธ ๋๋์ ๊ฐ์ง๊ณ ์์ต๋๋ค... ์ง๋ ฌ ๋ณํ๊ธฐ๋ฅผ "์ฃผ๋ฌธํ"์ผ๋ก ์ฌ๊ตฌ์ฑํฉ๋๋ค. ์ ์ผํ ์ ํ ์ฌํญ์ "์ฆ์" ์ฌ๊ตฌ์ฑํ ์ ์๋ค๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ์ธ์คํด์ค๊ฐ ์ผํ์ฉ์ด๋ผ๊ณ ๊ฐ์ ํ๋ฏ๋ก ์ด๊ฒ์ ์ค์ํ ๋ฌธ์ ๊ฐ ์๋๋๋ค.
๋๋ ์ง๊ธ ์ด๊ฒ์ ๋๋ง์ผ์คํค(de-milestone)์ผ๋ก ํ ๊ฒ์ด๋ค. v3.7 ์ดํ์ ์ฌํ๊ฐํ ์ ์์ต๋๋ค.
์ฌ๋ฌ๋ถ์๊ฒ ๋ฌ๋ ค ์์ง๋ง ์ด๊ฒ์ด ๋์์ฑ ์ง์์ ์ถ๊ฐํ๊ธฐ ์ํ ํฐ์ผ์ด ์๋๋ผ๋ ์ ์ ๋ถ๋ช ํ ํ๊ณ ์ถ์ต๋๋ค. ์ค์ ๋ฌธ์ ๋ ๋จ์ผ ์ง๋ ฌ ๋ณํ๊ธฐ๊ฐ ํ์ฌ ์ํคํ ์ฒ์์ PUT๊ณผ POST๋ฅผ ๋ชจ๋ ์ฌ๋ฐ๋ฅด๊ฒ ๊ฒ์ฆํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ๋์์ฑ์ "์คํจํ ํ ์คํธ"๋ฅผ ์ ๊ณตํ์ต๋๋ค.
TL;DR Tom์ด ์ ์ํ ์์ ์ฌํญ ์์ ์์ํ์ฌ ์ด ๋ฌธ์ ๊ฐ ์ฐจ๋จ๋ ์ด์ ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
์์ฝํ๋ฉด ์ ์๋ ์๋ฃจ์
์ PUT
์์ฒญ์ ํ์ํ ๋ชจ๋ ํ๋๋ฅผ ๋ง๋๋ ๊ฒ์
๋๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์๋ (์ ์ด๋) ๋ ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
create
PUT
๋ฐ POST
๊ฐ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์ create ์
๋๋ค. PUT
์ ์ํ ์์ฑ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋นํ์ฑํ๋์ด ์์ผ๋ฏ๋ก ์ ์๋ ์์ ์ฌํญ์ด ์๋ ๊ฒ๋ณด๋ค ๋์ ์ ์์ต๋๋ค.PUT
์ ๋ชจ๋ ํ๋๋ฅผ ์๊ตฌํ ํ์๋ ์์ต๋๋ค(#3648, #4703์์ ๊ณต์ ํ๋ ๊ฐ์ ). nillable ํ๋๊ฐ ์์ผ๋ฉด None์ผ ์ ์์ต๋๋ค. ๊ธฐ๋ณธ๊ฐ์ด ์๋ ํ๋๊ฐ ์์ผ๋ฉด ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. PUT
๋ ์ค์ ๋ก POST
์ ๋์ผํ (๋ชจ๋ธ ํ์) ํ๋ ์๊ตฌ ์ฌํญ์ ๊ฐ์ต๋๋ค.์ง์ง ๋ฌธ์ ๋ #3648, #4703์์ ๋๋ฝ๋ ๋ฐ์ดํฐ์ ๊ธฐ๋ณธ ์ ์์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด๋ฉฐ ์ฌ๊ธฐ ์ ์ฌ๋ฐ๋ฅธ ์๋ฃจ์
์ด ๋จ์ ์์ต๋๋ค. if_missing_use_default
์ ๊ฐ์ ๊ฐ๋
์ ๋์
ํ๋ฉด ๋ชจ๋ HTTP ๋ชจ๋( PUT
ํฌํจ)๋ฅผ ์ง์ํ ์ ์์ต๋๋ค. ๋ด ์๋ ์ ์ ์ partial
์ ๋์ฒดํ์ผ๋ก ์ ์ํ์ง๋ง ์ง๊ต ๊ฐ๋
์ผ๋ก ์๊ฐํ๋ ๊ฒ์ด ๋ ์ฝ๊ณ ํ์ํ ์๋ ์์ต๋๋ค.
if_missing_use_default์ ๊ฐ์ ๊ฐ๋ ์ ๋์ ํ๋ค๋ฉด.
๋๊ตฐ๊ฐ๊ฐ ์ด๊ฒ์ ๊ตฌํํ๊ฑฐ๋ ์๊ฒฉํ "๋ชจ๋ ํ๋ ํ์"๋ฅผ ๊ธฐ๋ณธ ์ง๋ ฌ ๋ณํ๊ธฐ ํด๋์ค๋ก ๊ตฌํํ๊ณ ์ด๋ฅผ ํ์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋ํํ๋ ๊ฒ์ ๋ฐฉํดํ๋ ๊ฒ์ ์์ต๋๋ค.
๋ด ์๊ฐ์๋ ์๊ฒฉํ "๋ชจ๋ ํ๋ ํ์" ๋ชจ๋๋ ํต์ฌ์ผ๋ก ๋ง๋ค ์ ์์ผ๋ฉฐ, ์ด๋ ๋งค์ฐ ๋ถ๋ช ํ๊ณ ๋ช ๋ฐฑํ ๋์์ด๋ฉฐ ์ด๊ฒ์ด ์ ์ ์ฉํ์ง ์ ์ ์์ต๋๋ค.
๋๋ "ํ๋๋ฅผ ์ ํ ์ฌํญ์ผ๋ก ํ์ฉํ์ง๋ง ์กด์ฌํ๋ ๊ฒฝ์ฐ ๋ชจ๋ธ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๊ฒ์ ๊ต์ฒดํฉ๋๋ค"๋ผ๊ณ ํ์ ํ์ง ์์ต๋๋ค. ์ด๋ ๋งค์ฐ ์ง๊ด์ ์ด์ง ์์ ๋์(์: "created_at" ํ๋, ์๋์ผ๋ก ์ข ๋ฃ๋๋ ์ค์ค๋ก ์ ๋ฐ์ดํธ). ์ฐ๋ฆฌ๊ฐ ๋ ์๊ฒฉํ ํ๋์ ์ํ๋ค๋ฉด ๋ ์๊ฒฉํ ํ๋์ ์ทจํด์ผ ํฉ๋๋ค.
์ด๋ ์ชฝ์ด๋ , ์ด์ ์ ๊ทผํ๋ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ ํ์ฌ ํจํค์ง๋ก ์ ํจ์ฑ์ ๊ฒ์ฌํ ๋ค์ ํด๋น ํจํค์ง์ ์ฐ๊ฒฐํ ์ ์๋๋ก ๋ฌธ์๋ฅผ ์ ๋ฐ์ดํธํ๋ ๊ฒ์ ๋๋ค.
๋๋ ์ฌ์ฉ์์๊ฒ ์ ๋ง ํ์ํ ๋์์ด ์ฝ์ด์์ ๋๋ฝ๋์๋ค๊ณ ํ์ ํ๋ ๊ฒฝ์ฐ ํ ์์ฒญ์ ํ๊ณ ๋์ ๋ฐ ๋ฌธ์๋ฅผ ์ ๋ฐ์ดํธํ์ฌ ๋งค์ฐ ์ ์ํ๊ฒ ์ฅ์ ์ ํ๊ฐํ ์ ์์ต๋๋ค. ๊ตฌ์ฒด์ ์ธ ๋ฐฉ๋ฒ.
ํ ๋ฆฌํ์คํธ๋ฅผ ์ด๋ฅผ ์ํ ์ถ๋ฐ์ ์ผ๋ก ์ผ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค. ์ด ๋์์ ์์ฐํ๋ ํ์ฌ ํจํค์ง๋ฅผ ํฌํจํ๊ฒ ๋์ด ๋์ฑ ๊ธฐ์ฉ๋๋ค.
PUT-is-strict ํ๋์ ์ต์ ์ ๊ฐ๋ ๊ฐ์น์ ์ ๊ทผํฉ๋๋ค.
์ด๊ฒ์ ์ฌ์ ํ โโ์ ์ง๋ฉ๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ๊ทธ ๋ผ์ธ์ ๋ฐ๋ผ ํ ๋ฆฌํ์คํธ๋ฅผ ํ ๋งํผ ์ถฉ๋ถํ ์ ๊ฒฝ์ ์ด ๋ค๋ฉด ์ฐ๋ฆฌ๋ ๊ทธ ์ธก๋ฉด์ ํต์ฌ์ ์ผ๋ก ๊ณ ๋ คํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ ํ์ ๋์์ด์ด์ผ ํฉ๋๋ค.
๊ทธ๊ฒ์ ๋งค์ฐ ์ง๊ด์ ์ด์ง ์์ ๋์์ ๋ํ๋ด๋ ๊ฒ ๊ฐ์ต๋๋ค(์: ์๋์ผ๋ก ์ ๋ฐ์ดํธ๋๋ "created_at" ํ๋).
created_at
ํ๋๋ read_only
์ด์ด์ผ ํฉ๋๋ค(๋๋ ์ง๋ ฌ ๋ณํ๊ธฐ์์ ์ ์ธ). ์ด ๋ ๊ฒฝ์ฐ ๋ชจ๋ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค(์ผ๋ฐ ์ง๋ ฌ ๋ณํ๊ธฐ ๋์). ์ง๋ ฌ ๋ณํ๊ธฐ์์ ํ๋๊ฐ ์ฝ๊ธฐ ์ ์ฉ์ด ์๋ ์ง๊ด์ ์ด์ง ์์ ๊ฒฝ์ฐ ์๋์ผ๋ก ํ๋๋ฅผ ๋ณ๊ฒฝํ๋ ์ง๊ด์ ์ด์ง ์์ ๋์์ ์ป๊ฒ ๋ฉ๋๋ค.
ํ ๋ฆฌํ์คํธ๋ฅผ ์ด๋ฅผ ์ํ ์ถ๋ฐ์ ์ผ๋ก ์ผ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค. ์ด ๋์์ ์์ฐํ๋ ํ์ฌ ํจํค์ง๋ฅผ ํฌํจํ๊ฒ ๋์ด ๋์ฑ ๊ธฐ์ฉ๋๋ค.
์ ์ ์ผ๋ก. "๊ธฐ๋ณธ๊ฐ ์ฌ์ฉ" ๋ณํ์ ํ์ฌ ํจํค์ง์ ์ด์์ ์ธ ๊ฒฝ์ฐ์ ๋๋ค. ๋ณ๊ฒฝ ์ฌํญ์ ๊ธฐ์กด ๋์์ ๋ํ ๊ฐ๋จํ ๋ํผ(ํ ๊ฐ์ง ๋ฐฉ๋ฒ)์ด๊ณ (๊ธฐ๋ณธ ์ธ์๋ฅผ ๊ตฌ๋งคํ๋ ๊ฒฝ์ฐ) ๋ชจ๋ ๋น-๋ถ๋ถ ์ง๋ ฌ ๋ณํ๊ธฐ์ ๋ํด ์๋ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
tomchristie๊ฐ 4์๊ฐ ์ ์ ๋ซ์์ต๋๋ค.
์๋ง๋ "PR Welcome" ๋๋ "3rd Party Plugin"๊ณผ ๊ฐ์ ๋ ์ด๋ธ์ ์ถ๊ฐํ๊ณ ์ด์ ๊ฐ์ด ์ ํจํ/ํ์ธ๋ ๋ฌธ์ ๋ฅผ ์ด์ด ๋๋ ๊ฒ์ ๊ณ ๋ คํ ์ ์์ต๋๋ค. ๋๋ ์ข ์ข ๋ฌธ์ ๊ฐ ์ด๋ฏธ ๋ณด๊ณ ๋์๊ณ ํด๊ฒฐ ๊ณผ์ ์ด ์งํ ์ค์ธ์ง ํ์ธํ๊ธฐ ์ํด ๋ฏธํด๊ฒฐ ๋ฌธ์ ๋ฅผ ๊ฒ์ํฉ๋๋ค. ๋ซํ ๋ฌธ์ ๋ฅผ "์๋ชป๋" ๋๋ "๊ณ ์ ๋" ๊ฒ์ผ๋ก ์ธ์ํฉ๋๋ค. ๋ช ๊ฐ์ง "์ ํจํ์ง๋ง ๋ง๊ฐ๋" ๋ฌธ์ ๋ฅผ ์์ฒ ๊ฐ์ ์ ํจํ์ง ์๊ฑฐ๋ ์์ ๋ โโ๋ฌธ์ ์ ํผํฉํ๋ ๊ฒ์ ํจ์จ์ ์ธ ๊ฒ์์ ์ ๋ํ์ง ์์ต๋๋ค.
"PR Welcome" ๋๋ "3rd Party Plugin"๊ณผ ๊ฐ์ ๋ ์ด๋ธ์ ์ถ๊ฐํ๋ ๊ฒ์ ๊ณ ๋ คํ ์ ์์ต๋๋ค.
์ถฉ๋ถํ ํฉ๋ฆฌ์ ์ด์ง๋ง ๋ฌธ์ ์ถ์ ๊ธฐ๊ฐ ํ๋ก์ ํธ ์์ฒด์ ๋ํ ํ์ฑ ๋๋ ์คํ ๊ฐ๋ฅํ ์์ ์ ๋ฐ์ํ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
๋ฌธ์ ์ ๋ฒ์๋ฅผ ์๊ฒฉํ๊ฒ ์ ์งํ๋ ค๊ณ ๋ ธ๋ ฅํ๋ ๊ฒ์ด ์ ๋ง ์ค์ํฉ๋๋ค. ์ฐ์ ์์๋ฅผ ๋ณ๊ฒฝํ๋ค๋ ๊ฒ์ ์ด์ ์ ๋ซ์๋ ๋ฌธ์ ๋ฅผ ๋ค์ ์ด๊ฒ ๋ค๊ณ ์ ํํ๋ ๊ฒ์ ์๋ฏธํ ์ ์์ต๋๋ค . ์ง๊ธ ๋น์ฅ์ ์ด๊ฒ์ด "ํต์ฌ ํ์ด ๊ฐ๊น์ด ์ฅ๋์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ ํ๋ ๊ฒ"์์ ๋ฒ์ด๋ฌ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ๊ฒ์ด ๋ฐ๋ณต์ ์ผ๋ก ๋ํ๋๊ณ ์ 3์ ์๋ฃจ์ ์ด ๊ณ์ ์๋ค๋ฉด ์๋ง๋ ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ์ฌํ๊ฐํ ๊ฒ์ ๋๋ค.
์ด์ ๊ฐ์ด ์ ํจํ/ํ์ธ๋ ๋ฌธ์ ๋ฅผ ์ด์ด ๋ก๋๋ค.
๋ฌธ์ ๊ด๋ฆฌ ์คํ์ผ์ ๋ํ ์ถ๊ฐ ์ ๋ณด - https://www.dabapps.com/blog/sustainable-open-source-management/