models.py 3.97 KB
Newer Older
1
2
3
# Future Imports
from __future__ import unicode_literals, absolute_import, print_function, division

David Haynes's avatar
David Haynes committed
4
5
6
# Python stdlib Imports
import string

7
# Django Imports
8
from django.db import models
Jean Michel Rouly's avatar
Jean Michel Rouly committed
9
10
from django.contrib.auth.models import User
from django.utils import timezone
11
from django.core.cache import cache
12
13
from django.db.models.signals import post_save
from django.dispatch import receiver
14
from django.utils.encoding import python_2_unicode_compatible
15
16

# Other Imports
17
from hashids import Hashids # http://hashids.org/python/
18

19
# generate the salt and initialize Hashids
20
hashids = Hashids(salt="srct.gmu.edu", alphabet=(string.ascii_lowercase + string.digits))
Jean Michel Rouly's avatar
Jean Michel Rouly committed
21

22
@python_2_unicode_compatible
23
class RegisteredUser(models.Model):
24
    """
David Haynes's avatar
David Haynes committed
25
26
    This is simply a wrapper model for the user object  which, if an object
    exists, indicates that that user is registered.
27
    """
Jean Michel Rouly's avatar
Jean Michel Rouly committed
28

29
30
    # Let's associate a User to this RegisteredUser
    user = models.OneToOneField(User)
Jean Michel Rouly's avatar
Jean Michel Rouly committed
31

32
    # What is your name?
33
    full_name = models.CharField(
34
35
        blank=False,
        max_length=100,
36
    )
Jean Michel Rouly's avatar
Jean Michel Rouly committed
37

38
    # What organization are you associated with?
39
    organization = models.CharField(
40
41
        blank=False,
        max_length=100,
42
43
    )

44
    # Why do you want to use Go?
45
    description = models.TextField(blank=True)
46

47
    # Have you filled out the registration form?
48
    registered = models.BooleanField(default=False)
49

50
    # Are you approved to use Go?
51
    approved = models.BooleanField(default=False)
52

David Haynes's avatar
David Haynes committed
53
54
55
    # Is this User Blocked?
    blocked = models.BooleanField(default=False)

56
    def __str__(self):
David Haynes's avatar
David Haynes committed
57
58
59
60
        """
        str(RegisteredUser)
        """

61
62
        return '<Registered User: %s - Approval Status: %s>' % (self.user, self.approved)

63

64
65
@receiver(post_save, sender=User)
def handle_regUser_creation(sender, instance, created, **kwargs):
David Haynes's avatar
David Haynes committed
66
67
68
69
70
    """
    When a post_save is called on a User object (and it is newly created), this 
    is called to create an associated RegisteredUser
    """

71
72
73
    if created:
        RegisteredUser.objects.create(user=instance)

74

75
@python_2_unicode_compatible
76
class URL(models.Model):
David Haynes's avatar
David Haynes committed
77
    """
David Haynes's avatar
David Haynes committed
78
79
80
    This model represents a stored URL redirection rule. Each URL has an
    owner, target url, short identifier, click counter, and expiration
    date.
David Haynes's avatar
David Haynes committed
81
    """
82

83
    # Who is the owner of this Go link
84
    owner = models.ForeignKey(RegisteredUser)
85
    # When was this link created?
David Haynes's avatar
David Haynes committed
86
    date_created = models.DateTimeField(default=timezone.now)
87

88
    # What is the target URL for this Go link
David Haynes's avatar
David Haynes committed
89
    target = models.URLField(max_length=1000)
90
    # What is the actual go link (short url) for this URL
David Haynes's avatar
David Haynes committed
91
    short = models.SlugField(max_length=20, primary_key=True)
92

93
    # how many people have visited this Go link
David Haynes's avatar
David Haynes committed
94
    clicks = models.IntegerField(default=0)
95
    # how many people have visited this Go link through the qr code
David Haynes's avatar
David Haynes committed
96
    qrclicks = models.IntegerField(default=0)
97
    # how many people have visited the go link through social media
David Haynes's avatar
David Haynes committed
98
    socialclicks = models.IntegerField(default=0)
99

100
    # does this Go link expire on a certain date
David Haynes's avatar
David Haynes committed
101
    expires = models.DateTimeField(blank=True, null=True)
102

103
    def __str__(self):
David Haynes's avatar
David Haynes committed
104
105
106
107
        """
        print(URL)
        """

David Haynes's avatar
David Haynes committed
108
        return '<Owner: %s - Target URL: %s>' % (self.owner.user, self.target)
109
110

    class Meta:
David Haynes's avatar
David Haynes committed
111
112
113
114
        """
        metadata for URLs
        """

115
        # they should be ordered by their short links
116
117
118
119
        ordering = ['short']

    @staticmethod
    def generate_valid_short():
David Haynes's avatar
David Haynes committed
120
121
122
123
        """
        legacy method to ensure that generated short URL's are valid
        should be updated to be simpler
        """
124
        if cache.get("hashids_counter") is None:
125
126
127
128
129
130
            cache.set("hashids_counter", URL.objects.count())
        cache.incr("hashids_counter")
        short = hashids.encrypt(cache.get("hashids_counter"))
        tries = 1
        while tries < 100:
            try:
David Haynes's avatar
David Haynes committed
131
                URL.objects.get(short__iexact = short)
132
133
                tries += 1
                cache.incr("hashids_counter")
134
            except URL.DoesNotExist as ex:
135
136
                return short
        return None