ç·šéïŒåé¡ã®çŸåšã®ã¹ããŒã¿ã¹ã«ã€ããŠã¯ã httpsïŒ //github.com/encode/django-rest-framework/issues/4231#issuecomment-332935943ã«ã¹ãããããŠãã ãã
===
DRFã䜿çšããŠããŒã¿ããŒã¹ãšå¯Ÿè©±ããã¢ããªã±ãŒã·ã§ã³ã«OptimisticConcurrencyã©ã€ãã©ãªãå®è£ ããéã«åé¡ãçºçããŸããã ç§ãããããšããŠããããšïŒ
æè¿ãDjangoã¢ããªã±ãŒã·ã§ã³ã«æ¥œèŠ³çåæå®è¡æ§ãè¿œå ããŸããã Wikiã«ãã¯ã¢ãããä¿åããã«ã¯ïŒ
DRFãä»ããŠè©±ããŠããã¬ã¬ã·ãŒUIããããŸããã åŸæ¥ã®UIã¯ããŒãžã§ã³çªå·ãåŠçããŸããã§ããã ããã«ããåæå®è¡ãšã©ãŒãçºçãããšäºæ³ããŸããããããã§ã¯ãããŸããã§ããã ïŒ3648ã®è°è«ãæ£ããç解ããŠããå ŽåïŒ
æ¬ èœããŠããããŒãžã§ã³IDã¯ããŒã¿ããŒã¹ãšäžèŽããªããããåæå®è¡ã®åé¡ãçºçããŸãã
æ¬ èœããŠããããŒãžã§ã³IDã¯ãDRFã«ãã£ãŠçŸåšã®IDã§åãããããããåæå®è¡æ§ãã§ãã¯ã«åæ ŒããŸãã
ããŠã次ã®3.4ãªãªãŒã¹ãåªå ãããããããã®ããªã詳现ãªãã±ãããããã«ç¢ºèªã§ãããšã¯çŽæã§ããŸããã ãããããã®ããã«è©³çŽ°ã§ããèããããåé¡ã«æè¬ããŸãã ããã¯ãããããæ°æ¥ãæ°ãæã§ã¯ãªããæ°é±éã®ã¹ã±ãŒã«ã§èŠãããããã«ãªããŸãã äœãé²æ©ããã£ãããèªåã§ããã«èããŠã¿ãŠãã ããããã±ãããæŽæ°ããŠãç§ãã¡ã«ç¥ãããŠãã ããã
ããã£ãã ç§ã®åé¡ã¯2ã€ã®èŠå ã®çµã¿åããã§ãããšç¢ºä¿¡ããŠããŸãã
ãã®çµæã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ã«æè¬ããŸãã ããã¯ç§ãæ¬çªãã©ã³ãã«çããŠãããŸãã
ãå¯ããåŸãäœåãªãããããããšã«æ°ã¥ããŸããã ç§ãèšã£ãããšã¯ãã¹ãŠãã·ãªã¢ã©ã€ã¶ãŒã®ãã£ãŒã«ãã«åœãŠã¯ãŸãã¯ãã§ãã ãã£ãŒã«ããã·ãªã¢ã©ã€ã¶ãŒã«å«ãŸããŠããªãå Žåã¯ãå€æŽããªãã§ãã ããã ãã®ããã«ããã¹ãŠã®ã»ãªã©ã€ã¶ãŒã¯ãå«ãŸããŠããªããã£ãŒã«ãã«å¯ŸããŠéšåçã§ãïŒãããŠéšåçã§ããå¿ èŠããããŸãïŒã ããã¯ãäžèšã®ãæ°ããã€ã³ã¹ã¿ã³ã¹ãäœæããããããå°ãè€éã§ãã
åé²ããããã«ã¯ããã®åé¡ãããå¶çŽã®ããææ¡ã«æžããå¿
èŠããããšæããŸãã
çŸåšã®ç¶æ
ã§å®è¡å¯èœã§ãããšåºãæãããŸãã
ä»ã®ãšããç§ã¯ãããéããŠããŸã-誰ãããããæãŸããè¡åã®ç°¡æœã§å®çšçãªã¹ããŒãã¡ã³ãã«æžããããšãã§ããã°ãç§ãã¡ã¯åèããããšãã§ããŸãã ãããŸã§ã¯ãåçŽã«åºããããšã ãšæããŸãã
ãããç°¡æœãªææ¡ã§ã...ééšåçãªã·ãªã¢ã©ã€ã¶ãŒã®å ŽåïŒ
blank
ããã³/ãŸãã¯null
ã«ãã£ãŠç€ºãããå€ãå«ããããã©ã«ããå
¥åããŸãæ確ã«ããããã«ãæ€èšŒã¯ãã®ããã»ã¹ã®æçµè£œåã§å®è¡ãããŸãã
ã€ãŸããæŽæ°ã®ããã«ãã¢ãã«ã®ããã©ã«ãããªãã·ãªã¢ã©ã€ã¶ãŒãã£ãŒã«ãã«required=True
ãèšå®ããŸããïŒ
ç§ã¯ãããæ£ããç解ããŸãããïŒ
ã¯ãïŒããã³ãã以äžïŒã ãããã partial
ïŒãã¹ãŠã®ãã£ãŒã«ãã¯ãªãã·ã§ã³ïŒãšnon-partial
ïŒãã¹ãŠã®ãã£ãŒã«ããå¿
é ïŒã®éããç解ããæ¹æ³ã§ãã non-partial
ã·ãªã¢ã©ã€ã¶ãŒããã£ãŒã«ããå¿
èŠãšããªãã®ã¯ãããã©ã«ãïŒç矩ãŸãã¯åºçŸ©ïŒãååšããå Žåã®ã¿ã§ãã_å€ãæå®ãããŠããªãå Žåãã·ãªã¢ã©ã€ã¶ãŒã¯ãã®ããã©ã«ãã䜿çšã§ããããã§ãã_
ã€ã¿ãªãã¯äœã®ã»ã¯ã·ã§ã³ã¯ãDRFãçŸåšè¡ã£ãŠããªãããšã§ãããç§ã®ææ¡ã«ãããããéèŠãªå€æŽã§ãã çŸåšã®å®è£ ã§ã¯ããã£ãŒã«ããã¹ãããããã ãã§ãã
ç§ã¯2çªç®ã®ææ¡ãæ··ãåãããŸããããããã¯å®éã«ã¯ããããã©ã«ããã®ã¢ã€ãã¢ã§ã©ãã ãå¯å€§ã«ãªãããããšããå¥ã®è³ªåã§ãã çŸåšã®åäœã¯ã 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ãã·ãªã¢ã©ã€ã¶ãŒã«ããŒãã³ãŒãã£ã³ã°ããŸããã 競åç¶æ ããããããããã¯ééã£ãå Žæã§ãã ïŒåã以åã®ããŒãžã§ã³ã®ïŒäžŠåæŽæ°ã¯ãã¹ãŠã·ãªã¢ã©ã€ã¶ãŒã§æž¡ãããŸã...ããããä¿åã¢ã¯ã·ã§ã³ã§åã€ã®ã¯1ã€ã ãã§ãã
ç§ã¯django-concurrency
ã䜿çšããŠããŸããããã¯ãOOLããžãã¯ãä¿åã¢ã¯ã·ã§ã³ïŒãããå±ããå ŽæïŒã«é
眮ããŸãã åºæ¬çã«UPDATE... WHERE version = submitted_version
ã ããã¯ã¢ãããã¯ã§ããããã競åç¶æ
ã¯ãããŸããã ãã ããã·ãªã¢ã«åããžãã¯ã®æ¬ é¥ãæããã«ãªããŸãã
required=False
ãèšå®ããŸãã ïŒæå¹ãªïŒèãæ¹ã¯ãå€ãéä¿¡ãããªãå ŽåãDRFã¯ãã®ããã©ã«ãã䜿çšã§ãããšãããã®ã§ãããã£ãŒã«ããäžèŠãªå Žåã¯ãããã©ã«ãã§äœ¿çšãããããå¿ èŠã«ãªããŸãã DRFã¯ããã©ã«ãã䜿çšããªãããããã®å¥çŽãå±¥è¡ããŸãã...æ¢åã®å€ã䜿çšããŸãã
æ ¹æ¬çãªåé¡ã«ã€ããŠã¯åã«èª¬æããŸããããå ·äœçãªäºäŸã¯ãããŸããã§ããã OOLã¯ãã®çæ³çãªã±ãŒã¹ã§ãã ããŒãžã§ã³ãã£ãŒã«ãã®æ¢åã®å€ã¯åžžã«OOLãæž¡ããããããŒãžã§ã³ãé€å€ããããšã§OOLã·ã¹ãã å šäœããã€ãã¹ã§ããŸãã ããã¯ïŒæããã«ïŒOOLã·ã¹ãã ã®æãŸããåäœã§ã¯ãããŸããã
@claytondaley
OOLãã·ãªã¢ã©ã€ã¶ãŒã«ããŒãã³ãŒãã£ã³ã°ããŸããã
ç§ã¯ããŸãããïŒ ãã£ãŒã«ãèŠä»¶ã®ã»ãã«ãç§ã®ã·ãªã¢ã©ã€ã¶ãŒã«OOLããžãã¯ãèŠã€ããŸãããïŒ
競åç¶æ ããããããããã¯ééã£ãå Žæã§ãã
ç³ãèš³ãããŸããããããã§ã®ç«¶åç¶æ ãã©ãã«ããã®ãããããŸããã
ç§ã¯ãOOLããžãã¯ãïŒãããå±ããå Žæã®ïŒä¿åã¢ã¯ã·ã§ã³ã«å ¥ããdjango-concurrencyã䜿çšããŠããŸãã
ç§ãdjango-concurrency
ã䜿çšããŠããŸã:)ããããããã¯ã¢ãã«ã¬ãã«ã§ãããã·ãªã¢ã©ã€ã¶ãŒã§ã¯ãããŸããã ã·ãªã¢ã©ã€ã¶ãŒã¬ãã«ã§ã¯ã次ã®ããšãè¡ãå¿
èŠããããŸãã
å®éãautorããä¿®æ£ãããªãããšããŒã¯ãããåé¡ã®ããã«django-concurrency
ã䜿çšããŠããŸããã obj.save(update_fields=['one', 'two', 'tree'])
ã䜿çšããããšOOLããã€ãã¹ããŸãããããã¯æªãç¿æ
£ã§ããããšãããã£ãã®ã§ãããã±ãŒãžããã©ãŒã¯ããŸããã
ããããåè¿°ã®ã·ãªã¢ã©ã€ã¶ãŒã®æ¬ èœããŠãã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ãã£ãŒã«ãã¯ãèãããããã¹ãŠã®å Žåã«åžžã«æ£ããå¿ èŠã§ãã
ãšããã§ãç§ã¯ã¢ãã«ã¬ãã«ã®ã³ãŒããhttps://github.com/gavinwahl/django-optimistic-lockããåããã®ã§ãã£ãŠã django-concurrency
ããåããã®ã§ã¯ãªããã»ãšãã©çç±ããªãè€éã«ãªã£ãŠããããšãããããŸããã
...ãããã£ãŠããã°ã¯ãééšåçãªã·ãªã¢ã©ã€ã¶ãŒãäžéšã®ãã£ãŒã«ãã誀ã£ãŠäžèŠã«èšå®ãããããšã§ãã ããã代æ¿æ段ã§ãã ããã¯ãééšåçãªã·ãªã¢ã©ã€ã¶ãŒãè¡ãïŒæé»ã®ïŒã³ãããã¡ã³ãã ããã§ãã
ç§ã¯ãããåŒçšããããšãã§ããŸãïŒ
ããã©ã«ãã§ã¯ãã·ãªã¢ã©ã€ã¶ãŒã«ã¯ãã¹ãŠã®å¿ é ãã£ãŒã«ãã®å€ãæž¡ãå¿ èŠããããŸããããããªããšãæ€èšŒãšã©ãŒãçºçããŸãã
ããã¯å¿ é ã«ã€ããŠã¯äœãèšããŸããïŒããã©ã«ããæäŸãããŠããå Žåãé€ãïŒã
ïŒãããŠãç§ã¯2ã€ã®ç°ãªãã¬ãã«ã«ã€ããŠè©±ããŠãããšæããŸãããModelSerializerããã®æ±ºå®ã«è²¬ä»»ãè² ããªãå Žåã¯ããã£ãŒã«ãã®èŠä»¶ã解é€ããã¹ãã§ã¯ãããŸããïŒ
ç§ã¯ããªãã®ãã€ã³ãã倱ã£ããšæããŸãã
ïŒãããŠãç§ã¯2ã€ã®ç°ãªãã¬ãã«ã«ã€ããŠè©±ããŠãããšæããŸãããModelSerializerããã®æ±ºå®ã«è²¬ä»»ãè² ããªãå Žåã¯ããã£ãŒã«ãã®èŠä»¶ã解é€ããã¹ãã§ã¯ãããŸããïŒ
ããã®äœããããªãã®ïŒ
OKãå¥ã®è§åºŠã§è©ŠããŠã¿ãŸãããã
åãããŒã¿ã䜿çšããCREATEãŸãã¯UPDATEã§ãç°ãªããªããžã§ã¯ãïŒIDãé€ãïŒãçæãããå Žå
ããã€ãã®éåžžã«åçŽãªã¢ãã«ãšã·ãªã¢ã©ã€ã¶ãŒãããã³å€±æãã/äºæ³ãããåäœã瀺ãæ°è¡ã䜿çšããŠãã¢ã€ãã¢ã説æã§ããŸããïŒ
ææ¥ã¯ããã§é ããªã£ãŠããã®ã§ãäœãããŸãšããŸã...ããããæ·±ããªãã»ã©ãïŒ3648ã¯ééšåçãªã·ãªã¢ã©ã€ã¶ãŒã«ãªããŸãã ãããŸã§ã®éãModelSerializerãã¢ãã«å ã®ãã¹ãŠã®ãã£ãŒã«ããå¿ èŠãšããªãã®ã¯ãªãã§ããïŒ ãã¶ãããªãã®è«ççæ ¹æ ã¯ç§ã®ãã®ãšã¯ç°ãªããŸãã
ModelSerializerã¯ãå¶éãããã¢ãã«ãæ€æ»ãããããå¿ èŠãã©ãããå€æããŸããã
ç§ã¯æ©æ¢°çã«ã©ã®ããã«æå³ããã®ã§ã¯ãããŸããã ééšåã·ãªã¢ã©ã€ã¶ãŒã®åºæ¬çãªåæã¯ããã¹ãŠãèŠæ±ããããšã§ãïŒäžèšã§åŒçšïŒã get_field_kwargs
ããã®ä»®å®ïŒå
·äœçã«ã¯ããïŒããéžè±ããå Žåã¯ãæ£åœãªçç±ãããã¯ãã§ãã ãã®çç±ã¯äœã§ããïŒ
ç§ã®å¥œã¿ã®çãã¯ããå€ãéä¿¡ãããªãå Žåã¯ãã®ããã©ã«ãã䜿çšã§ãããããïŒãã ããDRFã¯å®éã«ããã©ã«ãã䜿çšããå¿ èŠãããããïŒç§ãæäŸãç¶ãããã®ã§ãã ç§ãèŠéããŠããå¥ã®çãã¯ãããŸããïŒ ããã©ã«ãã®ãã£ãŒã«ããäžèŠãªçç±ã¯äœã§ããïŒ
æããã«ãç§ã¯ãå®å šãªããœãªã¥ãŒã·ã§ã³ã奜ã¿ãŸãã ããããç§ã¯2çªç®ã®çããããããšãèªããŸãã ããã©ã«ãã§ãããã®ãã£ãŒã«ããèŠæ±ã§ããŸãã ããã«ãããïŒçŸåšã¯ä»»æã®ïŒç¹æ®ãªã±ãŒã¹ãæé€ãããŸãã ã³ãŒããç°¡çŽ å/åæžããŸãã ããã¯å éšçã«äžè²«ããŠããŸãã ããã¯ç§ã®æžå¿µã«å¯ŸåŠããŸãã
åºæ¬çã«ãããã¯ééšåçãªã·ãªã¢ã©ã€ã¶ãŒãæ¬åœã«ééšåçã«ããŸãã
ä»ãç§ã¯å°ãªããšãããªããäœãæå³ããã®ããç¥ã£ãŠããŸãã ãã®ãããªå Žåã®ModelFormã®åäœã確èªããŸãããïŒ ïŒã¢ãã€ã«ã§ã¯èªåã§ãããè¡ãããšã¯ã§ããŸããïŒ
Djangoã®ããã¥ã¡ã³ãã«ãããšãã空çœãã¯ãã£ãŒã«ããå¿ é ãã©ãããå¶åŸ¡ããŸãã ãã®åé¡ã«ã¯ç¡é¢ä¿ãªã³ã¡ã³ããããããå«ãŸããŠããããããã®åé¡ã«ã€ããŠã¯å¥ã®ãã±ãããéãããšããå§ãããŸãã ç§ã®æèŠã§ã¯ãmodelserializerã¯modelformã®ããã«æ©èœããå¯èœæ§ããããŸãã空çœã®ãªãã·ã§ã³ã³ã³ãããŒã«ãå¿ èŠã§ãããnullãã¯Noneãåãå ¥ãå¯èœãªå ¥åã§ãããã©ããã瀺ãããdefaultãã¯ãã®ããžãã¯ã«åœ±é¿ãäžããŸããã
2ã€ç®ã®ãã±ãããéãã€ããã§ããã空çœã«åæ§ã®ã³ãŒããå¿ èŠã«ãªãã®ã§ã¯ãªãããšå¿é ããŠããŸãã 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ã«ã¯ãããã©ã«ããããå Žåã§ãããã®å ¥åãå¿ èŠã§ãã ããã¯ãå éšçã«äžè²«æ§ã®ãã2ã€ã®åäœã®1ã€ã§ãã
å¿ èŠãªç¶æ ãã¢ãã«ãã£ãŒã«ãã®ããã©ã«ãããããã£ã«äŸåããã®ã¯ãªãã§ããïŒ
ç°¡åã«èšããšãã¢ãã«ãã£ãŒã«ãã«ããã©ã«ããããå Žåã¯ãå ¥åãšããŠã®æäŸãçç¥ã§ããŸãã
@tomchristieã¯ååçã«åæããŸãã ããããæåŸ ãããåäœã¯äœã§ããïŒ
æŽæ°æã«ãããã©ã«ããååŸããå¿ èŠãããããã«æãããŸãã ééšåã·ãªã¢ã©ã€ã¶ãŒã2ã€ã®ã±ãŒã¹ã§ç°ãªãåäœãããçç±ãããããŸããã ééšåçãšã¯ããå®å šãªãã¬ã³ãŒããéä¿¡ããŠããããšãæå³ããŸãã ãããã£ãŠãå®å šãªã¬ã³ãŒãã眮ãæããå¿ èŠããããŸãã
æŽæ°æã«æäŸãããªãå Žåãå€ã¯å€æŽãããªããšæããŸãã èŠç¹ã¯ããããŸãããããã©ã«ãå€ã§ééçã«äžæžããããšãPOVããã¯çŽæã«åããŸãã
ïŒã©ã¡ãããšããã°ããã¹ãŠã®æŽæ°ããã¹ãŠã®ãã£ãŒã«ãã®éšåçãªã»ãã³ãã£ã¯ã¹ã§ããæ¹ãå®éã«ã¯ããããè¯ããšæããŸã-PUTã¯äŸç¶ãšããŠã¹ãçã§ãããããã¯éèŠãªåŽé¢ã§ãããçŸåšã®åäœãå€æŽããã®ã¯ããããåä»ã§ãïŒ
ç§ã¯ç¢ºãã«ããªãã®å¥œã¿ãå ±æããŸããã æå³çã«å¥ã®æ¹æ³ã§äœæããªãéãããã¹ãŠã®ã€ã³ã¿ãŒãã§ã€ã¹ãå³å¯ã«ããããšæããŸãã ãã ããPARTIALãšNON-PARTIALã®åºå¥ã¯ãïŒçè«çã«ã¯ïŒäž¡æ¹ãå¿ èŠãšãããã®ããã§ã«æäŸããŠããŸãã
ç§ã¯éšåçã«ããªããæãããã«æ£ç¢ºã«æ¯ãèããšä¿¡ããŠããŸãïŒ
default
ãšblank
ïŒè«çäŸå€ïŒã«é¢ããŠéšåçã§ãã ä»ã®ãã¹ãŠã®å Žåãã¢ãã«/ããŒã¿ããŒã¹ã®å¶çŽããã€ã³ããããŸããééšåã·ãªã¢ã©ã€ã¶ãŒã§äžè²«æ§ã確ä¿ããããšããŠããŸãã default
ã®ç¹æ®ãªã±ãŒã¹ãæé€ãããšãæ¢åã®ééšåã·ãªã¢ã©ã€ã¶ãŒãå³å¯ãªã·ãªã¢ã©ã€ã¶ãŒã«ãªããŸãã ãŸããModelFormãšåçã«ãªããŸãã
ããã«ãããããžã§ã¯ãå ã«å°ããªäžé£ç¶æ§ãçããããšã¯ããã£ãŠããŸããã誰ãããã®ãããªå€æŽãå ããã®ã¯ãããåããŠã§ã¯ãããŸããã çŸåšã®åäœã«ããã©ã«ãèšå®ãããŠãããã¬ã¬ã·ãŒããã©ã°ãè¿œå ããèŠåïŒããã©ã«ãã®åäœãå€æŽãããããšïŒãè¿œå ããåŸç¶ã®ã¡ãžã£ãŒãªãªãŒã¹ã§ããã©ã«ããå€æŽããŸãã
ããã«éèŠãªããšã«ãã·ãªã¢ã©ã€ã¶ãŒãDjangoã®æ°ããäºå®äžã®ãã®ã«ãããå Žåã¯ããšã«ãããã®å€æŽãè¡ãããšã«ãªããŸãã ModelFormããå€æãã人ã®æ°ã¯ãæ¢åã®ãŠãŒã¶ãŒããŒã¹ãå€§å¹ ã«äžåããå°ãªããšããã®å€æŽãæåŸ ããŸãã
ç§ã®2ã»ã³ããæ¿å
¥ããïŒ
@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'}
ãå«ãŸããŸãã 2åç®ã®PUTã®åŸã {'username': 'curly', 'role': 'admin'}
ã«ãªããŸãã ããã¯ã¹ãçæ§ãå£ããŸãããïŒ ïŒç§ã¯å®å
šã«ã¯ããããŸãã-åæ³çã«å°ããŠããŸãïŒ
ç·šéïŒ
PATCHã®ã»ãã³ãã£ã¯ã¹ã«ã€ããŠã¯èª°ããåãããŒãžã«ãããšæããŸãã
2çªç®ã®PUTã®åŸã«ã{'username'ïŒ 'curly'ã 'role'ïŒ 'admin'}ããããŸãã
ç§ã¯ã圹å²ãããã©ã«ãã«æ»ããšå人çã«é©ããŸãïŒãã®replace
ãªããžã§ã¯ãã®è°è«ã®çç±ã¯ããããŸãããå®éã®åé¡ã¯ãŸã çºçããŠããŸããïŒ
ç§ã¯ãŸã ããã§çŸå®äžçã®åé¡ãæ±ããããšã¯ãããŸãã
ããã§ãåãã§ããããããŸã§ã®ãšãããç§ãã¡ã®ãããžã§ã¯ãã¯PATCHã«äŸåããŠããŸã:)
ãšã¯èšããã®ã®ã䞊è¡æ§ãåŠçããããã®ã¢ãã«ããŒãžã§ã³ç®¡çã䌎ãOPã®ãŠãŒã¹ã±ãŒã¹ã¯ç§ã«ã¯çã«ããªã£ãŠããŸãã PUTãããã©ã«ãå€ïŒå€ãçç¥ãããŠããå ŽåïŒã䜿çšããŠãåæå®è¡äŸå€ãçºçãããããšãæåŸ
ããŸãã
ãŸããã·ãªã¢ã©ã€ã¶ãŒãå¿ ãããRESTfulRFCã«åŸãå¿ èŠããªãããšãèªããããšããå§ããŸãããã ãã ããå°ãªããšãäºææ§ã®ããã¢ãŒããæäŸããå¿ èŠããããŸããç¹ã«ãRESTãµããŒããæäŸããããã±ãŒãžã§ã¯ããã§ãã
ç§ã®æåã®è°è«ã¯ç¬¬äžåçããã®ãã®ã§ãããã RFC ïŒã»ã¯ã·ã§ã³4.3.4ïŒã¯å ·äœçã«æ¬¡ã®ããã«è¿°ã¹ãŠããŸãïŒåŒ·èª¿ãè¿œå ïŒïŒ
POSTã¡ãœãããšPUTã¡ãœããã®åºæ¬çãªéãã¯ãå²ãŸããè¡šçŸã®æå³ãç°ãªãããšã§åŒ·èª¿ãããŠããŸãã POSTãªã¯ãšã¹ãã®ã¿ãŒã²ãããªãœãŒã¹ã¯ããªãœãŒã¹èªäœã®ã»ãã³ãã£ã¯ã¹ã«åŸã£ãŠå²ãŸããè¡šçŸãåŠçããããšãç®çãšããŠããŸãããPUTãªã¯ãšã¹ãã®å²ãŸããè¡šçŸã¯ãã¿ãŒã²ãããªãœãŒã¹ã®ç¶æ ã眮ãæãããã®ãšããŠå®çŸ©ãããŠããŸãã
..ã
ç¹å®ã®ã¿ãŒã²ãããªãœãŒã¹ã§PUTãèš±å¯ãããªãªãžã³ãµãŒããŒã¯ããã€ããŒããéšåçãªã³ã³ãã³ãã§ããå¯èœæ§ãé«ããããContent-RangeããããŒãã£ãŒã«ãïŒ[RFC7233]ã®ã»ã¯ã·ã§ã³4.2ïŒãå«ãPUTãªã¯ãšã¹ãã«400ïŒBad RequestïŒå¿çãéä¿¡ããå¿ èŠããããŸã
ãããã£ãŠã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
ããªãéãããã£ãŒã«ãã¯å¿
é ã§ãã ïŒæ¢åïŒ_絶察çãª_æ£è§£ããªãããšã¯æããã§ãããçŸåšã®ãšãããæãå®çšçãªåäœãããŠãããšæããŸãã
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ã¯è¿œå ã®æ
å ±ãã·ãªã¢ã©ã€ã¶ãŒã«æž¡ãå¿
èŠããããŸãïŒ$ïŒ$ 1 $ïŒ$ã®å Žåã¯ãããreplace=True
PUT
ïŒã ã·ãªã¢ã©ã€ã¶ãŒã¯ããããå®è£
ããæ¹æ³ã決å®ã§ããŸãïŒãã¹ãŠã®ãã£ãŒã«ããèŠæ±ããããããã©ã«ããæ¿å
¥ããŸãïŒã
æããã«ãããã¯å€§ãŸããªææ¡ã«ãããŸãããããããããã¯ãæç Žããå¯èœæ§ããããŸãã
ããã«ãPUT-as-createã¯ããèªäœãæå¹ãªæäœã§ãããããPOSTãšã¯ç°ãªããå¿ é ãã»ãã³ãã£ã¯ã¹ããã£ãå Žåãå¥åŠã§ãã
PUTã§äœæã§ããããšã«åæããŸãããã»ãã³ãã£ã¯ã¹ãåãã§ããããšã«åæããŸããã PUT
ã¯ç¹å®ã®ãªãœãŒã¹ã§æ©èœããŸãïŒ
PUTã¡ãœããã¯ãã¿ãŒã²ãããªãœãŒã¹ã®ç¶æ ãäœæããããèŠæ±ã¡ãã»ãŒãžãã€ããŒãã§å²ãŸããè¡šçŸã«ãã£ãŠå®çŸ©ãããç¶æ ã«çœ®ãæããããšãèŠæ±ããŸãã
ãããã£ãŠãäœæã®ã»ãã³ãã£ã¯ã¹ã¯å®éã«ã¯ç°ãªããšæããŸãã
/citizen/
ã¯ãSSNïŒç€ŸäŒä¿éçªå·ïŒãçæãããããšãæåŸ
ããŠããŸã/citizen/<SSN>
ã«ãããšãç¹å®ã®SSNã®ããŒã¿ãæŽæ°ãããŸãã ãã®SSNã«ããŒã¿ããªãå Žåã¯ãäœæãããŸãããidãã¯PUTã®URIã«å«ãŸããŠããå¿ èŠããããããå¿ èŠã«å¿ããŠæ±ãããšãã§ããŸãã å¯Ÿç §çã«ãPOSTã§ã¯ãidãã¯ãªãã·ã§ã³ã§ãã
ãidãã¯PUTã®URIã«å«ãŸããŠããå¿ èŠããããããå¿ èŠã«å¿ããŠæ±ãããšãã§ããŸãã å¯Ÿç §çã«ãPOSTã§ã¯ãidãã¯ãªãã·ã§ã³ã§ãã
ããã¯ããã ãPUTã«å³å¯ã«_all_ãã£ãŒã«ããèŠæ±ãããããšããææ¡ãããå€æŽã¯ãPUT-as-createãPOST-as-createwrtãšã¯ç°ãªãåäœãããããšãæå³ãããšããäºå®ã«ç¹ã«èšåããŠããŸããã ãã£ãŒã«ããå¿ èŠãã©ããã
ç§ã¯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 APIã«ã¯åœ¹ç«ã¡ãŸãããå®éã«ã¯ããã£ã¯ã¹ãã£ã®ãã³ããšããŒãã«éå®ãããŠããŸãã
ããªãã¯ç§ãããDjangoãšDRFã®äž¡æ¹ã®ã¢ãŒããã¯ãã£äžã®ä»®å®ãããç¥ã£ãŠããã®ã§ããã®æ¹æ³ã«ã€ããŠã¯ããªãã«ä»»ããªããã°ãªããŸããã 確ãã«ã init
kwargã¯ããã«é©åãªæ觊ãæã£ãŠããŸã...ã·ãªã¢ã©ã€ã¶ãŒãããªã³ããã³ããã§åæ§æããŸãã å¯äžã®å¶éã¯ãããªã³ã¶ãã©ã€ãã§åæ§æã§ããªãããšã§ãããã€ã³ã¹ã¿ã³ã¹ã¯äœ¿ãæšãŠã§ãããšæ³å®ããŠãããããããã¯éèŠãªåé¡ã§ã¯ãããŸããã
ä»ã®ãšãããããããã€ã«ã¹ããŒã³ããå€ããŸãã v3.7以éã§åè©äŸ¡ã§ããŸã
çãã次第ã§ããããããåæå®è¡ãµããŒããè¿œå ããããã®ãã±ããã§ã¯ãªãããšãæ確ã«ããããšæããŸãã æ¬åœã®åé¡ã¯ãåäžã®ã·ãªã¢ã©ã€ã¶ãŒãçŸåšã®ã¢ãŒããã¯ãã£ã§PUTãšPOSTã®äž¡æ¹ãæ£ããæ€èšŒã§ããªãããšã§ãã 䞊è¡æ§ã¯ã倱æãããã¹ãããæäŸããã ãã§ãã
TL; DRãã ãææ¡ããä¿®æ£ããå§ãããšããã®åé¡ããããã¯ãããçç±ãããããŸãã
èŠçŽãããšãææ¡ããã解決çã¯ã PUT
ãªã¯ãšã¹ãã«å¿
èŠãªãã¹ãŠã®ãã£ãŒã«ããäœæããããšã§ãã ãã®ã¢ãããŒãã«ã¯ïŒå°ãªããšãïŒ2ã€ã®åé¡ããããŸãã
PUT
ãšPOST
ã§å
±æãããŠãããããæãããªäŸã¯create
$ã§ãã PUT
ã«ããäœæã¯ããã©ã«ãã§ç¡å¹ã«ãªã£ãŠãããããææ¡ãããä¿®æ£ã¯ããããäœããªããããåªããŠããããšã«æ³šæããŠãã ãããPUT
ïŒïŒ3648ãïŒ4703ã§å
±æãããææ
ïŒã®ãã¹ãŠã®ãã£ãŒã«ããèŠæ±ããå¿
èŠã¯ãããŸããã nillableãã£ãŒã«ããååšããªãå ŽåãNoneã§ããå¯èœæ§ããããŸãã ããã©ã«ãã®ãã£ãŒã«ãããªãå Žåã¯ãããã©ã«ãã䜿çšã§ããããšãããããŸãã PUT
ã«ã¯ãå®éã«ã¯POST
ãšåãïŒã¢ãã«ãã掟çããïŒãã£ãŒã«ãèŠä»¶ããããŸããæ¬åœã®åé¡ã¯ãæ¬ æž¬ããŒã¿ãšïŒ3648ãïŒ4703ã®åºæ¬çãªææ¡ãã©ã®ããã«åŠçãããã§ãããããã§ãæ£ãã解決çãç¶æããŸãã if_missing_use_default
ã®ãããªæŠå¿µãå°å
¥ããã°ããã¹ãŠã®HTTPã¢ãŒãïŒcreate-by- PUT
ãå«ãïŒããµããŒãã§ããŸãã ç§ã®æåã®ææ¡ã§ã¯ã partial
ã®ä»£ãããšããŠæ瀺ããŸããããçŽäº€ããæŠå¿µãšããŠèããæ¹ãç°¡åã§ãïŒå¿
èŠãªå ŽåããããŸãïŒã
if_missing_use_defaultã®ãããªæŠå¿µãå°å ¥ããå Žåã
ããããŸãã¯å³å¯ãªããã¹ãŠã®ãã£ãŒã«ããå¿ èŠãšããããåºæ¬ã·ãªã¢ã©ã€ã¶ãŒã¯ã©ã¹ãšããŠå®è£ ããããããµãŒãããŒãã£ã©ã€ãã©ãªãšããŠã©ããããããšã劚ãããã®ã¯äœããããŸããã
ç§ã®æèŠã§ã¯ãå³å¯ãªããã¹ãŠã®ãã£ãŒã«ããèŠæ±ãããã¢ãŒãã§ãã³ã¢ã«ããããšãã§ããå¯èœæ§ããããŸããããã¯éåžžã«æ確ãªåäœã§ããããªãããã圹ç«ã€ã®ããããããŸãã
ããã£ãŒã«ãããªãã·ã§ã³ã«ããããšã¯ã§ããŸãããã¢ãã«ã®ããã©ã«ããååšããå Žåã¯ããã䜿çšããŠããã¹ãŠã眮ãæããããšã¯ç¢ºä¿¡ããŠããŸãããããã¯ãéåžžã«çŽæã«åããåäœïŒããšãã°ããcreated_atããã£ãŒã«ããèªåçã«çµäºããïŒã瀺ãããã§ããèªåèªèº«ãæŽæ°ããïŒã ããå³å¯ãªåäœãå¿ èŠãªå Žåã¯ãããå³å¯ãªåäœãè¡ãå¿ èŠããããŸãã
ãããã«ãããããã«åãçµãæ£ããæ¹æ³ã¯ããµãŒãããŒãã£ã®ããã±ãŒãžãšããŠæ€èšŒããŠãããããã¥ã¡ã³ããæŽæ°ããŠãªã³ã¯ã§ããããã«ããããšã§ãã
ãŸãã¯ããŠãŒã¶ãŒãæ¬åœã«å¿ èŠãšããåäœãã³ã¢ããæ¬ èœããŠãããšç¢ºä¿¡ããŠããå Žåã¯ããã«ãªã¯ãšã¹ããäœæããŠåäœãšããã¥ã¡ã³ããæŽæ°ããããšãæè¿ããŸããããã«ãããéåžžã«ã¡ãªãããè©äŸ¡ã§ããŸããå ·äœçãªæ¹æ³ã
ãã®ããã®éå§ç¹ãšããŠãã«ãªã¯ãšã¹ããåãã§åãåããŸããããã«ããã®åäœã瀺ããµãŒãããŒãã£ã®ããã±ãŒãžãå«ããããšãã§ããŸãã
PUT-is-strictåäœã®ãªãã·ã§ã³ãæã€ããšã§äŸ¡å€ã«è¿ã¥ããŸãã
ããã¯ãŸã ç«ã£ãŠããŸãã 誰ãããããã®ç·ã«æ²¿ã£ãŠãã«ãªã¯ãšã¹ããè¡ãã®ã«ååæ°ã«ãããŠãããªããç§ãã¡ã¯ãã®åŽé¢ãã³ã¢ã§èããããšãã§ãããšæããŸãã ããã¯ãªãã·ã§ã³ã®åäœã§ããå¿ èŠããããŸãã
ããã¯ãéåžžã«çŽæã«åããåäœã瀺ãããã§ãïŒããšãã°ããcreated_atããã£ãŒã«ãã¯ãèªåçã«æŽæ°ãããŸãïŒã
created_at
ãã£ãŒã«ãã¯read_only
ã§ããå¿
èŠããããŸãïŒãŸãã¯ã·ãªã¢ã©ã€ã¶ãŒããé€å€ãããŸãïŒã ã©ã¡ãã®å Žåããå€æŽãããŸããïŒéåžžã®ã·ãªã¢ã©ã€ã¶ãŒã®åäœïŒã ã·ãªã¢ã©ã€ã¶ãŒã§ãã£ãŒã«ããèªã¿åãå°çšã§ã¯ãªããšããçŽæã«åããã±ãŒã¹ã§ã¯ããã£ãŒã«ããèªåçã«å€æŽãããšããçŽæã«åããåäœãçºçããŸãã
ãã®ããã®éå§ç¹ãšããŠãã«ãªã¯ãšã¹ããåãã§åãåããŸããããã«ããã®åäœã瀺ããµãŒãããŒãã£ã®ããã±ãŒãžãå«ããããšãã§ããŸãã
絶察ã ãããã©ã«ãã䜿çšãã®ããªãšãŒã·ã§ã³ã¯ããµãŒãããŒãã£ããã±ãŒãžã®çæ³çãªã±ãŒã¹ã§ããããã¯ãå€æŽãæ¢åã®åäœïŒã®1ã€ã®æ¹æ³ïŒã®ç°¡åãªã©ãããŒã§ãããïŒããã©ã«ãã®åŒæ°ãè³Œå ¥ããå ŽåïŒãã¹ãŠã®ééšåçãªã·ãªã¢ã©ã€ã¶ãŒã§æ©èœããããã§ãã
tomchristieã¯4æéåã«éåºããŸãã
ããããããPR WelcomeããããµãŒãããŒãã£ãã©ã°ã€ã³ããªã©ã®ã©ãã«ãè¿œå ãããã®ãããªæå¹ãª/確èªæžã¿ã®åé¡ãéãããŸãŸã«ããŠããããšãæ€èšããŠãã ããã ç§ã¯ããæªè§£æ±ºã®åé¡ãæ€çŽ¢ããŠãåé¡ããã§ã«å ±åãããŠãããã©ãããããã³åé¡ã®è§£æ±ºã«åããé²æç¶æ³ã確èªããŸãã ã¯ããŒãºãããåé¡ã¯ãç¡å¹ããŸãã¯ãä¿®æ£æžã¿ããšèªèããŠããŸãã ããã€ãã®ãæå¹ã ãã¯ããŒãºããããåé¡ãäœåãã®ç¡å¹/ä¿®æ£ãããåé¡ã«æ··ããŠããå¹ççãªæ€çŽ¢ã¯ã§ããŸããïŒããããååšããå¯èœæ§ãããããšãç¥ã£ãŠãããšããŠãïŒã
ããããããPRWelcomeããã3rdPartyPluginãã®ãããªã©ãã«ãè¿œå ããããšãæ€èšããã§ãããã
ããã¯ååã«åççã§ããããããžã§ã¯ãèªäœã®ã¢ã¯ãã£ããŸãã¯å®çšçãªäœæ¥ãåæ ããããã«ã課é¡è¿œè·¡ã·ã¹ãã ãå¿ èŠã§ãã
åé¡ã®ç¯å²ãå³ããä¿ã€ããšã¯ãç§ãã¡ã«ãšã£ãŠéåžžã«éèŠã§ãã åªå é äœãå€æŽãããšã以åã«ã¯ããŒãºããåé¡ãåéããããšãéžæããå ŽåããããŸãã ä»ã®ãšãããããã¯ãã³ã¢ããŒã ã¯è¿ãå°æ¥ããã«å¯ŸåŠããããããå€ããŠãããšæããŸãã
ãããç¹°ãè¿ãçºçãããµãŒãããŒãã£ã®è§£æ±ºçããªãå Žåã¯ããããããããåè©äŸ¡ããŸãã
ãã®ãããªæå¹ãª/確èªæžã¿ã®åé¡ã¯æªè§£æ±ºã®ãŸãŸã«ããŠãããŸãã
åé¡ç®¡çã¹ã¿ã€ã«ã«é¢ããããå°ãã³ã³ããã¹ã-httpsïŒ//www.dabapps.com/blog/sustainable-open-source-management/