Django-rest-framework: 직렬 λ³€ν™˜κΈ° DateTimeField에 예기치 μ•Šμ€ μ‹œκ°„λŒ€ 정보가 μžˆμŠ΅λ‹ˆλ‹€.

에 λ§Œλ“  2015λ…„ 12μ›” 13일  Β·  34μ½”λ©˜νŠΈ  Β·  좜처: encode/django-rest-framework

λ‚΄ 섀정에 TIME_ZONE = 'Asia/Kolkata' 및 USE_TZ = True 이 μžˆμŠ΅λ‹ˆλ‹€.

탐색 κ°€λŠ₯ν•œ APIλ₯Ό μ‚¬μš©ν•˜μ—¬ μƒˆ 객체λ₯Ό 생성할 λ•Œ 직렬 λ³€ν™˜κΈ°λŠ” μ‹œκ°„λŒ€λ₯Ό λ‚˜νƒ€λ‚΄λŠ” +5:30 후행이 μžˆλŠ” datetime으둜 μƒˆλ‘œ μƒμ„±λœ 객체λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€. λ°μ΄ν„°λ² μ΄μŠ€λŠ” UTC둜 μ‹œκ°„μ„ μ €μž₯ν•©λ‹ˆλ‹€.

예기치 μ•Šμ€ λ™μž‘μ€ λ‚˜μ€‘μ— κ°œμ²΄κ°€ λ‹€μ‹œ 직렬화될 λ•Œ λ‚ μ§œ/μ‹œκ°„μ΄ λͺ¨λ‘ UTC ν˜•μ‹μ΄κ³  뒀에 Z κ°€ λΆ™λŠ” κ²ƒμž…λ‹ˆλ‹€. ν˜„μž¬ 및 κΈ°λ³Έ μ‹œκ°„λŒ€μ— μž₯κ³  λ¬Έμ„œμ— λ”°λ₯΄λ©΄, λ‚˜λŠ” μ‹œλ¦¬μ–Όμ€ ν˜„μž¬ μ‹œκ°„λŒ€μ— λ‚ μ§œ μ‹œκ°„μ„ λ³€ν™˜ κΈ°λŒ€ν•˜λŠ” μ„€μ •λœ κΈ°λ³Έ μ‹œκ°„λŒ€, 기본값은 TIME_ZONE = 'Asia/Kolkata' .

λ‚΄κ°€ λ­”κ°€λ₯Ό λ†“μΉ˜κ³  μžˆμŠ΅λ‹ˆκΉŒ?

Needs further review

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

이 κΈ°λŠ₯에 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€. USE_TZ 섀정이 μ‘΄μ€‘λ˜μ–΄μ•Ό ν•˜κ³  ν‘œμ€€ Django λ™μž‘κ³Ό μœ μ‚¬ν•˜κ²Œ 값이 λ³€ν™˜λ˜μ–΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

λͺ¨λ“  34 λŒ“κΈ€

μŠ€νƒ μ˜€λ²„ν”Œλ‘œμ— λŒ€ν•΄ 질문 ν–ˆκ³  결둠은 datetime이 μœ νš¨μ„± 검사 ν›„(즉, 생성 λ˜λŠ” μ—…λ°μ΄νŠΈ ν›„) κ·ΈλŒ€λ‘œ μ§λ ¬ν™”λ˜κΈ° λ•Œλ¬Έμ— ν˜„μž¬ μ‹œκ°„λŒ€λŠ” μ‚¬μš©μžκ°€ μ œκ³΅ν•œ datetimeμ—λ§Œ μ‚¬μš©λœλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. Django λ¬Έμ„œμ—μ„œ 이것이 μ˜λ„λœ λ™μž‘μ΄λΌκ³  λ―ΏκΈ° μ–΄λ ΅μ§€λ§Œ 이것은 Rest Frameworkκ°€ μ•„λ‹ˆλΌ Django 자체의 λ¬Έμ œμ΄λ―€λ‘œ 이 문제λ₯Ό λ‹«κ² μŠ΅λ‹ˆλ‹€.

μ•ˆλ…•ν•˜μ„Έμš” @tomchristie ,

이것은 DRF 버그라고 μƒκ°ν•©λ‹ˆλ‹€.
IMHO, DRF의 μžμ—°μŠ€λŸ¬μš΄ μ‚¬μš©μ€ DRFλ₯Ό django ν…œν”Œλ¦Ώκ³Ό 같은 좜λ ₯으둜 μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.
django ν…œν”Œλ¦Ώμ—μ„œ μ‹œκ°„λŒ€κ°€ μ˜¬λ°”λ₯΄κ²Œ ν‘œμ‹œλ˜λŠ”λ° drf 직렬 λ³€ν™˜κΈ°κ°€ django μ‹œκ°„λŒ€ 섀정을 μ‘΄μ€‘ν•˜μ§€ μ•ŠλŠ” μ΄μœ λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

μ•ˆλ…•ν•˜μ„Έμš”,

DatetimeField 클래슀의 fields.py μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄λ©΄ Django μ‹œκ°„λŒ€ 섀정이 λ‚΄λΆ€ κ°’( to_internal_value() )에 λŒ€ν•΄μ„œλ§Œ 잘 κ³ λ €λœλ‹€λŠ” 것을 μ•Œμ•˜μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 λͺ¨λΈ 직렬 λ³€ν™˜κΈ°λ₯Ό μ‚¬μš©ν•˜λŠ” 것을 λ³΄μ•˜μŠ΅λ‹ˆλ‹€.

class MyModelSerializer(ModelSerializer):

    class Meta:
        model = MyModel
        depth = 1
        fields = ('some_field', 'my_date_time_field')

my_date_time_field ν•„λ“œμ˜ 경우 (DateTimeField라고 μƒκ°ν•©λ‹ˆλ‹€ :)) ν‘œν˜„μ˜ μ‹œκ°„λŒ€λŠ” κΈ°λ³Έκ°’( to_representation() )의 경우 μ—†μŒμž…λ‹ˆλ‹€.

즉, λ‚΄κ°€ 틀리지 μ•ŠμœΌλ©΄ Django μ‹œκ°„λŒ€λŠ” 값이 μŠ€ν† λ¦¬μ§€ λ°±μ—”λ“œμ— μ“°μ—¬μ§ˆ λ•Œλ§Œ κ³ λ €λ©λ‹ˆλ‹€.

IMHO to_representation() 의 λ°˜ν™˜ 값은 λ‹€μŒκ³Ό κ°™μ•„μ•Ό ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.
return self.enforce_timezone(value).strftime(output_format)
Django USE_TZ 섀정에 따라.

이에 λŒ€ν•œ ν’€ λ¦¬ν€˜μŠ€νŠΈλ₯Ό μž‘μ„±ν•©λ‹ˆλ‹€.

차였
λ°œλ Œν‹°λ…Έ

@vpistis ν˜„μž¬ 보고 μžˆλŠ” API λ™μž‘μ˜ μ˜ˆμ™€ 무엇을 λ³Ό κ²ƒμœΌλ‘œ μ˜ˆμƒν•˜λŠ”μ§€(κ΅¬ν˜„ 츑면을 λ¨Όμ € λ…Όμ˜ν•˜κΈ° λ³΄λ‹€λŠ”) 예λ₯Ό λ“€μ–΄ μ œμ‹œν•  수 μžˆλ‹€λ©΄ 이것을 κ²€ν† ν•˜λŠ” 것이 더 μ‰¬μšΈ κ²ƒμž…λ‹ˆλ‹€.

TIME_ZONE = 'Asia/Kolkata' ν•˜κ³  단일 λ‚ μ§œ/μ‹œκ°„ ν•„λ“œ appointment μ‚¬μš©ν•˜μ—¬ λͺ¨λΈ 직렬 λ³€ν™˜κΈ°λ₯Ό λ§Œλ“­λ‹ˆλ‹€.

생성/μ—…λ°μ΄νŠΈ 쀑에 λ‹€μŒμ„ λ³΄λƒ…λ‹ˆλ‹€.

{
    "appointment": "2016-12-19T10:00:00"
}

그리고 λŒμ•„μ˜€λ‹€:

{
    "appointment": "2016-12-19T10:00:00+5:30"
}

κ·ΈλŸ¬λ‚˜ ν•΄λ‹Ή 객체λ₯Ό λ‹€μ‹œ κ²€μƒ‰ν•˜κ±°λ‚˜ λ‚˜μ—΄ν•˜λ©΄ λ‹€μŒμ„ μ–»μŠ΅λ‹ˆλ‹€.

{
    "appointment": "2016-12-19T04:30:00Z"
}

μƒμ„±ν•˜λŠ” λ™μ•ˆ Zκ°€ μ§€μ •λ˜μ§€ μ•Šμ€ 경우 DRFλŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ TIME_ZONE μ§€μ •λœ μ‹œκ°„λŒ€λ₯Ό μ‚¬μš©ν•˜κ³  μžˆλ‹€κ³  κ°€μ •ν•˜κ³  ν•΄λ‹Ή μ‹œκ°„λŒ€μ— ν˜•μ‹μ΄ μ§€μ •λœ μ‹œκ°„μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€(끝에 +5:30 λ₯Ό μΆ”κ°€ν•˜μ—¬ ν΄λΌμ΄μ–ΈνŠΈκ°€ μ œκ³΅ν•œ μ‹œκ°„μΈ 경우 μ‹€μ œλ‘œ μœ νš¨ν•˜μ§€ μ•ŠμŒ). ν–₯ν›„ μ•‘μ„ΈμŠ€κ°€ ν•΄λ‹Ή μ‹œκ°„λŒ€μ— ν˜•μ‹μ΄ μ§€μ •λœ μ‹œκ°„μ„ λ°˜ν™˜ν•˜λŠ” 경우 더 μ˜λ―Έκ°€ μžˆμœΌλ―€λ‘œ 검색/λͺ©λ‘ 쀑 응닡이 생성/μ—…λ°μ΄νŠΈ 쀑 응닡과 λ™μΌν•©λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 생성/μ—…λ°μ΄νŠΈ 쀑에 ν›„ν–‰ Zκ°€ 제곡될 λ•Œ κ΅¬μ„±λœ μ‹œκ°„λŒ€μ˜ μ‹œκ°„μ„ λ°˜ν™˜ν• μ§€ 여뢀에 λŒ€ν•œ μ§ˆλ¬Έλ„ μžˆμŠ΅λ‹ˆλ‹€.

{
    "appointment": "2016-12-19T04:30:00Z"
}

보고:

{
    "appointment": "2016-12-19T10:00:00+5:30"
}

λͺ©λ‘/검색에 λŒ€ν•œ 응닡과 μΌκ΄€λœ 응닡을 μœ μ§€ν•˜κΈ° λ•Œλ¬Έμ— 이에 λ™μ˜ν•©λ‹ˆλ‹€.

또 λ‹€λ₯Έ μ˜΅μ…˜μ€ 생성/μ—…λ°μ΄νŠΈ 쀑에도 항상 UTC μ‹œκ°„μ„ λ°˜ν™˜ν•˜λŠ” κ²ƒμ΄μ§€λ§Œ 덜 μœ μš©ν•˜λ‹€λŠ” 것을 μ•Œμ•˜μŠ΅λ‹ˆλ‹€. μ–΄λŠ μͺ½μ΄λ“  μΌκ΄€λœ μ‹œκ°„λŒ€λ₯Ό κ°–λŠ” 것이 ν˜„μž¬ μš°λ¦¬κ°€ 가진 50/50 상황보닀 더 λ‚˜μ„ κ²ƒμž…λ‹ˆλ‹€.

TIME_ZONE = 'Asia/Kolkata'둜 μ„€μ •ν•˜κ³  단일 datetime ν•„λ“œμΈ 약속을 μ‚¬μš©ν•˜μ—¬ λͺ¨λΈ 직렬 λ³€ν™˜κΈ°λ₯Ό λ§Œλ“­λ‹ˆλ‹€.

생성/μ—…λ°μ΄νŠΈ 쀑에 λ‹€μŒμ„ λ³΄λƒ…λ‹ˆλ‹€.

{
"약속": "2016-12-19T10:00:00"
}
그리고 λŒμ•„μ˜€λ‹€:

{
"약속": "2016-12-19T10:00:00+5:30"
}
κ·ΈλŸ¬λ‚˜ ν•΄λ‹Ή 객체λ₯Ό λ‹€μ‹œ κ²€μƒ‰ν•˜κ±°λ‚˜ λ‚˜μ—΄ν•˜λ©΄ λ‹€μŒμ„ μ–»μŠ΅λ‹ˆλ‹€.

{
"약속": "2016-12-19T04:30:00Z"
}

κ°μ‚¬ν•©λ‹ˆλ‹€ @jonathan-golorry 이것은 λ‚΄κ°€ μ‹€μ œλ‘œ λ³΄λŠ” μ •ν™•ν•œ λ™μž‘μž…λ‹ˆλ‹€.
λ‚˜λ₯Ό μœ„ν•΄ 행동은 λ‹€μŒκ³Ό κ°™μ•„μ•Όν•©λ‹ˆλ‹€ ( @jonathan-golorry 예제 μ‚¬μš© :) ).

κΈ°λ³Έ DATETIME_FORMAT으둜 생성/μ—…λ°μ΄νŠΈν•˜λŠ” λ™μ•ˆ λ‹€μŒμ„ λ³΄λƒ…λ‹ˆλ‹€.

{
    "appointment": "2016-12-19T10:00:00"
}

그리고 λŒμ•„μ˜€λ‹€:

{
    "appointment": "2016-12-19T10:00:00+5:30"
}

ν•΄λ‹Ή 객체λ₯Ό λ‹€μ‹œ κ²€μƒ‰ν•˜κ±°λ‚˜ λ‚˜μ—΄ν•˜λ©΄ λ‹€μŒμ„ μ–»μŠ΅λ‹ˆλ‹€.

{
    "appointment": "2016-12-19T10:00:00+5:30"
}

IMHOλŠ” 이 λ™μž‘μ„ κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ DRF 섀정이어야 ν•©λ‹ˆλ‹€(예: DateTimeFieldκ°€ κΈ°λ³Έ μ‹œκ°„λŒ€λ₯Ό μ‚¬μš©ν•˜μ—¬ ν‘œμ‹œλ˜λ„λ‘ κ°•μ œν•˜λŠ” μ„€μ •).

κ°μ‚¬ν•©λ‹ˆλ‹€ @tomchristie

μ„œλ‘œ λ‹€λ₯Έ 행동 μ‚¬μ΄μ˜ λΆˆμΌμΉ˜λŠ” μ—¬κΈ°μ—μ„œ μž¬κ°œν•˜κΈ° μœ„ν•œ ν•΅μ‹¬μž…λ‹ˆλ‹€. λ‚˜λŠ” 그것이 사싀인지 λͺ°λžμŠ΅λ‹ˆλ‹€. 선택 μ‚¬ν•­μœΌλ‘œ λ§Œλ“€ 수 λŠ” μžˆμ§€λ§Œ 기본적으둜 전체 UTCλ₯Ό μ‚¬μš©ν•  κ²ƒμœΌλ‘œ μ˜ˆμƒν•©λ‹ˆλ‹€.

DRF 3.4.6을 μ‚¬μš©ν•˜λŠ” ν”„λ‘œλ•μ…˜ μ›Ή μ•±μ˜ 경우 λ‹€μŒ ν•΄κ²° λ°©λ²•μœΌλ‘œ ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€.
https://github.com/vpistis/django-rest-framework/commit/be62db9080b19998d4de3a1f651a291d691718f6

λˆ„κ΅¬λ“ μ§€ λ‹€μŒμ„ ν¬ν•¨ν•˜λŠ” ν’€ λ¦¬ν€˜μŠ€νŠΈλ₯Ό μ œμΆœν•˜κ³  μ‹Άλ‹€λ©΄:

  • μ‹€νŒ¨ν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό 포함 ν•˜κ±°λ‚˜ ...
  • ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ + μˆ˜μ •

κ°€μž₯ ν™˜μ˜ν•  μΌμž…λ‹ˆλ‹€.

ν…ŒμŠ€νŠΈν•  μ½”λ“œλ₯Ό μž‘μ„±ν–ˆμ§€λ§Œ drf ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό μ–΄λ–»κ²Œ μ‚¬μš©ν•˜λŠ”μ§€ 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€. λŸ°νƒ€μž„μ— μ‹œκ°„λŒ€ 및 기타 섀정을 λ³€κ²½ν•˜κΈ° μœ„ν•΄ django 섀정을 κ΄€λ¦¬ν•˜λŠ” 방법을 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€.
ꡬ체적인 μ˜ˆλ‚˜ κ°€μ΄λ“œλ₯Ό 링크해 μ£Όμ„Έμš”.

κ°μ‚¬ν•©λ‹ˆλ‹€

μ „μ—­ ν…ŒμŠ€νŠΈ 섀정을 μˆ˜μ •ν•˜λ €λŠ” 경우 μ—¬κΈ° 에

ν…ŒμŠ€νŠΈ 쀑에 섀정을 μž¬μ •μ˜ν•˜λ €λŠ” 경우 override_settings λ°μ½”λ ˆμ΄ν„°λ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

이 κΈ°λŠ₯에 κ°μ‚¬λ“œλ¦½λ‹ˆλ‹€. USE_TZ 섀정이 μ‘΄μ€‘λ˜μ–΄μ•Ό ν•˜κ³  ν‘œμ€€ Django λ™μž‘κ³Ό μœ μ‚¬ν•˜κ²Œ 값이 λ³€ν™˜λ˜μ–΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

μ—¬κΈ°μ„œ 첫 번째 λ‹¨κ³„λŠ” ν˜„μž¬ ν…ŒμŠ€νŠΈ μŠ€μœ„νŠΈμ— μΆ”κ°€ν•  수 μžˆλŠ” μ‹€νŒ¨ν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό μž‘μ„±ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.
λ‹€μŒ λ‹¨κ³„λŠ” ν•΄λ‹Ή 사둀에 λŒ€ν•œ μˆ˜μ •μ„ μ‹œμž‘ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. :)

μ•ˆλ…•ν•˜μ„Έμš”,
λ‚˜λ₯Ό μœ„ν•΄ 이것은이 κΈ°λŠ₯에 λŒ€ν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μž…λ‹ˆλ‹€

class TestDateTimeFieldTimeZone(TestCase):
    """
    Valid and invalid values for `DateTimeField`.
    """
    from django.utils import timezone

    valid_inputs = {
        '2001-01-01 13:00': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
        '2001-01-01T13:00': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
        '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
        datetime.datetime(2001, 1, 1, 13, 00): datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
        datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()): datetime.datetime(2001, 1, 1, 13, 00,
                                                                                        tzinfo=timezone.get_default_timezone()),
        # Django 1.4 does not support timezone string parsing.
        '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone())
    }
    invalid_inputs = {}
    outputs = {
        # This is not simple, for now I suppose TIME_ZONE = "Europe/Rome"
        datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()): '2001-01-01T13:00:00+01:00',
        datetime.datetime(2001, 1, 1, 13, 00, ): '2001-01-01T13:00:00+01:00',
    }

    field = serializers.DateTimeField()

λ‚΄ ν¬ν¬μ—μ„œ μ˜¬λ°”λ₯Έ μ‹œκ°„λŒ€ λ‚΄ 3.6.2_tz_fix μ‹œκ°„μ„ μ–»κΈ° μœ„ν•΄ λͺ‡ 가지 νŠΈλ¦­μ„ μ‚¬μš©ν•©λ‹ˆλ‹€.

이 도움이 되기λ₯Ό λ°”λžλ‹ˆλ‹€ :)

λ‚˜λŠ” 이것이 λ‹«ν˜€ μžˆλ‹€λŠ” 것을 μ•Œμ§€λ§Œ drf 3.6.3을 μ‹€ν–‰ 쀑이고 λ‚΄ postgres λ°μ΄ν„°λ² μ΄μŠ€μ— 이 νƒ€μž„μŠ€νƒ¬ν”„κ°€ "2017-07-12 14:26:00-06"μ΄μ§€λ§Œ 우편 배달뢀λ₯Ό μ‚¬μš©ν•˜μ—¬ 데이터λ₯Ό 얻을 λ•Œ 이 "νƒ€μž„μŠ€νƒ¬ν”„"λ₯Ό μ–»μŠ΅λ‹ˆλ‹€. : "2017-07-12T20:26:00Z". λ‚˜λŠ” 그것이 -06 μ‹œκ°„μ— μΆ”κ°€λ˜λŠ” κ²ƒμ²˜λŸΌ λ³΄μž…λ‹ˆλ‹€.

λ‚΄ django 섀정은 tzlocal을 μ‚¬μš©ν•˜μ—¬ TIME_ZONE = str(get_localzone()) μ‹œκ°„λŒ€λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€. λ”°λΌμ„œ μ‹œμž‘ μ‹œ μ‹œκ°„λŒ€κ°€ μ„€μ •λ©λ‹ˆλ‹€.

κΈ°λ³Έ modelSerializerλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

class SnapshotSerializer(serializers.ModelSerializer):
    class Meta:
        model = Snapshot
        resource_name = 'snapshot' 
        read_only_fields = ('id',)
        fields = ('id', 'timestamp', 'snapshot')

λ‚΄κ°€ λ­”κ°€λ₯Ό λ†“μΉ˜κ³  μžˆμŠ΅λ‹ˆκΉŒ?

아직 λ‹«νžˆμ§€ μ•Šκ³  μ—΄λ €μžˆμŠ΅λ‹ˆλ‹€ :)
ν‘œμ‹œλ˜λŠ” 빨간색 "λ‹«νžŒ λ²„νŠΌ"은 μ°Έμ‘° λ¬Έμ œμž…λ‹ˆλ‹€.
...그리고 λ‹Ήμ‹  말이 λ§žμ•„, "버그"λŠ” μ—¬μ „νžˆ 거기에 μžˆμŠ΅λ‹ˆλ‹€ ;(
μ΄μ •ν‘œκ°€ 3.6.3μ—μ„œ 3.6.4둜 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

였 그래. κ°μ‚¬ν•©λ‹ˆλ‹€!

2017λ…„ 7μ›” 12일 μ˜€ν›„ 5μ‹œ 10λΆ„ "λ°œλ Œν‹°λ…Έ ν”ΌμŠ€ν‹°μŠ€" μ•Œλ¦Ό @github.com
썼닀:

아직 λ‹«νžˆμ§€ μ•Šκ³  μ—΄λ €μžˆμŠ΅λ‹ˆλ‹€ :)
ν‘œμ‹œλ˜λŠ” 빨간색 "λ‹«νžŒ λ²„νŠΌ"은 μ°Έμ‘° λ¬Έμ œμž…λ‹ˆλ‹€.
...그리고 λ‹Ήμ‹  말이 λ§žμ•„, "버그"λŠ” μ—¬μ „νžˆ 거기에 μžˆμŠ΅λ‹ˆλ‹€ ;(
μ΄μ •ν‘œκ°€ 3.6.3μ—μ„œ 3.6.4둜 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

β€”
당신이 λŒ“κΈ€μ„ λ‹¬μ•˜κΈ° λ•Œλ¬Έμ— 이것을 λ°›λŠ” κ²ƒμž…λ‹ˆλ‹€.
이 이메일에 직접 λ‹΅μž₯ν•˜κ³  GitHubμ—μ„œ ν™•μΈν•˜μ„Έμš”.
https://github.com/encode/django-rest-framework/issues/3732#issuecomment-314923582 ,
λ˜λŠ” μŠ€λ ˆλ“œ μŒμ†Œκ±°
https://github.com/notifications/unsubscribe-auth/AIMBTcx-6PPbi_SOqeLCjeWV1Rb59-Ohks5sNVJ0gaJpZM4G0aRE
.

μ•ˆλ…•ν•˜μ„Έμš”,

이것이 μ›λž˜ 질문과 μ™„μ „νžˆ 관련이 μžˆλŠ”μ§€ ν™•μ‹€ν•˜μ§€ μ•Šμ§€λ§Œ DRFλŠ” https://docs.djangoproject.com/en/1.11/ref/utils/#django에 따라 μ„€μ •λœ μ‹œκ°„λŒ€ μž¬μ •μ˜λ₯Ό 쑴쀑해야 ν•©λ‹ˆλ‹€

λ‚΄ μ‚¬μš©μžκ°€ μ‹œκ°„λŒ€μ™€ μ—°κ²°λ˜μ–΄ 있고 APIκ°€ μˆœμ§„ν•œ λ‚ μ§œ μ‹œκ°„μ„ μˆ˜μ‹ ν•˜λŠ” μ‹œμŠ€ν…œμ΄ μžˆμŠ΅λ‹ˆλ‹€. ν•΄λ‹Ή λ‚ μ§œ μ‹œκ°„μ„ ν˜„μž¬ μ‚¬μš©μžμ˜ μ‹œκ°„λŒ€λ‘œ λ³€ν™˜ν•  수 μžˆμ„ κ²ƒμœΌλ‘œ μ˜ˆμƒν•˜μ§€λ§Œ ../rest_framework/fields.py 이 κΈ°λ³Έ μ‹œκ°„λŒ€(예: django μ„€μ • 파일의 μ‹œκ°„λŒ€)λ₯Ό μ μš©ν•˜κ³  μžˆμŒμ„ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

    def enforce_timezone(self, value):
        field_timezone = getattr(self, 'timezone', self.default_timezone())

        if (field_timezone is not None) and not timezone.is_aware(value):
            try:
                return timezone.make_aware(value, field_timezone)

[...]

    def default_timezone(self):
        return timezone.get_default_timezone() if settings.USE_TZ else None

λ‚΄ κ²½μš°μ™€ 같이 μ‘μš© ν”„λ‘œκ·Έλž¨μ΄ μž¬μ •μ˜λ₯Ό μ„€μ •ν•œ 경우 timezone.get_current_timezone() λ₯Ό κΈ°λ³Έ μ„€μ •μœΌλ‘œ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆκΉŒ?

μ•ˆλ…•ν•˜μ„Έμš” @RichardForshaw λŠ” λ³„κ°œμ˜ 문제처럼 λ³΄μ΄μ§€λ§Œ ν™•μ‹€νžˆ λ™μΌν•œ

μ˜ˆμƒλ˜λŠ” λ™μž‘μ„ λ‹€λ£¨λŠ” μ μ ˆν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ μ„ΈνŠΈλ₯Ό 얻을 수 μžˆλ‹€λ©΄ μ—¬κΈ°μ—μ„œ PR을 λ³Ό κ²ƒμž…λ‹ˆλ‹€.

λ‚΄ 첫 번째 생각은 μ„œλ²„μ˜ κ΅¬μ„±λœ μ‹œκ°„λŒ€μ— μ˜μ‘΄ν•˜μ§€ μ•Šκ³  API에 μ‹œκ°„λŒ€ 정보λ₯Ό 보내도둝 ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. κ·Έ 외에도 ν΄λΌμ΄μ–ΈνŠΈμ˜ μ‹œκ°„μ„ ν˜„μ§€ν™”ν•  μ€€λΉ„κ°€ λ˜μ–΄ μžˆμ–΄μ•Ό ν•œλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

ν•˜μ§€λ§Œ μ—¬κΈ°μ—λŠ” ν•΄κ²°ν•΄μ•Ό ν•  λΆˆμΌμΉ˜κ°€ μžˆμŠ΅λ‹ˆλ‹€. (홍보 ν™˜μ˜μ΄λΌκ³  λ§μ”€λ“œλ Έλ‚˜μš”? πŸ™‚)

carltongibson/django-filter#750이 여기에 κ΄€λ ¨λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. λ‚˜λŠ” μ›λž˜ DRF에 django-filter의 μ‹œκ°„λŒ€ 처리λ₯Ό 기반으둜 ν–ˆμœΌλ―€λ‘œ 750의 λ³€κ²½ 사항을 여기에 μ‰½κ²Œ μ μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‚΄ μ΄ˆλ³΄μžμ—κ²Œ λ―Έμ•ˆν•˜μ§€λ§Œ μ—¬κΈ°μ„œ λ¬Έμ œκ°€ μ •ν™•νžˆ λ¬΄μ—‡μž…λ‹ˆκΉŒ? λ‚΄ psql λ°μ΄ν„°λ² μ΄μŠ€μ˜ νƒ€μž„μŠ€νƒ¬ν”„κ°€ μ •ν™•ν•˜κ³  Djangoκ°€ μ˜¬λ°”λ₯Έ μ‹œκ°„λŒ€λ₯Ό μ‚¬μš©ν•˜λ„λ‘ μ„€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. νƒ€μž„ μŠ€νƒ¬ν”„λ₯Ό λ³€ν™˜ν•˜μ§€ μ•Šλ„λ‘ DRF 섀정이 μžˆμŠ΅λ‹ˆκΉŒ?

μ•ˆλ…•ν•˜μ„Έμš” @michaelaelise β€” λ°μ΄ν„°μ˜ 예λ₯Ό 보면(상단 λΆ€κ·Ό):

  1. 그듀은 μ‹œκ°„λŒ€ 정보없이 datetime을 보내고 μžˆμŠ΅λ‹ˆλ‹€. (이것은 λ‚΄ μ±…μ—μ„œ λ‚˜μœ μ›€μ§μž„μž…λ‹ˆλ‹€.)
  2. μ„œλ²„κ°€ ν˜„μ§€ μ‹œκ°„λŒ€λ₯Ό μ μš©ν•˜κ³  있으며 κ·ΈλŒ€λ‘œ λŒμ•„μ˜΅λ‹ˆλ‹€(이 경우 +5:30 ).
  3. κ·ΈλŸ¬λ‚˜ λ‚˜μ€‘μ— κ°€μ Έμ˜¬ λ•Œ UTC( Z , "Zulu"의 경우)둜 λŒμ•„μ˜΅λ‹ˆλ‹€.

ν΄λΌμ΄μ–ΈνŠΈκ°€ μ‹œκ°„λŒ€ λ³€ν™˜μ„ μ²˜λ¦¬ν•œλ‹€λŠ” κ°€μ • ν•˜μ— μ‹€μ œ 문제

ν•˜μ§€λ§Œ μ•½κ°„μ˜ λΆˆμΌμΉ˜κ°€ μžˆμŠ΅λ‹ˆλ‹€. ν™•μ‹€νžˆ 2와 3은 같은 ν˜•μ‹μ΄μ–΄μ•Ό ν•©λ‹ˆκΉŒ? (ν΄λΌμ΄μ–ΈνŠΈκ°€ μ˜¬λ°”λ₯΄κ²Œ λ‘˜ 쀑 ν•˜λ‚˜λ₯Ό λ™λ“±ν•œ κ°’μœΌλ‘œ μˆ˜λ½ν•˜λ”λΌλ„.)

λ‚˜λŠ” 이것을 λ‹«λŠ” κ²½ν–₯이 μžˆμŠ΅λ‹ˆλ‹€.

  • μ—¬κΈ°μ—λŠ” 논리 였λ₯˜κ°€ μ—†μŠ΅λ‹ˆλ‹€.

    • 이것은 같은 μ‹œκ°„μž…λ‹ˆλ‹€. "2016-12-19T10:00:00+5:30" 및 "2016-12-19T04:30:00Z" β€” μ–΄λŠ μ •λ„κΉŒμ§€λŠ” 그듀이 μ–΄λ–»κ²Œ λŒμ•„μ˜¬μ§€ λˆ„κ°€ 신경을 μ“°κ² μŠ΅λ‹ˆκΉŒ?

  • λ”°λΌμ„œ 그것은 λ‚΄κ°€ μ •λ§λ‘œ μ‹œκ°„μ„ ν• λ‹Ήν•˜λŠ” 것을 μ •λ‹Ήν™”ν•  수 μžˆλŠ” 것이 μ•„λ‹™λ‹ˆλ‹€.
  • 티켓은 2λ…„λœ 것이며 아무도 PR을 μ œμ•ˆν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

PR을 보게 λ˜μ–΄ κΈ°μ©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 이것을 _곡개 문제_둜 κ³ λ €ν•˜κ³  싢은지 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€.

μ•„, 이 문제 μŠ€λ ˆλ“œμ˜ μ›λž˜ κ²Œμ‹œλ¬Όμ—μ„œ "Z"κ°€ μ˜λ―Έν•œλ‹€λŠ” 것을 깨닫지 λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.
κ·Έλž˜μ„œ DRFλŠ” UI/ν˜ΈμΆœμžκ°€ μ²˜λ¦¬ν•  수 μžˆλ„λ‘ 인식 λ‚ μ§œ/μ‹œκ°„μ„ UTC둜 λ³€ν™˜ν•˜κ³  μžˆμŠ΅λ‹ˆκΉŒ?
μ„€λͺ…ν•΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€.

λ§ˆμ§€λ§‰ ν•œκ°€μ§€.
λ‹€λ₯Έ μ‹œκ°„λŒ€μ˜ μž₯치λ₯Ό ν΄λ§ν•˜κΈ° λ•Œλ¬Έμ— "2016-12-19T10:00:00+5:30"이 λ°˜ν™˜λ˜κΈ°λ₯Ό μ›ν•˜λ©΄ μ–΄λ–»κ²Œ λ κΉŒμš”?
"RETURN_DATETIME_WITH_TIMEZONE" 섀정이 μ•„λ‹κΉŒμš”?

μš°λ¦¬λŠ” 에지 μž₯μΉ˜μ—μ„œ django/drfλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ μ‚½μž…λ˜λŠ” λͺ¨λ“  λ‚ μ§œ μ‹œκ°„μ€ 에지 μž₯치 μ‹œκ°„λŒ€κ°€ κ΅¬μ„±λ˜κ³  postgres ν•„λ“œκ°€ ν•΄λ‹Ή μž₯치 λ‚ μ§œ μ‹œκ°„μ— λŒ€ν•΄ 항상 μ •ν™•ν•˜κΈ° λ•Œλ¬Έμ— μˆœμ§„ν•œμ§€ μ—¬λΆ€λ₯Ό μ‹ κ²½ 쓰지 μ•ŠμŠ΅λ‹ˆλ‹€.

ν˜„μž¬ μ‹œλ‚˜λ¦¬μ˜€μ˜ ν΄λΌμš°λ“œ μ„œλ²„λŠ” 각 μž₯치의 μ‹œκ°„λŒ€λ₯Ό μ•Œμ•„μ•Ό ν•˜λ©°, μ•„λ§ˆλ„ django/drfμ—μ„œ μ²˜λ¦¬ν•  ν΄λΌμš°λ“œ μ•±μœΌλ‘œ μž‘μ—…μ„ μ΄λ™ν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€.

USE_TZλ₯Ό κ°€μ •ν•˜λ©΄ DRFλŠ” 이미 μ‹œκ°„λŒ€ 정보와 ν•¨κ»˜ λ‚ μ§œ μ‹œκ°„μ„ λ°˜ν™˜ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ 이미 ν•„μš”ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

μ—¬κΈ°μ„œ μœ μΌν•œ λ¬Έμ œλŠ” λ™μΌν•œ DTκ°€ ν•œ μ‹œκ°„λŒ€ λ˜λŠ” λ‹€λ₯Έ μ‹œκ°„λŒ€μ—μ„œ ν˜•μ‹ν™”λ˜λŠ”μ§€ μ—¬λΆ€μž…λ‹ˆλ‹€. (ν•˜μ§€λ§Œ 그듀은 μ—¬μ „νžˆ ​​같은 μ‹œκ°„μž…λ‹ˆλ‹€.)

@carltongibson

μ—¬κΈ°μ—λŠ” 논리 였λ₯˜κ°€ μ—†μŠ΅λ‹ˆλ‹€.
이것은 같은 μ‹œκ°„μž…λ‹ˆλ‹€. "2016-12-19T10:00:00+5:30" 및 "2016-12-19T04:30:00Z" β€” μ–΄λŠ 정도 그듀이 μ–΄λ–»κ²Œ λŒμ•„μ˜€λ“  μƒκ΄€μ—†μŠ΅λ‹ˆκΉŒ?

IMHO 이것이 λ¬Έμ œμž…λ‹ˆλ‹€. λ°˜ν™˜λœ λ¬Έμžμ—΄μž…λ‹ˆλ‹€!
Django ν‘œμ€€ μ‹œκ°„λŒ€ 섀정을 μ‚¬μš©ν•˜κ³  λͺ¨λ“  ν…œν”Œλ¦Ώμ€ μ˜ˆμƒλŒ€λ‘œ μ˜¬λ°”λ₯Έ μ‹œκ°„ "2016-12-19T10:00:00+5:30" λ°˜ν™˜ν•˜μ§€λ§Œ DRFλŠ” 그렇지 μ•ŠμŠ΅λ‹ˆλ‹€. DRF λ°˜ν™˜ "2016-12-19T04:30:00Z" .
λ‚΄ REST APIλ₯Ό μ‚¬μš©ν•˜λŠ” ν΄λΌμ΄μ–ΈνŠΈμ—λŠ” 논리, μ‹œκ°„ λ³€ν™˜ λ˜λŠ” λ‚ μ§œ/μ‹œκ°„ λ¬Έμžμ—΄ 해석이 μ—†μŠ΅λ‹ˆλ‹€.
즉, DRF μ‘λ‹΅μ˜ datetime이 Django Template "response"와 동일할 κ²ƒμœΌλ‘œ μ˜ˆμƒν•©λ‹ˆλ‹€. μ„œλ²„λŠ” ν΄λΌμ΄μ–ΈνŠΈμ— λŒ€ν•œ λͺ¨λ“  데이터λ₯Ό μ€€λΉ„ν•˜κ³  ν΄λΌμ΄μ–ΈνŠΈλŠ” 이λ₯Ό λ³΄μ—¬μ£ΌκΈ°λ§Œ ν•©λ‹ˆλ‹€.

μ–΄μ¨Œλ“ , 이 ν™˜μƒμ μΈ ν”„λ‘œμ νŠΈμ— λŒ€ν•œ κ·€ν•˜μ˜ 인내, 지원 및 ν›Œλ₯­ν•œ μž‘μ—…μ— λŒ€ν•΄ λŒ€λ‹¨νžˆ κ°μ‚¬ν•©λ‹ˆλ‹€!

@vpistis μ—¬κΈ°μ„œ λ‚΄ μš”μ μ€ ν‘œμ‹œλœ λ‚ μ§œκ°€ μ •ν™•ν•˜κ³  ν‘œν˜„μ΄ μ˜ˆμƒλ˜μ§€ μ•ŠλŠ”λ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. κΈ°λ³Έ Date둜 ꡬ문 λΆ„μ„ν•˜λŠ” μ¦‰μ‹œ μ–Έμ–΄κ°€ 이λ₯Ό μ²˜λ¦¬ν•˜μ§€λ§Œ 차이가 μ—†μŠ΅λ‹ˆλ‹€.

μ‚¬μš©μžκ°€ λ‚ μ§œ λ¬Έμžμ—΄μ„ λ‚ μ§œλ‘œ ꡬ문 뢄석할 κ²ƒμœΌλ‘œ μ˜ˆμƒν•˜μ§€λ§Œ μ›μ‹œ λ¬Έμžμ—΄μ„ μ‚¬μš©ν•˜λŠ” λŒ€μ‹  ν΄λΌμ΄μ–ΈνŠΈ μ–Έμ–΄κ°€ 이λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.

λ‚˜λŠ” 당신이 μ›μ‹œ λ¬Έμžμ—΄μ„ μ†ŒλΉ„ν•œλ‹€λ©΄ λ‹Ήμ‹ μ˜ κΈ°λŒ€κ°€ μ—¬κΈ°μ—μ„œ μΆ©μ‘±λ˜μ§€ μ•Šμ„ κ²ƒμ΄λΌλŠ” 점을 μΈμ •ν•©λ‹ˆλ‹€. (ν•˜μ§€λ§Œ κ·Έλ ‡κ²Œ ν•˜μ§€ λ§ˆμ„Έμš”. UNIX νƒ€μž„μŠ€νƒ¬ν”„λ₯Ό 보낸닀고 상상해 λ³΄μ„Έμš”. μ›μ‹œ νƒ€μž„μŠ€νƒ¬ν”„λ₯Ό μ†ŒλΉ„ν•  방법이 μ—†μŠ΅λ‹ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈ μ–Έμ–΄λ‘œ 된 것이 무엇이든 μ μ ˆν•œ Date 객체둜 λ³€ν™˜ν•˜μ‹­μ‹œμ˜€.)

이에 λŒ€ν•΄ PR을 ν•˜κ²Œ λ˜μ–΄ 정말 κΈ°μ©λ‹ˆλ‹€. (아직 μ•ˆ λ‹«μ•˜μ–΄μš”!)

κ·ΈλŸ¬λ‚˜ 보고된 지 거의 2년이 지났고 첫 번째 의견이 λ‚˜μ˜¨ 지 9κ°œμ›”μ΄ μ§€λ‚¬μŠ΅λ‹ˆλ‹€(λ‹Ήμ‹ μ˜ 것, 1λ…„ ν›„). 아무도 μš°λ¦¬μ—κ²Œ μ‹€νŒ¨ν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό 주지 μ•Šμ•˜μŠ΅λ‹ˆλ‹€. 그것은 λˆ„κ΅¬μ—κ²Œλ‚˜ κ·Έλ ‡κ²Œ μ€‘μš”ν•  수 μ—†μŠ΅λ‹ˆλ‹€. 그만큼 μ‹œκ°„μ„ λ°°λΆ„ν•˜κΈ° μ–΄λ ΅λ‹€.

(λ”°λΌμ„œ λ‚˜λŠ” PR이 λ‚˜νƒ€λ‚˜λ©΄ PR을 ν•  κ²ƒμ΄λΌλŠ” 근거둜 그것을 λ‹«λŠ” κ²½ν–₯이 μžˆμŠ΅λ‹ˆλ‹€)

μ•ˆλ…•ν•˜μ„Έμš” μ—¬λŸ¬λΆ„, 이것은 #5408둜 μˆ˜μ •λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. λΆ„κΈ°λ₯Ό μ„€μΉ˜ν•˜κ³  λͺ¨λ“  것이 μ˜ˆμƒλŒ€λ‘œ μž‘λ™ν•˜λŠ”μ§€ 확인할 μ‹œκ°„μ΄ μžˆλ‹€λ©΄ ν™˜μƒμ μΌ κ²ƒμž…λ‹ˆλ‹€. 감사 ν•΄μš”!

λ‚˜λŠ” λ¬Έμ œκ°€ μ–΄λ–»κ²Œ λ“  λ‹€μ‹œ λ„μž…λ˜μ—ˆλ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

κΈ°λ³Έ TZλ₯Ό UTCμ—μ„œ 유럽/μ•”μŠ€ν…Œλ₯΄λ‹΄μœΌλ‘œ λ³€κ²½ν–ˆμ„ λ•Œ ν…ŒμŠ€νŠΈ 쀑 ν•˜λ‚˜κ°€ μ‹€νŒ¨ν–ˆκ³  DRFκ°€ κΈ°λ³Έ TZ와 λ‹€λ₯Έ κ²ƒμœΌλ‘œ μ§λ ¬ν™”ν•˜κ³  μžˆμŒμ„ μ•Œμ•˜μŠ΅λ‹ˆλ‹€.

νŽΈμ§‘: λ¬Έμ œλŠ” ν…ŒμŠ€νŠΈ/곡μž₯ μ„€μ •κ³Ό κ΄€λ ¨λ˜μ—ˆμŠ΅λ‹ˆλ‹€.


μ•„λž˜μ—μ„œ 섀정을 ν…ŒμŠ€νŠΈν•˜μ‹­μ‹œμ˜€.

λͺ¨λΈ

class Something(StampedModelMixin):
    MIN_VALUE = 1
    MAX_VALUE = 500

    id = models.BigAutoField(primary_key=True)  # pylint: disable=blacklisted-name
    product_id = models.BigIntegerField(db_index=True)
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    percentage = models.IntegerField()
    enabled = models.IntegerField()

곡μž₯

class SomethingFactory(factory.django.DjangoModelFactory):
    """ Base Factory to create records for Something

    """
    start_time = factory.Faker('date_time', tzinfo=get_default_timezone())
    end_time = factory.Faker('date_time', tzinfo=get_default_timezone())
    percentage = factory.Faker('random_int', min=1, max=500)
    enabled = factory.Faker('random_element', elements=[0, 1])

    class Meta:  # pylint: disable=missing-docstring
        model = Something

λ‹¨μœ„ ν…ŒμŠ€νŠΈ

class TestSomething:
    def test__get__empty(self):
        # preparation of data
        series = SeriesFactory.create(product_id=2)
        SomethingFactory.create_batch(3, product_id=1)

        # prepare request params
        url = reverse('series-somethings', kwargs={'pk': series.pk})

        # call the endpoint
        response = self.client.get(url)

        # asserts
        assert response.data == []

    def test__get__single(self):
        # preparation of data
        series = SeriesFactory.create(product_id=1)
        old_somethings = SomethingFactory.create_batch(1, product_id=1)

        # prepare request params
        url = reverse('series-somethings', kwargs={'pk': series.pk})

        # call the endpoint
        response = self.client.get(url)

        # asserts
        assert SomethingSerializer(old_somethings, many=True).data == response.data

보닀

class SomethingElseView(APILogMixin, ModelViewSet):
    @action(detail=True, methods=['get'])
    def somethings(self, request, pk=None):
        """ GET endpoint for Somethings

        .. seealso:: :func:`rest_framework.decorators.action`
        """
        otherthings = self.get_object()
        something_qs = Something.objects.all()
        something_qs = something_qs.filter(product_id=otherthings.product_id)
        serializer = self.something_serializer_class(something_qs, many=True)
        return Response(serializer.data)

직렬 λ³€ν™˜κΈ°

class SomethingSerializer(serializers.ModelSerializer):

    class Meta:
        model = Something
        list_serializer_class = SomethingListSerializer
        fields = '__all__'
        extra_kwargs = {
            'percentage': {'min_value': Something.MIN_VALUE,
                           'max_value': Something.MAX_VALUE}
        }
        read_only_fields = ('id',
                            'ts_activated',
                            'ts_created',
                            'ts_updated')

ν…ŒμŠ€νŠΈ ipdb κ²°κ³Ό

ipdb> old_somethings
[{'product_id': 1, 'start_time': datetime.datetime(2011, 7, 13, 1, 10, 33, tzinfo=<DstTzInfo 'Europe/Amsterdam' LMT+0:20:00 STD>), 'end_time': datetime.datetime(2003, 3, 10, 9, 31, tzinfo=<DstTzInfo 'Europe/Amsterdam' LMT+0:20:00 STD>), 'percentage': 103, 'enabled': 0}]
ipdb> response.data
[OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:16:33'), ('ts_updated', '2019-02-27 14:16:33'), ('product_id', 1), ('start_time', '2011-07-13 02:50:33'), ('end_time', '2003-03-10 10:11:00'), ('percentage', 103), ('enabled', 0)])]

검사 κ²°κ³Ό

E       AssertionError: assert [OrderedDict(...nabled', 0)])] == [OrderedDict([...nabled', 0)])]
E         At index 0 diff: OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 01:10:33'), ('end_time', '2003-03-10 09:31:00'), ('percentage', 103), ('enabled', 0)]) != OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 02:50:33'), ('end_time', '2003-03-10 10:11:00'), ('percentage', 103), ('enabled', 0)])
E         Full diff:
E         - [OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 01:10:33'), ('end_time', '2003-03-10 09:31:00'), ('percentage', 103), ('enabled', 0)])]
E         ?                                                                                                                                                       ^^^^^^^^^^                          ^^^^^^^^^^^
E         + [OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 02:50:33'), ('end_time', '2003-03-10 10:11:00'), ('percentage', 103), ('enabled', 0)])]
E         ?

μŠ€νƒ:

Django==2.0.10
djangorestframework==3.9.0
factory-boy==2.11.1
Faker==0.8.18
pytz==2018.9

μ•ˆλ…•ν•˜μ„Έμš” @diegueus9 - 이것을 더 κ°„λ‹¨ν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ‘œ 쀄일 수 μžˆμŠ΅λ‹ˆκΉŒ? μ§λ ¬ν™”λœ κ°€μ§œ 데이터와 보기의 응닡 데이터λ₯Ό λΉ„κ΅ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ μ‹€μ œ μ˜ˆμƒ 값이 무엇인지 λͺ…ν™•ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 일뢀 κ²°κ³Όλ₯Ό ν•˜λ“œμ½”λ”©λœ κ°’κ³Ό λΉ„κ΅ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 예,

assert SomethingSerializer(old_somethings, many=True).data == {'blah':'blah'}

@rpkilby λ‹΅λ³€ κ°μ‚¬ν•©λ‹ˆλ‹€. λ‚΄ μ‹€μˆ˜μ˜€μŠ΅λ‹ˆλ‹€. λ‚΄ λ‹¨μœ„ ν…ŒμŠ€νŠΈμ˜ λ¬Έμ œλŠ” DBμ—μ„œ μƒˆλ‘œ κ³ μΉ˜μ§€ μ•Šκ³  factory-boy/fakerλ₯Ό μ‚¬μš©ν•˜κ³  μžˆμ—ˆκΈ° λ•Œλ¬Έμ— 차이점이 μžˆμŠ΅λ‹ˆλ‹€. 방금 μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€.

    for old_something in old_somethings:
        old_something.refresh_from_db()

이전 λŒ“κΈ€μ„ μ œκ±°ν•΄μ•Ό ν•©λ‹ˆκΉŒ μ•„λ‹ˆλ©΄ λ‹€λ₯Έ μ‚¬λžŒμ΄ λ™μΌν•œ μ˜€νƒμ§€λ₯Ό κ²½ν—˜ν•  경우λ₯Ό λŒ€λΉ„ν•˜μ—¬ 남겨 두어야 ν•©λ‹ˆκΉŒ?

μ•ˆλ…•ν•˜μ„Έμš” @diegueus9 , κ±±μ • λ§ˆμ„Έμš” - μ €λŠ” details νƒœκ·Έμ— μ½”λ“œλ₯Ό μˆ¨κ²ΌμŠ΅λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰