将属性添加到Django中的自定义字段

时间:2010-12-02 07:29:32

标签: django attributes field

我会尽可能简短。

我希望能够做到这一点

{{ video.youtube_url.video_id }}

通过实现以下自定义字段:

class YouTubeURLField(URLField):
    description = _("YouTubeURL")

    def _video_id(self):
      return re.search('(?<=\?v\=)[\w-]+', self.value)
    video_id = property(_video_id)

    def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
      super(YouTubeURLField, self).__init__(**kwargs)
      kwargs['max_length'] = kwargs.get('max_length', 200)
      CharField.__init__(self, verbose_name, name, **kwargs)
      self.validators.append(YouTubeURLValidator(verify_exists=verify_exists))

此:

    def _video_id(self):
      return re.search('(?<=\?v\=)[\w-]+', self.value)
    video_id = property(_video_id)

未成功向我的自定义YouTubeURLField添加“video_id”属性。

其他一切都完美无缺。

我理解在YouTube自定义字段方面可能有更好的设计考虑因素,但我宁愿理解,首先,为什么这不起作用。

3 个答案:

答案 0 :(得分:2)

Django字段是descriptors,这意味着访问它们不会返回字段,而是返回字段值。您需要override the Django field methods才能返回具有您关注的属性的对象,以及明确定义的__unicode__()方法。

答案 1 :(得分:0)

是否有理由不能将其作为模型的属性?

为了从不直接包含在字段中的对象访问数据,我经常按照以下方式实现模式:

class: Sheep(models.Model):
    name = models.CharField(max_length=200)

    @property
    def sheep_says(self):
        return "Baa... my name is %s ... baa" % self.name

然后您将在模板中访问:

{{ sheep.sheep_says }}

答案 2 :(得分:0)

我想这样做,因为从设计角度看它似乎更有意义。视频ID是YouTube网址的属性,而不是模型本身的属性。

我明白了。我重写了to_python函数以返回一个YouTubeURL对象。

class YouTubeURL(object):
  def __init__(self, value):
    self.value = value

  @property
  def video_id(self):
    regex = re.compile(r'/v/([A-Za-z0-9\-_]+)', re.IGNORECASE)

    id = regex.search(self.value)
    return id.group(1)

  def __unicode__(self):
    return "%s" % (self.value,)

  def __str__(self):
    return "%s" % (self.value,)

  def __len__(self):
    return len(self.value)

class YouTubeURLField(URLField):
    description = _("YouTubeURL")

    __metaclass__ = SubfieldBase

    def to_python(self, value):
      return YouTubeURL(value)

    def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
      super(YouTubeURLField, self).__init__(**kwargs)
      kwargs['max_length'] = kwargs.get('max_length', 200)
      CharField.__init__(self, verbose_name, name, **kwargs)
      self.validators.append(YouTubeURLValidator(verify_exists=verify_exists))