IntegerField에 시간 간격을 분으로 저장합니다. 내 프런트 엔드 양식 (모델 양식)에서 필자는 입력을 분 동안 하나의 필드로, 시간으로 하나의 필드로 나누고 싶습니다. 또한 InLineFormset을 사용할 수 있기를 원합니다. 이것이 좋은 방법으로 할 수 있습니까? 내가 자바 스크립트를 사용할 수 있지만, 나에게 좋은 해결책처럼 보이지 않는가?IntegerField를 모델 양식의 시간 및 초 필드로 분할하는 Django 사용자 정의 위젯
2
A
답변
5
MultiWidget을 사용하려고합니다. 필드 자체를 재정의하는 것이 좋습니다. docs for creating custom fields을 살펴보십시오.
가능한 경우 데이터를 python timedelta을 나타내는 부동 소수점으로 저장하는 것이 좋습니다. 필드에 몇 가지 사용자 정의 메소드를 추가 할 수 있습니다. timedelta를 사용하면 필드로 계산을 수행하려는 경우 유용합니다.
아마도 form validation에서 약간의 독서를하고 싶을 것입니다.
from datetime import timedelta
from django import forms
from django.db import models
from django.core import exceptions, validators
def validate_timedelta(value):
if not isinstance(value, timedelta):
raise exceptions.ValidationError('A valid time period is required')
class SplitHoursMinsWidget(forms.widgets.MultiWidget):
def __init__(self, *args, **kwargs):
widgets = (
forms.TextInput(),
forms.TextInput(),
forms.TextInput(),
)
super(SplitHoursMinsWidget, self).__init__(widgets, *args, **kwargs)
def decompress(self, value):
if value:
return [value.seconds // 3600, (value.seconds // 60) % 60,
value.seconds % 60]
return [None, None, None]
def format_output(self, rendered_widgets):
return ("HH:MM:SS " + rendered_widgets[0] + ":" + rendered_widgets[1] +
":" + rendered_widgets[2])
def value_from_datadict(self, data, files, name):
hours_mins_secs = [
widget.value_from_datadict(data, files, name + '_%s' % i)
for i, widget in enumerate(self.widgets)]
try:
time_delta = (timedelta(hours=float(hours_mins_secs[0])) +
timedelta(minutes=float(hours_mins_secs[1])) +
timedelta(seconds=float(hours_mins_secs[2])))
except ValueError:
return None
else:
return time_delta
class TimeDeltaFormField(forms.Field):
widget = SplitHoursMinsWidget
class TimeDeltaField(models.Field):
__metaclass__ = models.SubfieldBase
description = "Field to hold a python timedelta object"
default_validators = [validate_timedelta, ]
def to_python(self, value):
if value in validators.EMPTY_VALUES or isinstance(value, timedelta):
return value
try:
return timedelta(seconds=float(value))
except:
raise exceptions.ValidationError('A valid time period is required')
def get_prep_value(self, value):
return float(value.days * 86400 + value.seconds)
def get_internal_type(self):
return 'FloatField'
def formfield(self, **kwargs):
defaults = {'form_class': TimeDeltaFormField}
defaults.update(kwargs)
return super(TimeDeltaField, self).formfield(**defaults)
그것은이 그것으로 가능 (유용한 입력 레벨의 유효성 검사를 제공하지 않는다는 것을 주목할 필요가 -
나는 장고 1.4에 다음 시간, 분, 플로트를 기반으로 사용자 정의 필드와 초 multiwidget을 테스트 한 분과 초 입력 요소 모두에 60 이상을 입력하십시오). 아마 그것은 자바 스크립트로 가장 잘 해결 될 수 있습니다.
감사합니다. MultiWidget 링크를 자세히 살펴 보겠습니다. timedelta 정보 : IntegerField 저장 시간과 비교하여 설명하는 방식으로 timedelta를 사용한 성능에 대해 어떻게 생각합니까? 나는 많은 합계가있을 훈련 로그를 만들고있다. – LordNelson
저는 이것이 문제가되어야한다고 생각하지 않습니다. (int 계산은 생각보다 약 두 배 빨라질 것입니다.하지만 이것을 최적화 할 필요가 있는지 의심 스럽습니다. 앱에서 병목 현상이 발생할 가능성은 거의 없습니다.) –
@LordNelson 시간, 분, 초 위젯을 가진 float를 사용하는 기본 필드에 대한 코드를 추가했습니다. 그것은 시간과 초 또는 정수 기본 필드에 대해이를 상당히 간단하게 조정해야합니다. –