1
1
"""Views for creating, editing and viewing site-specific user profiles."""
2
2
3
- from django .contrib import messages
4
3
from django .contrib .auth import logout
5
- from django .contrib .auth .decorators import login_required
6
4
from django .contrib .auth .models import User
7
- from django .http import HttpResponseRedirect
8
- from django .shortcuts import get_object_or_404 , redirect , render
5
+ from django .contrib .messages .views import SuccessMessageMixin
9
6
from django .urls import reverse
10
7
from django .utils .translation import ugettext_lazy as _
11
- from django .views .generic import ListView
12
8
from rest_framework .authtoken .models import Token
9
+ from vanilla import DetailView , FormView , ListView , UpdateView
13
10
14
- from readthedocs .core .forms import UserAdvertisingForm , UserDeleteForm
11
+ from readthedocs .core .forms import (
12
+ UserAdvertisingForm ,
13
+ UserDeleteForm ,
14
+ UserProfileForm ,
15
+ )
15
16
from readthedocs .core .mixins import PrivateViewMixin
17
+ from readthedocs .core .models import UserProfile
16
18
17
19
18
- @login_required
19
- def edit_profile (
20
- request ,
21
- form_class ,
22
- success_url = None ,
23
- template_name = 'profiles/private/edit_profile.html' ,
24
- extra_context = None ,
25
- ):
26
- """
27
- Edit the current user's profile.
28
-
29
- **Optional arguments:**
30
-
31
- ``extra_context``
32
- A dictionary of variables to add to the template context. Any
33
- callable object in this dictionary will be called to produce
34
- the end result which appears in the context.
35
-
36
- ``form_class``
37
- The form class to use for validating and editing the user
38
- profile. This form class must operate similarly to a standard
39
- Django ``ModelForm`` in that it must accept an instance of the
40
- object to be edited as the keyword argument ``instance`` to
41
- its constructor, and it must implement a method named
42
- ``save()`` which will save the updates to the object.
43
-
44
- ``success_url``
45
- The URL to redirect to following a successful edit. If not
46
- specified, this will default to the URL of
47
- :view:`profiles.views.profile_detail` for the profile object
48
- being edited.
49
-
50
- ``template_name``
51
- The template to use when displaying the profile-editing
52
- form. If not specified, this will default to
53
- :template:`profiles/edit_profile.html`.
54
-
55
- **Context:**
56
-
57
- ``form``
58
- The form for editing the profile.
59
-
60
- ``profile``
61
- The user's current profile.
62
-
63
- **Template:**
64
-
65
- ``template_name`` keyword argument or
66
- :template:`profiles/edit_profile.html`.
67
- """
68
- profile_obj = request .user .profile
69
- if success_url is None :
70
- success_url = reverse (
20
+ class ProfileEdit (PrivateViewMixin , UpdateView ):
21
+
22
+ """Edit the current user's profile."""
23
+
24
+ model = UserProfile
25
+ form_class = UserProfileForm
26
+ template_name = 'profiles/private/edit_profile.html'
27
+ context_object_name = 'profile'
28
+
29
+ def get_object (self ):
30
+ return self .request .user .profile
31
+
32
+ def get_success_url (self ):
33
+ return reverse (
71
34
'profiles_profile_detail' ,
72
- kwargs = {'username' : request .user .username },
73
- )
74
- if request .method == 'POST' :
75
- form = form_class (
76
- data = request .POST ,
77
- files = request .FILES ,
78
- instance = profile_obj ,
35
+ kwargs = {'username' : self .request .user .username },
79
36
)
80
- if form .is_valid ():
81
- form .save ()
82
- return HttpResponseRedirect (success_url )
83
- else :
84
- form = form_class (instance = profile_obj )
85
-
86
- if extra_context is None :
87
- extra_context = {}
88
- context = {
89
- key : value () if callable (value ) else value
90
- for key , value in extra_context .items ()
91
- }
92
- context .update ({
93
- 'form' : form ,
94
- 'profile' : profile_obj ,
95
- 'user' : profile_obj .user ,
96
- })
97
- return render (request , template_name , context = context )
98
-
99
-
100
- @login_required ()
101
- def delete_account (request ):
102
- form = UserDeleteForm ()
37
+
38
+
39
+ class AccountDelete (PrivateViewMixin , SuccessMessageMixin , FormView ):
40
+
41
+ form_class = UserDeleteForm
103
42
template_name = 'profiles/private/delete_account.html'
43
+ success_message = _ ('You have successfully deleted your account' )
104
44
105
- if request .method == 'POST' :
106
- form = UserDeleteForm (instance = request .user , data = request .POST )
107
- if form .is_valid ():
108
- # Delete the user permanently
109
- # It will also delete some projects where the user is the only owner
110
- request .user .delete ()
111
- logout (request )
112
- messages .info (request , 'You have successfully deleted your account' )
113
-
114
- return redirect ('homepage' )
115
-
116
- return render (request , template_name , {'form' : form })
117
-
118
-
119
- def profile_detail (
120
- request ,
121
- username ,
122
- public_profile_field = None ,
123
- template_name = 'profiles/public/profile_detail.html' ,
124
- extra_context = None ,
125
- ):
126
- """
127
- Detail view of a user's profile.
128
-
129
- If the user does not exists, ``Http404`` will be raised.
130
-
131
- **Required arguments:**
132
-
133
- ``username``
134
- The username of the user whose profile is being displayed.
135
-
136
- **Optional arguments:**
137
-
138
- ``extra_context``
139
- A dictionary of variables to add to the template context. Any
140
- callable object in this dictionary will be called to produce
141
- the end result which appears in the context.
142
-
143
- ``public_profile_field``
144
- The name of a ``BooleanField`` on the profile model; if the
145
- value of that field on the user's profile is ``False``, the
146
- ``profile`` variable in the template will be ``None``. Use
147
- this feature to allow users to mark their profiles as not
148
- being publicly viewable.
149
-
150
- If this argument is not specified, it will be assumed that all
151
- users' profiles are publicly viewable.
152
-
153
- ``template_name``
154
- The name of the template to use for displaying the profile. If
155
- not specified, this will default to
156
- :template:`profiles/profile_detail.html`.
157
-
158
- **Context:**
159
-
160
- ``profile``
161
- The user's profile, or ``None`` if the user's profile is not
162
- publicly viewable (see the description of
163
- ``public_profile_field`` above).
164
-
165
- **Template:**
166
-
167
- ``template_name`` keyword argument or
168
- :template:`profiles/profile_detail.html`.
169
- """
170
- user = get_object_or_404 (User , username = username )
171
- profile_obj = user .profile
172
- if (public_profile_field is not None and
173
- not getattr (profile_obj , public_profile_field )):
174
- profile_obj = None
175
-
176
- if extra_context is None :
177
- extra_context = {}
178
- context = {
179
- key : value () if callable (value ) else value
180
- for key , value in extra_context .items ()
181
- }
182
- context .update ({'profile' : profile_obj })
183
- return render (request , template_name , context = context )
184
-
185
-
186
- @login_required
187
- def account_advertising (request ):
188
- success_url = reverse (account_advertising )
189
- profile_obj = request .user .profile
190
- if request .method == 'POST' :
191
- form = UserAdvertisingForm (
192
- data = request .POST ,
193
- instance = profile_obj ,
194
- )
195
- if form .is_valid ():
196
- form .save ()
197
- messages .info (request , _ ('Updated your advertising preferences' ))
198
- return HttpResponseRedirect (success_url )
199
- else :
200
- form = UserAdvertisingForm (instance = profile_obj )
201
-
202
- return render (
203
- request ,
204
- 'profiles/private/advertising_profile.html' ,
205
- context = {
206
- 'form' : form ,
207
- 'profile' : profile_obj ,
208
- 'user' : profile_obj .user ,
209
- },
210
- )
45
+ def get_object (self ):
46
+ return self .request .user
47
+
48
+ def form_valid (self , form ):
49
+ self .request .user .delete ()
50
+ logout (self .request )
51
+ return super ().form_valid (form )
52
+
53
+ def get_form (self , data = None , files = None , ** kwargs ):
54
+ kwargs ['instance' ] = self .get_object ()
55
+ return super ().get_form (data , files , ** kwargs )
56
+
57
+ def get_success_url (self ):
58
+ return reverse ('homepage' )
59
+
60
+
61
+ class ProfileDetail (DetailView ):
62
+
63
+ model = User
64
+ template_name = 'profiles/public/profile_detail.html'
65
+ lookup_field = 'username'
66
+
67
+ def get_context_data (self , ** kwargs ):
68
+ context = super ().get_context_data (** kwargs )
69
+ context ['profile' ] = self .get_object ().profile
70
+ return context
71
+
72
+
73
+ class AccountAdvertisingEdit (PrivateViewMixin , SuccessMessageMixin , UpdateView ):
74
+
75
+ model = UserProfile
76
+ form_class = UserAdvertisingForm
77
+ context_object_name = 'profile'
78
+ template_name = 'profiles/private/advertising_profile.html'
79
+ success_message = _ ('Updated your advertising preferences' )
80
+
81
+ def get_object (self ):
82
+ return self .request .user .profile
83
+
84
+ def get_success_url (self ):
85
+ return reverse ('account_advertising' )
211
86
212
87
213
88
class TokenMixin (PrivateViewMixin ):
@@ -230,4 +105,5 @@ def get_success_url(self):
230
105
231
106
232
107
class TokenList (TokenMixin , ListView ):
108
+
233
109
pass
0 commit comments