Working smarter not harder with Django

  • Sat 02 March 2013

  • I admit it...I often over-engineer the crap out of things. Lack of familiarity with Python's stdlib and/or all of Django's offerings, I will often make my own wheel when someone else has already put forth the effort and done so.

    And so in the beginning...well, let me go back before the beginning. An app I built allows users to upload images. Some of these images need to be in numerical order. There is a field in the model to support the image number, but early on it required the user to upload the image, then specify the number in which it was to be ordered. I know! BAD BARRY!!

    It was an irk of mine, it was a corner cut to get it out out the door. I am full of shame. It had always been my intention to come back later and clean that up, and today I did so.

    Here is how!

    The Model(.py)

    Class CommunityPicture(models.Model):
        event = models.ForeignKey(CommunityEvent)
        file = ImageWithThumbsField(upload_to="community", sizes=((125, 125), (250, 250), (640, 427),))
        slug = models.SlugField(max_length=50, blank=True)
        pgnumber = models.IntegerField(default=0)
    
        class Meta:
            ordering = ['pgnumber']
    
        def __unicode__(self):
            return '%s' '%s' % (self.event, self.file)
    
        @models.permalink
        def get_absolute_url(self, *args, **kwargs):
            return('admin-community-images', (), {
                'pk': self.event.id
                })
    
        def save(self, *args, **kwargs):
            self.slug = slugify.slugify(self.file.name)
            regex = re.compile(r'(\d+)')
            nonInteger = regex.findall(self.file.name)
            if not nonInteger:
                self.pgnumber = 0
            else:
                self.pgnumber = int(re.split(r'(\d+)', self.slug)[-2].lstrip('0'))
            super(CommunityPicture, self).save(*args, **kwargs)
    
        def delete(self, *args, **kwargs):
            self.file.delete(False)
            super(CommunityPicture, self).delete(*args, **kwargs)
    

    As I'm pasting this, others are going to see my horrible code. I look forward to the nasty tweets in the morning from some l33t hax04. Flame away!

    Allow me to shed light on the important part.

    def save(self, *args, **kwargs):
        self.slug = slugify.slugify(self.file.name)
        ## I want to capture [0-9]
        regex = re.compile(r'(\d+)')
        ## I need to capture a filename that might not have an integer in it's name.
        nonInteger = regex.findall(self.file.name)
        ## If it does not have an integer in it's file.name
        if not nonInteger:
            ## set the page number to 0 (this can really be any number)
            self.pgnumber = 0
        else:
            ## if it does have a number, give it to me, and strip any leading zeros.
            self.pgnumber = int(re.split(r'(\d+)', self.slug)[-2].lstrip('0'))
    

    Here is perhaps a little more in-depth on what it is doing.

    In [1]: import re
    
    In [2]: fileName7 = 'photo.jpg'
    
    In [3]: pattern = re.compile(r'(\d+)')
    
    In [4]: z = pattern.findall(fileName7)
    
    In [5]: z
    Out[5]: []
    

    I'm using stdlib re module. In the above example, my filename does not have an integer in it. Line 4 is doing the checking. Line 5 shows that the list is empty.

    From the code above:

    if not nonInteger:
        self.pgnumber = 0
    

    That is checking to see if the list is empty, if it is, set pgnumber to zero.

    Here is an example with an integer in the filename:

    In [1]: import re
    
    In [2]: fileName2 = 'IMG-00123.jpg'
    
    In [3]: pattern = re.compile(r'(\d+)')
    
    In [4]: z = pattern.findall(fileName2)
    
    In [5]: z
    Out[5]: ['00123']
    
    In [6]: foo = int(z[0])
    
    In [7]: foo
    Out[7]: 123
    

    While creating this, I have test (use the word test loosely here) coverage for these different file name scenarios. It is likely that it doesn't cover all the possible file name scenarios, but hopefully it gets most of them.

    fileName = 'IMG_00134.jpg'
    fileName2 = 'IMG-00123.jpg'
    fileName3 = '003.jpg'
    fileName4 = '4.jpg'
    fileName5 = '000-005.jpg'
    fileName6 = 'IMG123_006.jpg'
    fileName7 = 'photo.jpg'
    

    If you have any advice on how I may have done this differently/better, please feel free to comment below! Much appreciated!

    Comments !

    social