HTML의 일,시, 분 및 초 텍스트 입력 필드가있는 기간을 나타내는 Django 모델 필드를 만들고 해당 기간을 사용하여 db에 저장하려고합니다. 형식 (RFC5545)."개체에 특성이 없습니다"Django 사용자 지정 모델 필드에
감사 bakkal 및 폴 :
(이이 How to create an ical duration field in Django?에 내 질문에 관련이있다) 여기내 접근 방식입니다. 아래는 내가 생각해내는 것입니다.
from django.db import models
from icalendar.prop import vDuration
from django.forms.widgets import MultiWidget
from django.forms import TextInput, IntegerField
from django.forms.util import flatatt
from django.forms.fields import MultiValueField
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
from django.utils.text import capfirst
from django.utils.translation import ugettext_lazy as _
from django.core import validators
from datetime import timedelta
def is_int(s):
try:
int(s)
return True
except ValueError:
return False
class Widget_LabelInputField(TextInput):
"""
Input widget with label
"""
input_type="numbers"
def __init__(self, labelCaption, attrs=None):
self.labelCaption = labelCaption
super(Widget_LabelInputField, self).__init__(attrs)
def _format_value(self, value):
if is_int(value):
return value
return '0'
def render(self, name, value, attrs=None):
if value is None:
value = '0'
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
if value != '':
# Only add the 'value' attribute if a value is non-empty.
final_attrs['value'] = force_unicode(self._format_value(value))
if (self.labelCaption):
typeString = self.labelCaption + ': '
else:
typeString = ''
return mark_safe(u'' + typeString + '<input%s style=\'width: 30px; margin-right: 20px\'/>' % flatatt(final_attrs))
class Widget_DurationField(MultiWidget):
"""
A Widget that splits duration input into two <input type="text"> boxes.
"""
def __init__(self, attrs=None):
widgets = (Widget_LabelInputField(labelCaption='days', attrs=attrs),
Widget_LabelInputField(labelCaption='hours', attrs=attrs),
Widget_LabelInputField(labelCaption='minutes', attrs=attrs),
Widget_LabelInputField(labelCaption='seconds', attrs=attrs)
)
super(Widget_DurationField, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
duration = vDuration.from_ical(value)
return [str(duration.days), str(duration.seconds // 3600), str(duration.seconds % 3600 // 60), str(duration.seconds % 60)]
return [None, None, None, None]
class Forms_DurationField(MultiValueField):
widget = Widget_DurationField
default_error_messages = {
'invalid_day': _(u'Enter a valid day.'),
'invalid_hour': _(u'Enter a valid hour.'),
'invalid_minute': _(u'Enter a valid minute.'),
'invalid_second': _(u'Enter a valid second.')
}
def __init__(self, *args, **kwargs):
errors = self.default_error_messages.copy()
if 'error_messages' in kwargs:
errors.update(kwargs['error_messages'])
fields = (
IntegerField(min_value=-9999, max_value=9999,
error_messages={'invalid': errors['invalid_day']},),
IntegerField(min_value=-9999, max_value=9999,
error_messages={'invalid': errors['invalid_hour']},),
IntegerField(min_value=-9999, max_value=9999,
error_messages={'invalid': errors['invalid_minute']},),
IntegerField(min_value=-9999, max_value=9999,
error_messages={'invalid': errors['invalid_second']},),
)
super(Forms_DurationField, self).__init__(fields, *args, **kwargs)
def compress(self, data_list):
if data_list:
if data_list[0] in validators.EMPTY_VALUES:
raise ValidationError(self.error_messages['invalid_day'])
if data_list[1] in validators.EMPTY_VALUES:
raise ValidationError(self.error_messages['invalid_hour'])
if data_list[2] in validators.EMPTY_VALUES:
raise ValidationError(self.error_messages['invalid_minute'])
if data_list[3] in validators.EMPTY_VALUES:
raise ValidationError(self.error_messages['invalid_second'])
return vDuration(timedelta(days=data_list[0],hours=data_list[1],minutes=data_list[2],seconds=data_list[3]))
return None
class Model_DurationField(models.Field):
description = "Duration"
def __init__(self, *args, **kwargs):
super(Model_DurationField, self).__init__(*args, **kwargs)
def db_type(self, connection):
return 'varchar(255)'
def get_internal_type(self):
return "Model_DurationField"
def to_python(self, value):
if isinstance(value, vDuration) or value is None:
return value
return vDuration.from_ical(value)
def get_prep_value(self, value):
return value.to_ical()
def formfield(self, **kwargs):
defaults = {
'form_class': Forms_DurationField,
'required': not self.blank,
'label': capfirst(self.verbose_name),
'help_text': self.help_text}
defaults.update(kwargs)
return super(Model_DurationField, self).formfield(**defaults)
은 다음과 같은 모델에서 작동합니다
class TestModel(models.Model):
ID = models.CharField(max_length=255)
start = models.DateTimeField(null=True)
#duration = models.CharField(max_length=255,null=True) commented out
otherDuration = duration.Model_DurationField(null=True)
하지만이 하나
class TestModel(models.Model):
ID = models.CharField(max_length=255)
start = models.DateTimeField(null=True)
duration = models.CharField(max_length=255,null=True) # not commented out
otherDuration = duration.Model_DurationField(null=True)
나는 다음과 같은 오류 얻을 :
File "/somepath/models.py", line 5, in TestModel
otherDuration = duration.Model_DurationField(null=True)
AttributeError: 'CharField' object has no attribute 'Model_DurationField'
나 퍼즐 ... 파이썬은 내 필드를 이전 필드의 특성이지만 CharField 인 경우에만 어떤 아이디어?
비슷한 문제가 있습니다. 뷰의 이름을 모델 이름과 동일하게 지정했습니다. – User