1

I am writing an URL shortener application in Django. Where i want to check whether a URL is expired or not (URL is only valid for 3 hours). Below is my models.py but it is not working I am getting error can't subtract datetime object

import uuid
import base64
import datetime
from django.db import models
from django.contrib import admin
#------------------------------------------------------------------------------ 

def _generateShortUrl():
    """
        This function will generate base64 encoded id
    """
    return base64.urlsafe_b64encode(uuid.uuid1().bytes)[:6]


class link(models.Model):
    """
        This is a link class 
    """
    link = models.URLField()                                    # To store user entered URL
    hits = models.IntegerField(default=0)                       # How many hits for particular URL
    last_used = models.DateTimeField(auto_now=True)             # When URL is last used 
    short_url = models.CharField(max_length=6,unique=True)      # base64 URL encoded id  

    def linkValidate(self):
        timediff = datetime.datetime.now() - self.last_used                       
        return timediff.min

    def save(self, *args, **kwargs):
        """
            Custom Save method for link model 
        """
        self.short_url = _generateShortUrl()        
        super(link, self).save(*args, **kwargs)   


class user_info(models.Model):
    """
        This is a user_info class 
    """
    user_agent = models.TextField()                 # Stores user_agent name used by user
    user_ip = models.ManyToManyField(link)          # Stores user's IP

    def userIP(self):
        """Method to return tags related to store"""
        return ','.join([t.link for t in self.link.all()])

#------------------------------------------------------------------------------ 

class linkAdmin(admin.ModelAdmin):
    """
        link admin class
    """
    list_display = ('link','hits','short_url','last_used',
                    'linkValidate')
    ordering = ('hits',)

class userInfoAdmin(admin.ModelAdmin):
    """
        user_info admin class
    """
    list_display = ('user_agent','userIP')

#------------------------------------------------------------------------------ 
admin.site.register(link,linkAdmin)
admin.site.register(user_info,userInfoAdmin)

Can someone please help me.

Vaibhav Jain
  • 5,287
  • 10
  • 54
  • 114
  • Do you have time zone support enabled? `USE_TZ` in settings is `True`? – alecxe Sep 06 '13 at 18:03
  • I imagine someone will beat me to the real fix for your question, but I have to ask... aren't you playing with fire that your URL's are going to be unique for the first 4ish letters? – Foon Sep 06 '13 at 18:05
  • `@alecxe` it is there in my settings.py ...`@Foon` thanks for the tip i will fix it .... – Vaibhav Jain Sep 06 '13 at 18:07
  • @user2217267 actually, I may have misspoke a little... I ran a quick test in which I generated lots of uids... using :6, I still haven't had a collision. 6 bytes works out (after doing 3/4 due to base64 encoding) to 36 bits, 2^36 = 68719476736; even taking account the birthday paradox, your odds are pretty good it'll be a while before there's a problem if you're deleting them after 3 hours). Second comment... did you mean .min to be minutes (which is what I interrupted it as) or did you just mean to return a big negative while you were debugging – Foon Sep 06 '13 at 18:15
  • I actually wanted to return the number of hours elapsed ...... – Vaibhav Jain Sep 06 '13 at 18:18

1 Answers1

4

Since you have time zone support enabled, self.last_used is a timezone-aware datetime object, datetime.datetime.now() is not.

Try this instead:

timediff = datetime.datetime.utcnow() - self.last_used.replace(tzinfo=None)

Another option is to make your now() timezone-aware using make_aware():

from django.utils import timezone
now = timezone.make_aware(datetime.datetime.now(), timezone.get_default_timezone())
timediff = now() - self.last_used

Also see:

Community
  • 1
  • 1
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195