forms.py 7.35 KB
Newer Older
1
# Django Imports
2
from django import forms
3
from django.core.exceptions import ValidationError
4
from django.utils.safestring import mark_safe
5
6
7
8
9

# App Imports
from go.models import URL, RegisteredUser

# Other Imports
David Haynes's avatar
David Haynes committed
10
from crispy_forms.helper import FormHelper
11
12
from crispy_forms.layout import Layout, Fieldset, Submit, HTML, Div, Field
from crispy_forms.bootstrap import StrictButton, PrependedText, Accordion, AccordionGroup
13
from bootstrap3_datetime.widgets import DateTimePicker
14
15

class URLForm(forms.ModelForm):
16

17
18
19
20
21
22
23
24
    # Prevent redirect loop links
    def clean_target(self):
        target = self.cleaned_data.get('target')
        if self.host in target:
            raise ValidationError("You can't make a Go link to Go silly!")
        else:
            return target

25
26
27
    # Custom target URL field
    target = forms.URLField(
        required=True,
28
        label='Long URL (Required)',
29
30
        max_length=1000,
        widget=forms.URLInput(attrs={
31
            'placeholder': 'https://yoursite.com/'
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
        })
    )

    # Check to make sure the short url has not been used
    def unique_short(value):
        try:
            URL.objects.get(short__iexact=value)
        except URL.DoesNotExist:
            return
        raise ValidationError('Short url already exists.')

    # Custom short-url field with validators.
    short = forms.SlugField(
        required=False,
        label='Short URL (Optional)',
        widget=forms.TextInput(),
        validators=[unique_short],
        max_length=20,
        min_length=3,
    )

    DAY = '1 Day'
    WEEK = '1 Week'
    MONTH = '1 Month'
56
    CUSTOM = 'Custom Date'
57
58
59
60
61
62
63
    NEVER = 'Never'

    EXPIRATION_CHOICES = (
        (DAY, DAY),
        (WEEK, WEEK),
        (MONTH, MONTH),
        (NEVER, NEVER),
64
        (CUSTOM, CUSTOM),
65
66
67
68
69
    )

    # Add a custom expiration choice field.
    expires = forms.ChoiceField(
        required=True,
70
        label='Expiration (Required)',
71
72
73
74
75
        choices=EXPIRATION_CHOICES,
        initial=NEVER,
        widget=forms.RadioSelect(),
    )

76
77
78
79
    expires_custom = forms.DateTimeField(
        widget=DateTimePicker(options={"format": "YYYY-MM-DD", "pickTime": False})
    )

80

81
    def __init__(self, *args, **kwargs):
82
83
        # Grab that host info
        self.host = kwargs.pop('host', None)
84
        super(URLForm, self).__init__(*args, **kwargs)
85
        # Define the basics for crispy-forms
86
        self.helper = FormHelper()
87
        self.helper.form_method = 'POST'
88

89
        # Some xtra vars for form css purposes
90
91
92
93
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-md-1'
        self.helper.field_class = 'col-md-6'

94
        # The main "layout" defined
95
        self.helper.layout = Layout(
96
97
            Fieldset('',
            #######################
98
                Accordion(
99
                    # Step 1: Long URL
100
101
102
103
                    AccordionGroup('Step 1: Long URL',
                        Div(
                            HTML("""
                                <h4>Paste the URL you would like to shorten:</h4>
104
                                <br />"""),
105
                            'target',
106
                            style="background: rgb(#F6F6F6);"),
107
                        active=True,
108
109
110
                        template='crispy/accordian-group.html'),

                    # Step 2: Short URL
111
112
113
114
                    AccordionGroup('Step 2: Short URL',
                        Div(
                            HTML("""
                                <h4>Create a custom Go address:</h4>
115
116
117
118
                                <br />"""),
                            PrependedText(
                            'short', 'https://go.gmu.edu/'),
                            style="background: rgb(#F6F6F6);"),
119
                        active=True,
120
121
122
                        template='crispy/accordian-group.html',),

                    # Step 3: Expiration
123
124
125
126
                    AccordionGroup('Step 3: URL Expiration',
                        Div(
                            HTML("""
                                <h4>Set when you would like your Go address to expire:</h4>
127
                                <br />"""),
128
                            'expires',
129
                            'expires_custom',
130
                            style="background: rgb(#F6F6F6);"),
131
                        active=True,
132
                        template='crispy/accordian-group.html'),
133

134
135
136
137
138
139
                    # FIN
                    template='crispy/accordian.html'),
            #######################
            HTML("""
                <br />"""),
            StrictButton('Shorten', css_class="btn btn-primary btn-md col-md-4", type='submit')))
140

141
142
143
144
145
146
    class Meta:
        model = URL
        fields = ('target',)
        exclude = ('owner', 'short', 'date_created', 'clicks', 'expires')


147
class SignupForm(forms.ModelForm):
148
149
150
151
152
153
154
155

    def validate_username(username):
        try:
            registered = RegisteredUser.objects.get(username=username)
            raise ValidationError('Username "%s" is already in use.' % username)
        except RegisteredUser.DoesNotExist:
            return

156
157
158
159
160
161
162
    def clean_username(self):
        # Prevent hax: (non-staff) Users cannot signup for other users
        data_username = self.cleaned_data.get("username")

        if not self.request.user.is_staff:
            if self.request.user.username not in data_username:
                raise ValidationError('username', "This is not your NetID!")
163
        return data_username
164

165
    username = forms.CharField(
166
        required=True,
167
        label='Mason NetID (Required)',
168
        max_length=30,
169
        validators=[validate_username],
170
        widget=forms.TextInput(attrs={
171
172
173
        }),
    )
    full_name = forms.CharField(
174
        required=True,
175
        label='Full Name (Required)',
176
177
        max_length=100,
        widget=forms.TextInput(attrs={
178
179
        }),
    )
180
181
182
183
184
185
186
    organization = forms.CharField(
        required=True,
        label='Organization (Required)',
        max_length=100,
        widget=forms.TextInput(attrs={
        })
    )
187
    description = forms.CharField(
188
189
190
191
        required=False,
        label='Description (Optional)',
        max_length=200,
        widget=forms.Textarea(attrs={
192
193
        }),
    )
194
195
    tos_box = forms.BooleanField(
        required=True,
196
        # Need to add a Terms of Service Page and replace the href below
197
198
199
        label = mark_safe('Do you accept the <a href="#" target="_blank">Terms of Service</a>?'),
    )

200
201
202
203
    def __init__(self, request, *args, **kwargs):
        # Necessary to call request in forms.py, is otherwise restricted to views.py and models.py
        self.request = request
        super(SignupForm, self).__init__(*args, **kwargs)
David Haynes's avatar
David Haynes committed
204
        self.helper = FormHelper()
205
206
207
208
209
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-md-4'
        self.helper.field_class = 'col-md-6'

        self.helper.layout = Layout(
210
            Fieldset('',
211
                Div(
212
                    # Place in form fields
213
214
215
216
217
218
                    Div(
                        'username',
                        'full_name',
                        'organization',
                        'description',
                        'tos_box',
219
220
221
                        css_class='well'),

                    # Extras at bottom
222
                    StrictButton('Submit',css_class='btn btn-primary btn-md col-md-4', type='submit'),
223
                    css_class='col-md-6')))
224
225
    class Meta:
        model = RegisteredUser
226
        fields = '__all__'