1

I'll be as brief as possible.

I want to able to do this

{{ video.youtube_url.video_id }}

by implementing something like the following custom field:

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))

This:

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

Does not sucessfully add a "video_id" attribute to my custom YouTubeURLField.

Everything else works flawlessly.

I understand there maybe better design considerations in terms of the YouTube custom field, but I'd rather just understand, first, why this doesn't work.

3 Answers 3

2

Django fields are descriptors, which means that accessing them does not return the field, but rather the field value. You will need to override the Django field methods in order to return an object that has the attributes you care about, as well as a sanely-defined __unicode__() method.

Sign up to request clarification or add additional context in comments.

Comments

0

Is there a reason you can't have it as a property of the model?

In order to access data from an object not directly contained within the fields I frequently implement a pattern along the lines of:

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

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

Which you would then access in the template with:

{{ sheep.sheep_says }}

Comments

-1

I wanted to do it this way, because it seems it makes more sense from a design stand point. The video id is an attribute of the YouTube URL and not of the model itself.

I figured it out. I overrode the to_python function to return a YouTubeURL object.

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))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.