diff --git a/.style.yapf b/.style.yapf new file mode 100644 index 0000000..5dad752 --- /dev/null +++ b/.style.yapf @@ -0,0 +1,3 @@ +[style] +based_on_style = pep8 +column_limit=100 \ No newline at end of file diff --git a/past3d/settings.py b/past3d/settings.py index 7308881..5bdddee 100644 --- a/past3d/settings.py +++ b/past3d/settings.py @@ -1,7 +1,8 @@ # Django settings for past3d project. -from django.core.urlresolvers import reverse_lazy +from django.urls import reverse_lazy import os + BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../') DEBUG = True @@ -15,13 +16,15 @@ MANAGERS = ADMINS DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. + 'ENGINE': + 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 'NAME': os.path.join(BASE_DIR, "data.sqlite"), # Or path to database file if using sqlite3. # The following settings are not used with sqlite3: 'USER': '', 'PASSWORD': '', - 'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. - 'PORT': '', # Set to empty string for default. + 'HOST': + '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. + 'PORT': '', # Set to empty string for default. } } @@ -54,7 +57,7 @@ USE_TZ = True # Absolute filesystem path to the directory that will hold user-uploaded files. # Example: "/var/www/example.com/media/" -MEDIA_ROOT = os.path.join(BASE_DIR,"media") +MEDIA_ROOT = os.path.join(BASE_DIR, "media") # URL that handles the media served from MEDIA_ROOT. Make sure to use a # trailing slash. @@ -65,7 +68,7 @@ MEDIA_URL = '/media/' # Don't put anything in this directory yourself; store your static files # in apps' "static/" subdirectories and in STATICFILES_DIRS. # Example: "/var/www/example.com/static/" -STATIC_ROOT = os.path.join(BASE_DIR,"static") +STATIC_ROOT = os.path.join(BASE_DIR, "static") # URL prefix for static files. # Example: "http://example.com/static/", "http://static.example.com/" @@ -73,7 +76,7 @@ STATIC_URL = '/static/' # Additional locations of static files STATICFILES_DIRS = ( - os.path.join(BASE_DIR,"static_common"), + os.path.join(BASE_DIR, "static_common"), # Put strings here, like "/home/html/static" or "C:/www/django/static". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. @@ -84,7 +87,7 @@ STATICFILES_DIRS = ( STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', -# 'django.contrib.staticfiles.finders.DefaultStorageFinder', + # 'django.contrib.staticfiles.finders.DefaultStorageFinder', ) # Make this unique, and don't share it with anybody. @@ -94,7 +97,7 @@ SECRET_KEY = 'InsertSomethingSecretHereBeforeDoingProduktion' TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', -# 'django.template.loaders.eggs.Loader', + # 'django.template.loaders.eggs.Loader', ) MIDDLEWARE_CLASSES = ( @@ -113,7 +116,7 @@ ROOT_URLCONF = 'past3d.urls' WSGI_APPLICATION = 'past3d.wsgi.application' TEMPLATE_DIRS = ( - os.path.join(BASE_DIR,'templates'), + os.path.join(BASE_DIR, 'templates'), # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. @@ -140,7 +143,7 @@ SESSION_SERIALIZER = 'django.contrib.sessions.serializers.JSONSerializer' LOGIN_REDIRECT_URL = reverse_lazy('geometry_create') EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' -EMAIL_FILE_PATH = '/tmp/django' +EMAIL_FILE_PATH = '/tmp/django' # A sample logging configuration. The only tangible logging # performed by this configuration is to send an email to diff --git a/past3d/urls.py b/past3d/urls.py index cbf650f..b57a8b9 100644 --- a/past3d/urls.py +++ b/past3d/urls.py @@ -1,31 +1,19 @@ -from django.conf.urls import patterns, include, url - +from django.urls import include, re_path, path from django.conf import settings from django.conf.urls.static import static # Uncomment the next two lines to enable the admin: from django.contrib import admin + admin.autodiscover() -from views import HomeView +from past3d.views import HomeView -urlpatterns = patterns('', - # Examples: - # url(r'^$', 'past3d.views.home', name='home'), - # url(r'^past3d/', include('past3d.foo.urls')), - - url(r'^$', HomeView.as_view(), name='home'), - - url(r'^users/', include('users.urls')), - url(r'^3d/', include('pastebin.urls')), - - # Uncomment the admin/doc line below to enable admin documentation: - # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), - - # Uncomment the next line to enable the admin: - url(r'^admin/', include(admin.site.urls)), - - -) +urlpatterns = [ + re_path(r'^$', HomeView.as_view(), name='home'), + path('users/', include('users.urls')), + path('3d/', include('pastebin.urls')), + path('admin/', admin.site.urls), +] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/pastebin/admin.py b/pastebin/admin.py index 5bf2abd..1bfa04a 100644 --- a/pastebin/admin.py +++ b/pastebin/admin.py @@ -2,9 +2,11 @@ # -*- coding: utf-8 -*- from django.contrib import admin -from models import Geometry +from pastebin.models import Geometry + class GeometryAdmin(admin.ModelAdmin): list_display = ['name', 'description', 'date', 'file', 'sourcefile'] + admin.site.register(Geometry, GeometryAdmin) diff --git a/pastebin/forms.py b/pastebin/forms.py index 338a633..9049a8d 100644 --- a/pastebin/forms.py +++ b/pastebin/forms.py @@ -5,7 +5,7 @@ import struct from django.forms import ModelForm from django import forms -from models import Geometry +from pastebin.models import Geometry facet_pattern = re.compile(r'facet normal\s+[0-9.e+-]+\s+[0-9.e+-]+\s+[0-9.e+-]+') loop_pattern = re.compile(r'outer\s+loop') @@ -14,74 +14,77 @@ endloop_pattern = re.compile(r'endloop') endfacet_pattern = re.compile(r'endfacet') endsolid_pattern = re.compile(r'endsolid .*') + class STLUploadForm(ModelForm): - def clean_file(self): - stlfile = self.cleaned_data.get("file") - stlfile.open() + def clean_file(self): - if stlfile.read(5) != "solid": - #print "binary" - #Skip header - stlfile.seek(80) - count = struct.unpack("i",stlfile.read(4))[0] - if stlfile.size - 84 != count * 50: - raise forms.ValidationError("Not a valid binary STL file.") + stlfile = self.cleaned_data.get("file") + stlfile.open() - else: - #print "ascii" - next_patterns = [facet_pattern] - stlfile.readline() - line = stlfile.readline().strip() - - matched_pattern = None - vertex_count = 0 + if stlfile.read(5) != "solid": + #print "binary" + #Skip header + stlfile.seek(80) + count = struct.unpack("i", stlfile.read(4))[0] + if stlfile.size - 84 != count * 50: + raise forms.ValidationError("Not a valid binary STL file.") - while line != "": + else: + #print "ascii" + next_patterns = [facet_pattern] + stlfile.readline() + line = stlfile.readline().strip() - corret = False - for pattern in next_patterns: - if pattern.match(line) != None: - corret = True - matched_pattern = pattern - if not corret: - raise forms.ValidationError("Not a valid ascii STL file.") + matched_pattern = None + vertex_count = 0 - if matched_pattern == facet_pattern: - next_patterns = [loop_pattern] - if matched_pattern == loop_pattern: - vertex_count = 0 - next_patterns = [vertex_pattern] - if matched_pattern == vertex_pattern: - vertex_count += 1 - if vertex_count < 3: - next_patterns = [vertex_pattern, endloop_pattern] - else : - next_patterns = [endloop_pattern] - if matched_pattern == endloop_pattern: - next_patterns = [endfacet_pattern] - if matched_pattern == endfacet_pattern: - next_patterns = [facet_pattern, endsolid_pattern] + while line != "": - line = stlfile.readline().strip() + corret = False + for pattern in next_patterns: + if pattern.match(line) != None: + corret = True + matched_pattern = pattern + if not corret: + raise forms.ValidationError("Not a valid ascii STL file.") - if matched_pattern != endsolid_pattern: - raise forms.ValidationError("Not a valid ascii STL file.") + if matched_pattern == facet_pattern: + next_patterns = [loop_pattern] + if matched_pattern == loop_pattern: + vertex_count = 0 + next_patterns = [vertex_pattern] + if matched_pattern == vertex_pattern: + vertex_count += 1 + if vertex_count < 3: + next_patterns = [vertex_pattern, endloop_pattern] + else: + next_patterns = [endloop_pattern] + if matched_pattern == endloop_pattern: + next_patterns = [endfacet_pattern] + if matched_pattern == endfacet_pattern: + next_patterns = [facet_pattern, endsolid_pattern] - # see https://code.djangoproject.com/ticket/20020 - # stlfile.close() - return stlfile + line = stlfile.readline().strip() + + if matched_pattern != endsolid_pattern: + raise forms.ValidationError("Not a valid ascii STL file.") + + # see https://code.djangoproject.com/ticket/20020 + # stlfile.close() + return stlfile class GeometryForm(STLUploadForm): - class Meta: - model = Geometry - fields = ['name', 'description', 'public', 'expiration', 'file', 'sourcefile'] + + class Meta: + model = Geometry + fields = ['name', 'description', 'public', 'expiration', 'file', 'sourcefile'] class AnonymousGeometryForm(STLUploadForm): - expiration = forms.ChoiceField(choices=Geometry.EXPIRATION_CHOICES[:-1]) - class Meta: - model = Geometry - fields = ['name', 'description', 'public', 'expiration', 'file'] + expiration = forms.ChoiceField(choices=Geometry.EXPIRATION_CHOICES[:-1]) + class Meta: + model = Geometry + fields = ['name', 'description', 'public', 'expiration', 'file'] diff --git a/pastebin/models.py b/pastebin/models.py index f955579..be7793f 100644 --- a/pastebin/models.py +++ b/pastebin/models.py @@ -5,164 +5,160 @@ import re from hashlib import md5 from datetime import datetime, timedelta -from django.core.urlresolvers import reverse +from django.urls import reverse from django.contrib.auth.models import User from django.db import models vertex_pattern = re.compile(r'vertex\s+([0-9.e+-]+)\s+([0-9.e+-]+)\s+([0-9.e+-]+)') + def safe_upload_path(base_dir): - def generate_path(instance, filename): + def generate_path(instance, filename): - ext = os.path.splitext(filename)[1] + ext = os.path.splitext(filename)[1] - md5sum = md5() - md5sum.update(instance.name - + str(datetime.now()) - + filename) - randomname = md5sum.hexdigest() + md5sum = md5() + md5sum.update(instance.name + str(datetime.now()) + filename) + randomname = md5sum.hexdigest() - return os.path.join(base_dir,'%s%s' % (randomname, ext)) - - return generate_path + return os.path.join(base_dir, '%s%s' % (randomname, ext)) + return generate_path class Geometry(models.Model): - HOUR = 0 - DAY = 1 - WEEK = 2 - MONTH = 3 - FORERVER = 4 + HOUR = 0 + DAY = 1 + WEEK = 2 + MONTH = 3 + FORERVER = 4 - EXPIRATION_CHOICES = ((HOUR, 'one hour'), - (DAY, 'one day'), - (WEEK, 'one week'), - (MONTH, 'one month'), - (FORERVER, 'forever')) + EXPIRATION_CHOICES = ((HOUR, 'one hour'), (DAY, 'one day'), (WEEK, 'one week'), + (MONTH, 'one month'), (FORERVER, 'forever')) - DELTAS = { HOUR : timedelta(hours = 1), - DAY : timedelta(days = 1), - WEEK : timedelta(weeks = 1), - MONTH : timedelta(weeks = 4)} + DELTAS = { + HOUR: timedelta(hours=1), + DAY: timedelta(days=1), + WEEK: timedelta(weeks=1), + MONTH: timedelta(weeks=4) + } - name = models.CharField(max_length = 128) - description = models.TextField(blank=True) - user = models.ForeignKey(User, blank=True, null=True) - date = models.DateTimeField(auto_now_add=True) - expiration = models.IntegerField(default = 0, choices = EXPIRATION_CHOICES) - public = models.BooleanField(default=True) - polycount = models.IntegerField(blank=True, default=0) - width = models.FloatField(blank=True, default=0) - depth = models.FloatField(blank=True, default=0) - height = models.FloatField(blank=True, default=0) - file = models.FileField(upload_to=safe_upload_path('models')) - sourcefile = models.FileField(upload_to=safe_upload_path('sources'), blank=True) + name = models.CharField(max_length=128) + description = models.TextField(blank=True) + user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE) + date = models.DateTimeField(auto_now_add=True) + expiration = models.IntegerField(default=0, choices=EXPIRATION_CHOICES) + public = models.BooleanField(default=True) + polycount = models.IntegerField(blank=True, default=0) + width = models.FloatField(blank=True, default=0) + depth = models.FloatField(blank=True, default=0) + height = models.FloatField(blank=True, default=0) + file = models.FileField(upload_to=safe_upload_path('models')) + sourcefile = models.FileField(upload_to=safe_upload_path('sources'), blank=True) - def get_absolute_url(self): - return reverse('geometry_details', kwargs={'id' : self.pk}) + def get_absolute_url(self): + return reverse('geometry_details', kwargs={'id': self.pk}) - @classmethod - def get_latest(cls): - return cls.objects.all().filter(public = True).order_by('-date')[:10] + @classmethod + def get_latest(cls): + return cls.objects.all().filter(public=True).order_by('-date')[:10] - def get_expiration_date(self): - for expiration in [self.HOUR, self.DAY, self.WEEK, self.MONTH]: - if self.expiration == expiration: - return self.date + self.DELTAS[expiration] + def get_expiration_date(self): + for expiration in [self.HOUR, self.DAY, self.WEEK, self.MONTH]: + if self.expiration == expiration: + return self.date + self.DELTAS[expiration] - return None + return None + def _generate_meta_infos(self): + print("Generating metainfos %s" % self.name) - def _generate_meta_infos(self): - print "Generating metainfos %s" % self.name + self.file.open() - self.file.open() + count = 0 + min_coord = [None, None, None] + max_coord = [None, None, None] - count = 0 - min_coord = [None,None,None] - max_coord = [None,None,None] + if self.file.read(5) != "solid": + print("binary") + # Skip header + self.file.seek(80) + count = struct.unpack("i", self.file.read(4))[0] - if self.file.read(5) != "solid": - print "binary" - #Skip header - self.file.seek(80) - count = struct.unpack("i",self.file.read(4))[0] + done = False + for pos in range(0, count): + # Skip normal (3 * 32bit) + self.file.seek(self.file.tell() + 3 * 4) + # Loop over each coordinate + for vert in range(0, 3): + # Loop over each coordinate + for i in range(0, 3): + x = struct.unpack("[0-9]+)/$', GeometryListView.as_view(), name='geometry_list'), - url(r'^delete/(?P\d+)/$', GeometryDelete.as_view(), name='geometry_delete'), - url(r'^(?P\d+)/$', GeometryView.as_view(), name='geometry_details')) - \ No newline at end of file +urlpatterns = [ + re_path(r'^new/$', GeometryCreate.as_view(), name='geometry_create'), + re_path(r'^list/$', GeometryListView.as_view(), name='geometry_list'), + re_path(r'^list/page/(?P[0-9]+)/$', GeometryListView.as_view(), name='geometry_list'), + re_path(r'^delete/(?P\d+)/$', GeometryDelete.as_view(), name='geometry_delete'), + re_path(r'^(?P\d+)/$', GeometryView.as_view(), name='geometry_details') +] \ No newline at end of file diff --git a/pastebin/views.py b/pastebin/views.py index e102f54..46e83d2 100644 --- a/pastebin/views.py +++ b/pastebin/views.py @@ -1,23 +1,25 @@ from django.views.generic.edit import CreateView, DeleteView from django.views.generic.detail import DetailView -from django.core.urlresolvers import reverse +from django.urls import reverse from django.views.generic.base import ContextMixin from django.core.exceptions import PermissionDenied from django.views.generic.base import TemplateView from django.views.generic.list import ListView -from forms import GeometryForm, AnonymousGeometryForm -from models import Geometry +from pastebin.forms import GeometryForm, AnonymousGeometryForm +from pastebin.models import Geometry class LastesGeometriesMixin(ContextMixin): - def get_context_data(self, **kwargs): - context = super(LastesGeometriesMixin, self).get_context_data(**kwargs) - context['latest_geometries'] = Geometry.get_latest() - return context + + def get_context_data(self, **kwargs): + context = super(LastesGeometriesMixin, self).get_context_data(**kwargs) + context['latest_geometries'] = Geometry.get_latest() + return context + class GeometryListView(ListView, LastesGeometriesMixin): - queryset = Geometry.objects.all().filter(public = True).order_by('date') + queryset = Geometry.objects.all().filter(public=True).order_by('date') paginate_by = 50 paginate_orphans = 25 page_kwarg = 'page' @@ -26,10 +28,10 @@ class GeometryListView(ListView, LastesGeometriesMixin): class GeometryView(DetailView): - model = Geometry - pk_url_kwarg = 'id' - context_object_name = 'geometry' - template_name = 'pastebin/geometry.html' + model = Geometry + pk_url_kwarg = 'id' + context_object_name = 'geometry' + template_name = 'pastebin/geometry.html' class GeometryCreate(CreateView, LastesGeometriesMixin): @@ -37,28 +39,29 @@ class GeometryCreate(CreateView, LastesGeometriesMixin): template_name = 'pastebin/geometry_create.html' def get_success_url(self): - return reverse('geometry_details', kwargs={'id' :self.object.id}) + return reverse('geometry_details', kwargs={'id': self.object.id}) def get_form_class(self): - if self.request.user.is_authenticated() : - return GeometryForm - else: - return AnonymousGeometryForm + if self.request.user.is_authenticated(): + return GeometryForm + else: + return AnonymousGeometryForm def form_valid(self, form): - res = super(GeometryCreate, self).form_valid(form) - - if self.request.user.is_authenticated() : - self.object.user = self.request.user - self.object.save() + res = super(GeometryCreate, self).form_valid(form) + + if self.request.user.is_authenticated(): + self.object.user = self.request.user + self.object.save() + + return res - return res class GeometryDelete(DeleteView, LastesGeometriesMixin): model = Geometry pk_url_kwarg = 'id' template_name = 'pastebin/geometry_delete.html' - success_url ='/' + success_url = '/' def check_user(self, request): obj = self.get_object() @@ -67,8 +70,8 @@ class GeometryDelete(DeleteView, LastesGeometriesMixin): def get(self, request, *args, **kwargs): self.check_user(request) - return super(GeometryDelete,self).get(self, request, *args, **kwargs) + return super(GeometryDelete, self).get(self, request, *args, **kwargs) def delete(self, request, *args, **kwargs): self.check_user(request) - return super(GeometryDelete,self).delete(self, request, *args, **kwargs) \ No newline at end of file + return super(GeometryDelete, self).delete(self, request, *args, **kwargs) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index d757d4a..ce034d8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ -Django==1.5.4 -Werkzeug==0.9.4 -django-extensions==1.2.2 -six==1.4.1 -wsgiref==0.1.2 +asgiref==3.7.2 +Django==4.2.3 +django-extensions==3.2.3 +MarkupSafe==2.1.3 +sqlparse==0.4.4 +Werkzeug==2.3.6 diff --git a/users/forms.py b/users/forms.py index 8fff434..c38bc3d 100644 --- a/users/forms.py +++ b/users/forms.py @@ -2,93 +2,86 @@ from django import forms from django.forms import ModelForm from django.contrib.auth.models import User + class UserCreateForm(ModelForm): - password1 = forms.CharField(label='Password', widget=forms.PasswordInput) - password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) - - class Meta: - model = User - fields = ['username', 'email'] + password1 = forms.CharField(label='Password', widget=forms.PasswordInput) + password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) + class Meta: + model = User + fields = ['username', 'email'] - def clean_password2(self): - password1 = self.cleaned_data.get("password1") - password2 = self.cleaned_data.get("password2") - - if password1 and password2 and password1 != password2: - raise forms.ValidationError("Passwords don't match") - - return password1 + def clean_password2(self): + password1 = self.cleaned_data.get("password1") + password2 = self.cleaned_data.get("password2") + if password1 and password2 and password1 != password2: + raise forms.ValidationError("Passwords don't match") - def clean_email(self): - #Make sure Email is unique - email = self.cleaned_data.get("email") - if User.objects.filter(email = email): - raise forms.ValidationError("Email already in use.") + return password1 - return email + def clean_email(self): + # Make sure Email is unique + email = self.cleaned_data.get("email") + if User.objects.filter(email=email): + raise forms.ValidationError("Email already in use.") + return email - def save(self, commit=True): - user = super(UserCreateForm, self).save(commit=False) - user.set_password(self.cleaned_data["password1"]) - user.is_active = False - if commit: - user.save() - return user - + def save(self, commit=True): + user = super(UserCreateForm, self).save(commit=False) + user.set_password(self.cleaned_data["password1"]) + user.is_active = False + if commit: + user.save() + return user class UserUpdateForm(ModelForm): - new_password1 = forms.CharField(label='New Password', - widget=forms.PasswordInput, - required=False) - new_password2 = forms.CharField(label='New Password confirmation', - widget=forms.PasswordInput, - required=False) - current_password = forms.CharField(label='Current Password', widget=forms.PasswordInput) + new_password1 = forms.CharField(label='New Password', + widget=forms.PasswordInput, + required=False) + new_password2 = forms.CharField(label='New Password confirmation', + widget=forms.PasswordInput, + required=False) + current_password = forms.CharField(label='Current Password', widget=forms.PasswordInput) - class Meta: - model = User - fields = ['email'] + class Meta: + model = User + fields = ['email'] + def clean_current_password(self): + current_password = self.cleaned_data.get("current_password") - def clean_current_password(self): - current_password = self.cleaned_data.get("current_password") - - if not self.instance.check_password(current_password): - raise forms.ValidationError("Password incorrect") + if not self.instance.check_password(current_password): + raise forms.ValidationError("Password incorrect") - return current_password + return current_password + def clean_new_password2(self): + password1 = self.cleaned_data.get("new_password1") + password2 = self.cleaned_data.get("new_password2") - def clean_new_password2(self): - password1 = self.cleaned_data.get("new_password1") - password2 = self.cleaned_data.get("new_password2") - - if password1 and password2 and password1 != password2: - raise forms.ValidationError("Passwords don't match") - - return password1 + if password1 and password2 and password1 != password2: + raise forms.ValidationError("Passwords don't match") + return password1 - def clean_email(self): - #Make sure Email is still unique - email = self.cleaned_data.get("email") - if User.objects.filter(email = email).exclude(id=self.instance.id): - raise forms.ValidationError("Email already in use.") + def clean_email(self): + # Make sure Email is still unique + email = self.cleaned_data.get("email") + if User.objects.filter(email=email).exclude(id=self.instance.id): + raise forms.ValidationError("Email already in use.") - return email + return email + def save(self, commit=True): + user = super(UserUpdateForm, self).save(commit=False) - def save(self, commit=True): - user = super(UserUpdateForm, self).save(commit=False) - - password = self.cleaned_data.get("new_password1") - if password: - user.set_password(password) - - if commit: - user.save() - return user \ No newline at end of file + password = self.cleaned_data.get("new_password1") + if password: + user.set_password(password) + + if commit: + user.save() + return user \ No newline at end of file diff --git a/users/urls.py b/users/urls.py index ebc39a3..e1b9f4e 100644 --- a/users/urls.py +++ b/users/urls.py @@ -1,37 +1,57 @@ -from django.conf.urls import patterns, include, url -from django.core.urlresolvers import reverse_lazy +from django.urls import re_path, path, reverse_lazy +from django.contrib.auth import views as auth_views from pastebin.models import Geometry -from views import * +from users.views import * -urlpatterns = patterns('', - url(r'^signup/$', UserCreateView.as_view(), name='signup'), - url(r'^confirm/(?P\d+)/$', SendConfirmationView.as_view(), name='send_confirmation'), - url(r'^confirm/(?P\d+)/(?P.+)/$', CheckConfirmationView.as_view(), name='check_confirmation'), - - url(r'^update/(?P\d+)/$', UserUpdateView.as_view(), name='user_update'), - - url(r'^password/reset/$', 'django.contrib.auth.views.password_reset', {'extra_context' : {'latest_geometries' : Geometry.get_latest()}, - 'template_name' : 'users/password_reset.html', - 'post_reset_redirect' : reverse_lazy('password_reset_sent')}, - name='password_reset'), - - url(r'^password/reset/(?P[0-9A-Za-z]+)/(?P.+)/$', 'django.contrib.auth.views.password_reset_confirm', {'extra_context' : {'latest_geometries' : Geometry.get_latest()}, - 'template_name' : 'users/password_reset_confirm.html', - 'post_reset_redirect' : reverse_lazy('login')}, - name='password_reset_confirm'), - - url(r'^password/reset/sent/$', 'django.contrib.auth.views.password_reset_done', {'extra_context' : {'latest_geometries' : Geometry.get_latest()}, - 'template_name' : 'users/password_reset_sent.html',}, - name='password_reset_sent'), - - - url(r'^login/$', 'django.contrib.auth.views.login', {'extra_context' : {'latest_geometries' : Geometry.get_latest()}, - 'template_name' : 'users/login.html'}, - name='login'), - - url(r'^logout/$', 'django.contrib.auth.views.logout',{'extra_context' : {'latest_geometries' : Geometry.get_latest()}, - 'next_page' : reverse_lazy('login')}, - name='logout'), - ) \ No newline at end of file +urlpatterns = [ + re_path(r'^signup/$', UserCreateView.as_view(), name='signup'), + re_path(r'^confirm/(?P\d+)/$', SendConfirmationView.as_view(), name='send_confirmation'), + re_path(r'^confirm/(?P\d+)/(?P.+)/$', + CheckConfirmationView.as_view(), + name='check_confirmation'), + re_path(r'^update/(?P\d+)/$', UserUpdateView.as_view(), name='user_update'), + path('password/reset/', + auth_views.PasswordResetView.as_view(), { + 'extra_context': { + 'latest_geometries': Geometry.get_latest() + }, + 'template_name': 'users/password_reset.html', + 'post_reset_redirect': reverse_lazy('password_reset_sent') + }, + name='password_reset'), + path('password/reset/confirm/', + auth_views.PasswordResetConfirmView.as_view(), { + 'extra_context': { + 'latest_geometries': Geometry.get_latest() + }, + 'template_name': 'users/password_reset_confirm.html', + 'post_reset_redirect': reverse_lazy('login') + }, + name='password_reset_confirm'), + path('password/reset/sent/', + auth_views.PasswordResetDoneView.as_view(), { + 'extra_context': { + 'latest_geometries': Geometry.get_latest() + }, + 'template_name': 'users/password_reset_sent.html', + }, + name='password_reset_sent'), + path('login/', + auth_views.LoginView.as_view(), { + 'extra_context': { + 'latest_geometries': Geometry.get_latest() + }, + 'template_name': 'users/login.html' + }, + name='login'), + path('logout/', + auth_views.LogoutView.as_view(), { + 'extra_context': { + 'latest_geometries': Geometry.get_latest() + }, + 'next_page': reverse_lazy('login') + }, + name='logout'), +] \ No newline at end of file diff --git a/users/views.py b/users/views.py index 43da46b..aea6717 100644 --- a/users/views.py +++ b/users/views.py @@ -1,104 +1,105 @@ from django.views.generic.edit import CreateView, UpdateView from django.views.generic.base import TemplateView from django.contrib.auth.models import User -from django.core.urlresolvers import reverse -from django.contrib.sites.models import get_current_site +from django.urls import reverse +from django.contrib.sites.shortcuts import get_current_site from django.contrib.auth.tokens import default_token_generator from django.template import loader from django.utils.http import int_to_base36 -from django.http import Http404 +from django.http import Http404 from django.core.exceptions import PermissionDenied from pastebin.views import LastesGeometriesMixin -from forms import UserCreateForm, UserUpdateForm +from users.forms import UserCreateForm, UserUpdateForm + class UserCreateView(CreateView, LastesGeometriesMixin): - model = User - form_class = UserCreateForm - template_name = 'users/signup.html' + model = User + form_class = UserCreateForm + template_name = 'users/signup.html' - - def get_success_url(self): - return reverse('send_confirmation', kwargs={'user_id' : self.object.pk}) + def get_success_url(self): + return reverse('send_confirmation', kwargs={'user_id': self.object.pk}) class UserUpdateView(UpdateView, LastesGeometriesMixin): - model = User - form_class = UserUpdateForm - template_name = 'users/user_update.html' - pk_url_kwarg = 'user_id' + model = User + form_class = UserUpdateForm + template_name = 'users/user_update.html' + pk_url_kwarg = 'user_id' - def get_queryset(self): - return self.model.objects.filter(id=self.request.user.id) - - def get_success_url(self): - return reverse('geometry_create') + def get_queryset(self): + return self.model.objects.filter(id=self.request.user.id) + def get_success_url(self): + return reverse('geometry_create') class SendConfirmationView(TemplateView, LastesGeometriesMixin): - template_name = 'users/send_confirmation.html' - email_template_name = 'users/confirmation_email.txt' + template_name = 'users/send_confirmation.html' + email_template_name = 'users/confirmation_email.txt' - def get_context_data(self, **kwargs): - context = super(SendConfirmationView, self).get_context_data(**kwargs) - context['confirm_user'] = User.objects.get(id=kwargs['user_id']) - return context + def get_context_data(self, **kwargs): + context = super(SendConfirmationView, self).get_context_data(**kwargs) + context['confirm_user'] = User.objects.get(id=kwargs['user_id']) + return context - def get(self, request, *args, **kwargs): - try: - user = User.objects.get(id=kwargs['user_id']) - except User.DoesNotExist: - raise Http404 + def get(self, request, *args, **kwargs): + try: + user = User.objects.get(id=kwargs['user_id']) + except User.DoesNotExist: + raise Http404 - if user.is_active: - raise Http404 - - site_name = get_current_site(self.request).name - uid = int_to_base36(user.pk) - token = default_token_generator.make_token(user) - link = request.build_absolute_uri(reverse('check_confirmation', kwargs={'user_id' : user.pk, 'token' : token})) + if user.is_active: + raise Http404 - context = { - 'email': user.email, - 'site_name': site_name, - 'validation_link': link, - 'user': user - } + site_name = get_current_site(self.request).name + uid = int_to_base36(user.pk) + token = default_token_generator.make_token(user) + link = request.build_absolute_uri( + reverse('check_confirmation', kwargs={ + 'user_id': user.pk, + 'token': token + })) - subject = "Validate your registration at %s" % site_name - email = loader.render_to_string(self.email_template_name, context) - user.email_user(subject,email) + context = { + 'email': user.email, + 'site_name': site_name, + 'validation_link': link, + 'user': user + } + subject = "Validate your registration at %s" % site_name + email = loader.render_to_string(self.email_template_name, context) + user.email_user(subject, email) - return super(SendConfirmationView,self).get(self, request, *args, **kwargs) - + return super(SendConfirmationView, self).get(self, request, *args, **kwargs) class CheckConfirmationView(TemplateView, LastesGeometriesMixin): - template_name = 'users/check_confirmation.html' + template_name = 'users/check_confirmation.html' - def get_context_data(self, **kwargs): - context = super(CheckConfirmationView, self).get_context_data(**kwargs) - context['confirm_user'] = User.objects.get(id=kwargs['user_id']) - return context + def get_context_data(self, **kwargs): + context = super(CheckConfirmationView, self).get_context_data(**kwargs) + context['confirm_user'] = User.objects.get(id=kwargs['user_id']) + return context - def get(self, request, *args, **kwargs): - try: - user = User.objects.get(id=kwargs['user_id']) - except User.DoesNotExist: - raise Http404 + def get(self, request, *args, **kwargs): + try: + user = User.objects.get(id=kwargs['user_id']) + except User.DoesNotExist: + raise Http404 - if user.is_active: - raise Http404 + if user.is_active: + raise Http404 - if not default_token_generator.check_token(user,kwargs['token']): - raise Http404 + if not default_token_generator.check_token(user, kwargs['token']): + raise Http404 - user.is_active = True - user.save() + user.is_active = True + user.save() - print "Acitvating %s" % user.username + print("Acitvating %s" % user.username) - return super(CheckConfirmationView,self).get(self, request, *args, **kwargs) + return super(CheckConfirmationView, self).get(self, request, *args, **kwargs)