Merge lp:~widelands-dev/widelands-website/auto_one_to_one_ractivating into lp:widelands-website

Proposed by kaputtnik
Status: Merged
Merged at revision: 432
Proposed branch: lp:~widelands-dev/widelands-website/auto_one_to_one_ractivating
Merge into: lp:widelands-website
Diff against target: 295 lines (+64/-102)
10 files modified
mainpage/views.py (+0/-26)
settings.py (+3/-2)
urls.py (+2/-2)
wl_utils.py (+51/-0)
wlggz/fields.py (+0/-33)
wlggz/migrations/0001_initial.py (+2/-3)
wlggz/models.py (+1/-1)
wlprofile/fields.py (+1/-32)
wlprofile/migrations/0001_initial.py (+2/-2)
wlprofile/models.py (+2/-1)
To merge this branch: bzr merge lp:~widelands-dev/widelands-website/auto_one_to_one_ractivating
Reviewer Review Type Date Requested Status
SirVer Approve
Review via email: mp+310813@code.launchpad.net

Description of the change

Another issue from the update to django 1.8:

Formerly to django 1.8 entrys to the database of wlprofile and wlggz has been created on demand.

For some reason i didn't checked this when working on the django 1.8 branch and thought the database entries got created during registering.

The last django errors from today told me that there is something wrong: A user who registered in year 2010 tried to access his profile the first time, and django through the error. For this user i created the wlprofile and wlggz database entries by hand over the admin site. Comparing the amount of users and wlprofiles i found that we have over 4000 users while there are only a bit more than 2000 wlprofiles :-S

This branch brings back the old behavior. I didn't know much about the code change, just get it from here:

https://github.com/skorokithakis/django-annoying/issues/36

So the code may need a review from a more experienced user.

This branch is tested here at home including normal registration over the registration app. I decided to move the relevant code to wl_utils because this code was used two times (wlprofile and wlggz). Additionally removed the code introduced by my misunderstanding.

We should get this in as soon as possible.

To post a comment you must log in.
431. By kaputtnik

resolved merge conflict because of settings.py

Revision history for this message
GunChleoc (gunchleoc) wrote :

django-annoying released that fix over a year ago, so it should be quite safe.

We should compare with their current code though:

https://github.com/skorokithakis/django-annoying/blob/master/annoying/fields.py#L37

I noticed that this has an extra @atomic in it.

Revision history for this message
kaputtnik (franku) wrote :

The @atomic decorator is only used with transactions, which depends on

- the version of database
- the capability of the Database
- table engine of the Database
- the settings of a database.

As far as i know we doesn't use transactions in our code and trust to the django default Autocommit mode (which is also default in MySql)

Nevertheless by reading through https://docs.djangoproject.com/en/1.8/topics/db/transactions/ i guess it is not bad to set this decorator. But i am no database specialist and my guess is maybe wrong.

I think we will never use transactions, so why should we (i) add this decorator if the consequences are unknown...

This Database stuff is really complicated... lets keep it as simple as it could be, imho.

432. By kaputtnik

merged with trunk

Revision history for this message
SirVer (sirver) wrote :

I cannot really comment on the AutoSingleRelatedObjectDescriptor - it seems to work around various non-backwards compatible changes in django overtime. For example this comment about caching and not returning the created objects sounds frightening....

Let's get it in and hope for the best. Sometimes hope is a strategy :)

review: Approve
433. By kaputtnik

make it responsible with future Django versions

Revision history for this message
kaputtnik (franku) wrote :

Related to your code comment: Yes it was a failure during the conflict resolving.

Merged and deployed. Hopefully all is working now...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'mainpage/views.py'
2--- mainpage/views.py 2016-10-20 20:30:14 +0000
3+++ mainpage/views.py 2016-11-15 22:47:42 +0000
4@@ -55,32 +55,6 @@
5 def legal_notice_thanks(request):
6 return render(request, 'mainpage/legal_notice_thanks.html')
7
8-from wlprofile.models import Profile
9-from registration.backends.hmac.views import RegistrationView
10-from django.contrib.auth.models import User
11-from wlggz.models import GGZAuth
12-
13-class OwnRegistrationView(RegistrationView):
14- """Overwriting the default function to save also the extended User model
15- (wlprofile)"""
16-
17- def create_inactive_user(self, form):
18- """Additionally save the custom enxtended user data."""
19- new_user = form.save(commit=False)
20- new_user.is_active = False
21- new_user.save()
22- reg_user = User.objects.get(username=new_user)
23- # Creating a wlprofile
24- ext_profile = Profile(user=reg_user)
25- ext_profile.save()
26- # Creating a ggzprofile
27- ggz_profile = GGZAuth(user=reg_user)
28- ggz_profile.save()
29-
30- self.send_activation_email(new_user)
31-
32- return new_user
33-
34
35 def developers(request):
36 """This reads out some json files in the SVN directory, and returns it as a
37
38=== modified file 'settings.py'
39--- settings.py 2016-10-29 07:00:53 +0000
40+++ settings.py 2016-11-15 22:47:42 +0000
41@@ -3,8 +3,9 @@
42 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
43 import os
44
45-BASE_DIR = os.path.dirname(os.path.abspath(__file__))#+ '/widelands'
46+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
47 DEBUG = True
48+
49 ADMINS = (
50 # ('Your Name', 'your_email@domain.com'),
51 )
52@@ -75,7 +76,7 @@
53 'django.contrib.staticfiles',
54 'django.contrib.sites',
55 'django.contrib.humanize',
56- #'django_comments',
57+ 'django_comments',
58 'nocaptcha_recaptcha',
59 # Thirdparty apps, but need preload
60 'tracking', # included as wlapp
61
62=== modified file 'urls.py'
63--- urls.py 2016-08-02 19:22:42 +0000
64+++ urls.py 2016-11-15 22:47:42 +0000
65@@ -9,7 +9,7 @@
66 from news.feeds import NewsPostsFeed
67 from django.views.generic.base import RedirectView
68 from django.contrib.syndication.views import Feed
69-from mainpage.views import OwnRegistrationView
70+from registration.backends.hmac.views import RegistrationView
71 from mainpage.forms import RegistrationWithCaptchaForm
72
73 urlpatterns = [
74@@ -18,7 +18,7 @@
75
76 # Django builtin / Registration
77 # overwrite registration with own implementation
78- url (r'^accounts/register/$', OwnRegistrationView.as_view(form_class=RegistrationWithCaptchaForm), name='registration_register'),
79+ url (r'^accounts/register/$', RegistrationView.as_view(form_class=RegistrationWithCaptchaForm), name='registration_register'),
80 url(r'^accounts/', include('registration.backends.hmac.urls')),
81 url('^', include('django.contrib.auth.urls')),
82
83
84=== modified file 'wl_utils.py'
85--- wl_utils.py 2016-10-17 20:24:04 +0000
86+++ wl_utils.py 2016-11-15 22:47:42 +0000
87@@ -6,3 +6,54 @@
88 return request.META[key]
89 # No match -> Return a fictional IP to have the model fields not empty
90 return '192.168.255.255'
91+
92+
93+# AutoOneToOneField
94+# =================
95+# Initial implemenation details about AutoOneToOneField:
96+# http://softwaremaniacs.org/blog/2007/03/07/auto-one-to-one-field/
97+#
98+# This doesn't worked anymore with django 1.8
99+# changed according to:
100+# https://github.com/skorokithakis/django-annoying/issues/36
101+
102+
103+# SingleRelatedObjectDescriptor gets renamed with Django 1.9
104+try:
105+ from django.db.models.fields.related import SingleRelatedObjectDescriptor
106+except ImportError:
107+ from django.db.models.fields.related_descriptors import ReverseOneToOneDescriptor as SingleRelatedObjectDescriptor
108+
109+from django.db.models import OneToOneField
110+from django.db.models.fields.related import SingleRelatedObjectDescriptor
111+from django.db import models
112+
113+class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
114+ """
115+ The descriptor that handles the object creation for an AutoOneToOneField.
116+ """
117+ def __get__(self, instance, instance_type=None):
118+ model = getattr(self.related, 'related_model', self.related.model)
119+
120+ try:
121+ return (super(AutoSingleRelatedObjectDescriptor, self)
122+ .__get__(instance, instance_type))
123+ except model.DoesNotExist:
124+ obj = model(**{self.related.field.name: instance})
125+
126+ obj.save()
127+
128+ # Don't return obj directly, otherwise it won't be added
129+ # to Django's cache, and the first 2 calls to obj.relobj
130+ # will return 2 different in-memory objects
131+ return (super(AutoSingleRelatedObjectDescriptor, self)
132+ .__get__(instance, instance_type))
133+
134+class AutoOneToOneField(OneToOneField):
135+ """
136+ OneToOneField creates dependent object on first request from parent object
137+ if dependent oject has not created yet.
138+ """
139+
140+ def contribute_to_related_class(self, cls, related):
141+ setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))
142
143=== removed file 'wlggz/fields.py'
144--- wlggz/fields.py 2016-08-08 18:18:04 +0000
145+++ wlggz/fields.py 1970-01-01 00:00:00 +0000
146@@ -1,33 +0,0 @@
147-"""
148-Details about AutoOneToOneField:
149- http://softwaremaniacs.org/blog/2007/03/07/auto-one-to-one-field/
150-"""
151-
152-from StringIO import StringIO
153-import logging
154-
155-from django.db.models import OneToOneField
156-from django.db.models.fields.related import SingleRelatedObjectDescriptor
157-from django.db import models
158-
159-
160-class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
161- def __get__(self, instance, instance_type=None):
162- try:
163- return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
164- except self.related.model.DoesNotExist:
165- obj = self.related.model(**{self.related.field.name: instance})
166- obj.save()
167- return obj
168-
169-
170-class AutoOneToOneField(OneToOneField):
171- """
172- OneToOneField creates dependent object on first request from parent object
173- if dependent oject has not created yet.
174- """
175-
176- def contribute_to_related_class(self, cls, related):
177- setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))
178- #if not cls._meta.one_to_one_field:
179- #cls._meta.one_to_one_field = self
180
181=== modified file 'wlggz/migrations/0001_initial.py'
182--- wlggz/migrations/0001_initial.py 2016-04-18 13:29:23 +0000
183+++ wlggz/migrations/0001_initial.py 2016-11-15 22:47:42 +0000
184@@ -3,8 +3,7 @@
185
186 from django.db import models, migrations
187 from django.conf import settings
188-import wlggz.fields
189-
190+import wl_utils
191
192 class Migration(migrations.Migration):
193
194@@ -21,7 +20,7 @@
195 ('lastlogin', models.DateTimeField(null=True, verbose_name='ggz lastlogin')),
196 ('permissions', models.IntegerField(default=7, verbose_name='ggz permissions')),
197 ('confirmed', models.IntegerField(default=1, verbose_name='confirmed', editable=False)),
198- ('user', wlggz.fields.AutoOneToOneField(related_name='wlggz', verbose_name='User', to=settings.AUTH_USER_MODEL)),
199+ ('user', wl_utils.AutoOneToOneField(related_name='wlggz', verbose_name='User', to=settings.AUTH_USER_MODEL)),
200 ],
201 options={
202 'verbose_name': 'ggz',
203
204=== modified file 'wlggz/models.py'
205--- wlggz/models.py 2016-08-05 18:20:29 +0000
206+++ wlggz/models.py 2016-11-15 22:47:42 +0000
207@@ -9,7 +9,7 @@
208
209 from django.db import models
210 from django.contrib.auth.models import User
211-from fields import AutoOneToOneField
212+from wl_utils import AutoOneToOneField
213 from django.utils.translation import ugettext_lazy as _
214 from pybb.models import Post
215
216
217=== modified file 'wlprofile/fields.py'
218--- wlprofile/fields.py 2016-06-05 11:00:17 +0000
219+++ wlprofile/fields.py 2016-11-15 22:47:42 +0000
220@@ -1,38 +1,7 @@
221-"""
222-Details about AutoOneToOneField:
223- http://softwaremaniacs.org/blog/2007/03/07/auto-one-to-one-field/
224-"""
225-
226 from StringIO import StringIO
227+from django.db import models
228 import logging
229
230-from django.db.models import OneToOneField
231-from django.db.models.fields.related import SingleRelatedObjectDescriptor
232-from django.db import models
233-from django.core.files.uploadedfile import SimpleUploadedFile
234-
235-
236-class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
237- def __get__(self, instance, instance_type=None):
238- try:
239- return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
240- except self.related.model.DoesNotExist:
241- obj = self.related.model(**{self.related.field.name: instance})
242- obj.save()
243- return obj
244-
245-
246-class AutoOneToOneField(OneToOneField):
247- """
248- OneToOneField creates dependent object on first request from parent object
249- if dependent oject has not created yet.
250- """
251-
252- def contribute_to_related_class(self, cls, related):
253- setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))
254- #if not cls._meta.one_to_one_field:
255- #cls._meta.one_to_one_field = self
256-
257
258 class ExtendedImageField(models.ImageField):
259 """
260
261=== modified file 'wlprofile/migrations/0001_initial.py'
262--- wlprofile/migrations/0001_initial.py 2016-04-18 13:29:23 +0000
263+++ wlprofile/migrations/0001_initial.py 2016-11-15 22:47:42 +0000
264@@ -3,9 +3,9 @@
265
266 from django.db import models, migrations
267 from django.conf import settings
268+import wl_utils
269 import wlprofile.fields
270
271-
272 class Migration(migrations.Migration):
273
274 dependencies = [
275@@ -29,7 +29,7 @@
276 ('signature', models.TextField(default=b'', max_length=255, verbose_name='Signature', blank=True)),
277 ('avatar', wlprofile.fields.ExtendedImageField(default=b'wlprofile/anonymous.png', upload_to=b'wlprofile/avatars/', verbose_name='Avatar', blank=True)),
278 ('show_signatures', models.BooleanField(default=True, verbose_name='Show signatures')),
279- ('user', wlprofile.fields.AutoOneToOneField(related_name='wlprofile', verbose_name='User', to=settings.AUTH_USER_MODEL)),
280+ ('user', wl_utils.AutoOneToOneField(related_name='wlprofile', verbose_name='User', to=settings.AUTH_USER_MODEL)),
281 ],
282 options={
283 'verbose_name': 'Profile',
284
285=== modified file 'wlprofile/models.py'
286--- wlprofile/models.py 2016-07-31 08:44:48 +0000
287+++ wlprofile/models.py 2016-11-15 22:47:42 +0000
288@@ -1,6 +1,7 @@
289 from django.db import models
290 from django.contrib.auth.models import User
291-from fields import AutoOneToOneField, ExtendedImageField
292+from fields import ExtendedImageField
293+from wl_utils import AutoOneToOneField
294 from django.utils.translation import ugettext_lazy as _
295 from pybb.models import Post
296

Subscribers

People subscribed via source and target branches