python - 自定义 Django 模型字段中的 "object has no attribute"

标签 python django model field rfc5545

我正在尝试创建一个 Django 模型字段,该字段表示 HTML 中包含天、小时、分钟和秒文本输入字段的持续时间,并使用 ical 格式 (RFC5545) 将持续时间存储在数据库中。

(这与我在 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'

这让我很困惑...似乎 python 认为我的字段是前一个字段的属性,但前提是它是 CharField。有什么想法吗?

最佳答案

我是个傻子。问题是我将定义模型的文件命名为duration.py,因此与“duration”字段存在命名冲突。我重命名了该文件并且它起作用了。

关于python - 自定义 Django 模型字段中的 "object has no attribute",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13635320/

相关文章:

python - 列表理解无用变量

python - 在 Python 中使用 Bcrypt 散列密码时出错

python - 如何从 Django 目录外部访问文件

python - Django 数据库查询在比较字符串时给出意外的 'illegal double'

forms - Symfony 获取表单模型对象

java - 面板使用与父页面相同的模型

Python:检查字典中的键是否包含在字符串中

python - django 将以前的数据保存在数据库中

python - 如何在 django(python)的元组中删除多余的 ','

swift - 如何在 iOS 中模拟不同的外形尺寸?