首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Django中创建一个ical duration字段?

如何在Django中创建一个ical duration字段?
EN

Stack Overflow用户
提问于 2012-11-28 11:00:49
回答 3查看 1.4K关注 0票数 0

我使用在管理站点注册的Django模型。我的模型中的一个字段表示持续时间。我想使用DateTimeField,但不是将值保存到数据库中的日期时间,而是将其保存为RFC5545 (ical)格式的varchar (例如,1天1小时1分1秒将存储为"P1DT1H1M1S")。我该怎么做呢?我应该覆盖DateTimeField吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-28 11:04:28

您可以为它创建一个自定义的Django字段,而不是覆盖DateTimeField。

https://docs.djangoproject.com/en/dev/howto/custom-model-fields/

票数 0
EN

Stack Overflow用户

发布于 2012-11-28 11:10:50

是的,只需创建model.Field.的子类并定义两个方法:

-将db值转换为python对象。

-这与to_python将对象转换为db值相反。

票数 0
EN

Stack Overflow用户

发布于 2012-11-30 03:31:09

谢谢bakkal和Pol。下面是我想出来的。

代码语言:javascript
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13597063

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档