models.py 3.87 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
25
26
27
    """
        This is simply a wrapper model for the user object  which, if an object
        exists, indicates that that user is registered.
    """
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
56
    # Is this User Blocked?
    blocked = models.BooleanField(default=False)

    # str(RegisteredUser)
57
    def __str__(self):
58
59
        return '<Registered User: %s - Approval Status: %s>' % (self.user, self.approved)

60

61
62
63
64
# When a post_save is called on a User object (and it is newly created), this is
# called to create an associated RegisteredUser
@receiver(post_save, sender=User)
def handle_regUser_creation(sender, instance, created, **kwargs):
65
66
67
    if created:
        RegisteredUser.objects.create(user=instance)

68

69
@python_2_unicode_compatible
70
class URL(models.Model):
David Haynes's avatar
David Haynes committed
71
72
73
74
75
    """
        This model represents a stored URL redirection rule. Each URL has an
        owner, target url, short identifier, click counter, and expiration
        date.
    """
76

77
    # Who is the owner of this Go link
78
    owner = models.ForeignKey(RegisteredUser)
79
    # When was this link created?
David Haynes's avatar
David Haynes committed
80
    date_created = models.DateTimeField(default=timezone.now)
81

82
    # What is the target URL for this Go link
David Haynes's avatar
David Haynes committed
83
    target = models.URLField(max_length=1000)
84
    # What is the actual go link (short url) for this URL
David Haynes's avatar
David Haynes committed
85
    short = models.SlugField(max_length=20, primary_key=True)
86

87
    # how many people have visited this Go link
David Haynes's avatar
David Haynes committed
88
    clicks = models.IntegerField(default=0)
89
    # how many people have visited this Go link through the qr code
David Haynes's avatar
David Haynes committed
90
    qrclicks = models.IntegerField(default=0)
91
    # how many people have visited the go link through social media
David Haynes's avatar
David Haynes committed
92
    socialclicks = models.IntegerField(default=0)
93

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

97
    # print(URL)
98
    def __str__(self):
David Haynes's avatar
David Haynes committed
99
        return '<Owner: %s - Target URL: %s>' % (self.owner.user, self.target)
100

101
    # metadata for URL's
102
    class Meta:
103
        # they should be ordered by their short links
104
105
        ordering = ['short']

106
    # legacy method to ensure that generated short URL's are valid
David Haynes's avatar
David Haynes committed
107
    # should be updated to be simpler
108
109
    @staticmethod
    def generate_valid_short():
110
        if cache.get("hashids_counter") is None:
111
112
113
114
115
116
            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
117
                URL.objects.get(short__iexact = short)
118
119
                tries += 1
                cache.incr("hashids_counter")
120
            except URL.DoesNotExist as ex:
121
122
                return short
        return None