models.py 4.09 KB
Newer Older
1
2
3
4
"""
go/models.py
"""

5
# Future Imports
6
7
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
8

David Haynes's avatar
David Haynes committed
9
10
11
# Python stdlib Imports
import string

12
# Django Imports
Jean Michel Rouly's avatar
Jean Michel Rouly committed
13
from django.contrib.auth.models import User
14
from django.core.cache import cache
15
from django.db import models
16
17
from django.db.models.signals import post_save
from django.dispatch import receiver
18
from django.utils import timezone
19
from django.utils.encoding import python_2_unicode_compatible
20
21

# Other Imports
22
from hashids import Hashids  # http://hashids.org/python/
23

24
# generate the salt and initialize Hashids
25
26
27
HASHIDS = Hashids(
    salt="srct.gmu.edu", alphabet=(string.ascii_lowercase + string.digits)
)
Jean Michel Rouly's avatar
Jean Michel Rouly committed
28

29
@python_2_unicode_compatible
30
class RegisteredUser(models.Model):
31
    """
32
    This is simply a wrapper model for the user object which, if an object
David Haynes's avatar
David Haynes committed
33
    exists, indicates that that user is registered.
34
    """
Jean Michel Rouly's avatar
Jean Michel Rouly committed
35

36
37
    # Let's associate a User to this RegisteredUser
    user = models.OneToOneField(User)
Jean Michel Rouly's avatar
Jean Michel Rouly committed
38

39
    # What is your name?
40
    full_name = models.CharField(
41
42
        blank=False,
        max_length=100,
43
    )
Jean Michel Rouly's avatar
Jean Michel Rouly committed
44

45
    # What organization are you associated with?
46
    organization = models.CharField(
47
48
        blank=False,
        max_length=100,
49
50
    )

51
    # Why do you want to use Go?
52
    description = models.TextField(blank=True)
53

54
    # Have you filled out the registration form?
55
    registered = models.BooleanField(default=False)
56

57
    # Are you approved to use Go?
58
    approved = models.BooleanField(default=False)
59

David Haynes's avatar
David Haynes committed
60
61
62
    # Is this User Blocked?
    blocked = models.BooleanField(default=False)

63
    def __str__(self):
David Haynes's avatar
David Haynes committed
64
65
66
67
        """
        str(RegisteredUser)
        """

68
69
70
        return '<Registered User: %s - Approval Status: %s>' % (
            self.user, self.approved
        )
71

72

73
74
@receiver(post_save, sender=User)
def handle_regUser_creation(sender, instance, created, **kwargs):
David Haynes's avatar
David Haynes committed
75
    """
76
    When a post_save is called on a User object (and it is newly created), this
David Haynes's avatar
David Haynes committed
77
78
79
    is called to create an associated RegisteredUser
    """

80
81
82
    if created:
        RegisteredUser.objects.create(user=instance)

83

84
@python_2_unicode_compatible
85
class URL(models.Model):
David Haynes's avatar
David Haynes committed
86
    """
David Haynes's avatar
David Haynes committed
87
88
89
    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
90
    """
91

92
    # Who is the owner of this Go link
93
    owner = models.ForeignKey(RegisteredUser)
94
    # When was this link created?
David Haynes's avatar
David Haynes committed
95
    date_created = models.DateTimeField(default=timezone.now)
96

97
    # What is the target URL for this Go link
David Haynes's avatar
David Haynes committed
98
    target = models.URLField(max_length=1000)
99
    # What is the actual go link (short url) for this URL
David Haynes's avatar
David Haynes committed
100
    short = models.SlugField(max_length=20, primary_key=True)
101

102
    # how many people have visited this Go link
David Haynes's avatar
David Haynes committed
103
    clicks = models.IntegerField(default=0)
104
    # how many people have visited this Go link through the qr code
David Haynes's avatar
David Haynes committed
105
    qrclicks = models.IntegerField(default=0)
106
    # how many people have visited the go link through social media
David Haynes's avatar
David Haynes committed
107
    socialclicks = models.IntegerField(default=0)
108

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

112
    def __str__(self):
David Haynes's avatar
David Haynes committed
113
114
115
116
        """
        print(URL)
        """

117
118
119
        return '<Owner: %s - Target URL: %s>' % (
            self.owner.user, self.target
        )
120
121

    class Meta:
David Haynes's avatar
David Haynes committed
122
123
124
125
        """
        metadata for URLs
        """

126
        # they should be ordered by their short links
127
128
129
130
        ordering = ['short']

    @staticmethod
    def generate_valid_short():
David Haynes's avatar
David Haynes committed
131
132
133
134
        """
        legacy method to ensure that generated short URL's are valid
        should be updated to be simpler
        """
135
        if cache.get("hashids_counter") is None:
136
137
            cache.set("hashids_counter", URL.objects.count())
        cache.incr("hashids_counter")
138
        short = HASHIDS.encrypt(cache.get("hashids_counter"))
139
140
141
        tries = 1
        while tries < 100:
            try:
142
                URL.objects.get(short__iexact=short)
143
144
                tries += 1
                cache.incr("hashids_counter")
145
            except URL.DoesNotExist as ex:
146
                print(ex)
147
148
                return short
        return None