commit
097724722f
11
.travis.yml
11
.travis.yml
@ -1,6 +1,9 @@
|
||||
language: python
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
install: "pip install --allow-external argparse -r requirements.txt"
|
||||
script: "fab travis_ci"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
install: "pip install -r requirements.txt"
|
||||
script:
|
||||
- "DJANGO_SETTINGS_MODULE='tests.settings' coverage run ./manage.py django test"
|
||||
- "coverage report -m --fail-under=80"
|
||||
- "flake8 --max-line-length=150 --statistics openslides tests"
|
||||
|
@ -4,6 +4,11 @@
|
||||
|
||||
http://openslides.org
|
||||
|
||||
Version 2.0.0 (unreleased)
|
||||
==========================
|
||||
|
||||
- Changed supported Python version to >= 3.3
|
||||
|
||||
Version 1.6.1 (unreleased)
|
||||
==========================
|
||||
[https://github.com/OpenSlides/OpenSlides/issues?milestone=16]
|
||||
|
22
README.rst
22
README.rst
@ -26,12 +26,12 @@ Installation on GNU/Linux or Mac OS X
|
||||
|
||||
1. Check requirements
|
||||
|
||||
Make sure that you have installed Python Programming Language 2 (>= 2.6.9)
|
||||
Make sure that you have installed Python Programming Language 3 (>= 3.3)
|
||||
on your system. You will also need the Python development headers.
|
||||
|
||||
For example for Ubuntu run::
|
||||
|
||||
$ sudo apt-get install python-dev
|
||||
$ sudo apt-get install python3-dev
|
||||
|
||||
2. Setup a virtual environment with Virtual Python Environment builder
|
||||
(optional)
|
||||
@ -49,7 +49,7 @@ Installation on GNU/Linux or Mac OS X
|
||||
|
||||
$ mkdir OpenSlides
|
||||
$ cd OpenSlides
|
||||
$ virtualenv .virtualenv
|
||||
$ virtualenv -p /usr/bin/python3 .virtualenv
|
||||
$ source .virtualenv/bin/activate
|
||||
|
||||
3. Install OpenSlides
|
||||
@ -67,11 +67,6 @@ Installation on GNU/Linux or Mac OS X
|
||||
OpenSlides will install all required python packages (see
|
||||
requirements_production.txt).
|
||||
|
||||
If you use Python 2.6.x, you have to add the option `--allow-external
|
||||
argparse` to the pip command::
|
||||
|
||||
$ pip install --allow-external argparse openslides
|
||||
|
||||
|
||||
Installation on Windows
|
||||
-----------------------
|
||||
@ -82,18 +77,18 @@ portable version you should observe the following install steps.*
|
||||
|
||||
1. Check requirements
|
||||
|
||||
Make sure that you have installed Python Programming Language 2 (>= 2.6.9)
|
||||
Make sure that you have installed Python Programming Language 3 (>= 3.3)
|
||||
and Setuptools on your system.
|
||||
|
||||
a. Download and run the `Python 32-bit MSI installer
|
||||
<http://www.python.org/ftp/python/2.7.6/python-2.7.6.msi>`_. Note
|
||||
<https://www.python.org/ftp/python/3.4.1/python-3.4.1.msi>`_. Note
|
||||
that the 32-bit MSI installer is required even on a 64-bit Windows
|
||||
system. If you use the 64-bit MSI installer, step 3 of this
|
||||
instruction will fail unless you installed the package reportlab
|
||||
manually.
|
||||
|
||||
b. Add python directories to PATH (via Control Panel > System >
|
||||
Advanced): ``";C:\\Python27;C:\\Python27\\Scripts"``. Note that the path
|
||||
Advanced): ``";C:\\Python34;C:\\Python34\\Scripts"``. Note that the path
|
||||
can differ if you customized the install of Python in the first step.
|
||||
|
||||
c. Download and run (via double click) the last `install script
|
||||
@ -214,11 +209,6 @@ Installation and start of the development version
|
||||
|
||||
$ pip install -r requirements.txt
|
||||
|
||||
If you use Python 2.6.x, you have to add the option `--allow-external
|
||||
argparse` to the pip command::
|
||||
|
||||
$ pip install --allow-external argparse -r requirements.txt
|
||||
|
||||
For Windows run::
|
||||
|
||||
> easy_install # Insert all packages from requirements.txt and requirements_production.txt here
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# OpenSlides documentation build configuration file, created by
|
||||
# sphinx-quickstart on Mon Mar 12 08:08:56 2012.
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Extension for Sphinx to add new directive 'autoimage' which works as subclass
|
||||
# of the internal Image directive.
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
import multiprocessing
|
||||
import random
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import Queue
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import csv
|
||||
import argparse
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from random import randint, choice
|
||||
|
||||
# Import the openslide settings. Has has to be done before any other openslides
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import errno
|
||||
import glob
|
||||
|
1
fabfile.py
vendored
1
fabfile.py
vendored
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
VERSION = (2, 0, 0, 'alpha', 1) # During development it is the next release
|
||||
RELEASE = False
|
||||
|
||||
@ -38,9 +36,10 @@ def get_git_commit_id():
|
||||
try:
|
||||
git_head = open('.git/HEAD', 'r').read().rstrip()
|
||||
if git_head[:5] == 'ref: ':
|
||||
# The file is a reference. We have to follow it to get the commit id
|
||||
git_commit_id = open('.git/%s' % git_head[5:], 'r').read().rstrip()
|
||||
else:
|
||||
git_commit_id = git_head
|
||||
return git_commit_id
|
||||
except IOError:
|
||||
git_commit_id = 'unknown'
|
||||
return str(git_commit_id)
|
||||
return 'unknown'
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import argparse
|
||||
import os
|
||||
@ -13,7 +12,6 @@ from openslides import get_version
|
||||
from openslides.utils.main import (
|
||||
detect_openslides_type,
|
||||
ensure_settings,
|
||||
filesystem2unicode,
|
||||
get_browser_url,
|
||||
get_database_path_from_settings,
|
||||
get_default_settings_path,
|
||||
@ -244,10 +242,9 @@ def syncdb(settings, args):
|
||||
Run syncdb to create or update the database.
|
||||
"""
|
||||
ensure_settings(settings, args)
|
||||
# TODO: Check use of filesystem2unicode here.
|
||||
db_file = get_database_path_from_settings()
|
||||
if db_file is not None:
|
||||
db_dir = filesystem2unicode(os.path.dirname(db_file))
|
||||
db_dir = os.path.dirname(db_file)
|
||||
if not os.path.exists(db_dir):
|
||||
os.makedirs(db_dir)
|
||||
if not os.path.exists(db_file):
|
||||
|
@ -1,3 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import widgets # noqa
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
|
@ -1,3 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import main_menu, personal_info, signals, slides, widgets # noqa
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import csv
|
||||
import re
|
||||
|
||||
@ -23,14 +21,15 @@ def import_agenda_items(csvfile):
|
||||
else:
|
||||
csvfile.seek(0)
|
||||
# Check dialect
|
||||
dialect = csv.Sniffer().sniff(csvfile.readline())
|
||||
dialect = csv.Sniffer().sniff(csvfile.readline().decode('utf8'))
|
||||
dialect = csv_ext.patchup(dialect)
|
||||
csvfile.seek(0)
|
||||
# Parse CSV file
|
||||
with transaction.commit_on_success():
|
||||
success_lines = []
|
||||
error_lines = []
|
||||
for (line_no, line) in enumerate(csv.reader(csvfile, dialect=dialect)):
|
||||
for (line_no, line) in enumerate(csv.reader(
|
||||
(line.decode('utf8') for line in csvfile.readlines()), dialect=dialect)):
|
||||
if line_no == 0:
|
||||
# Do not read the header line
|
||||
continue
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
from ckeditor.widgets import CKEditorWidget
|
||||
|
||||
@ -77,5 +75,5 @@ class AppendSpeakerForm(CssClassMixin, forms.Form):
|
||||
if Speaker.objects.filter(person=speaker, item=self.item, begin_time=None).exists():
|
||||
raise forms.ValidationError(ugettext_lazy(
|
||||
'%s is already on the list of speakers.'
|
||||
% unicode(speaker)))
|
||||
% str(speaker)))
|
||||
return speaker
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.main_menu import MainMenuEntry
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
@ -133,7 +131,7 @@ class Item(SlideMixin, AbsoluteUrlMixin, MPTTModel):
|
||||
raise ValidationError(_('Organizational items can not have agenda items as child elements.'))
|
||||
return super(Item, self).clean()
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.get_title()
|
||||
|
||||
def get_absolute_url(self, link='detail'):
|
||||
@ -397,8 +395,8 @@ class Speaker(AbsoluteUrlMixin, models.Model):
|
||||
super(Speaker, self).delete(*args, **kwargs)
|
||||
self.check_and_update_projector()
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.person)
|
||||
def __str__(self):
|
||||
return str(self.person)
|
||||
|
||||
def get_absolute_url(self, link='detail'):
|
||||
if link == 'detail':
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.personal_info import PersonalInfo
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from haystack import indexes
|
||||
from .models import Item
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from django import forms
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from openslides.config.api import config
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from . import views
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# TODO: Rename all views and template names
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
@ -394,7 +393,7 @@ class SpeakerAppendView(SingleObjectMixin, RedirectView):
|
||||
else:
|
||||
try:
|
||||
Speaker.objects.add(item=self.object, person=request.user)
|
||||
except OpenSlidesError, e:
|
||||
except OpenSlidesError as e:
|
||||
messages.error(request, e)
|
||||
else:
|
||||
messages.success(request, _('You were successfully added to the list of speakers.'))
|
||||
@ -627,7 +626,7 @@ class CurrentListOfSpeakersView(RedirectView):
|
||||
if self.request.user.has_perm('agenda.can_be_speaker'):
|
||||
try:
|
||||
Speaker.objects.add(self.request.user, item)
|
||||
except OpenSlidesError, e:
|
||||
except OpenSlidesError as e:
|
||||
messages.error(request, e)
|
||||
else:
|
||||
messages.success(request, _('You were successfully added to the list of speakers.'))
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.widgets import Widget
|
||||
|
@ -1,3 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import main_menu, personal_info, signals, slides, template, widgets # noqa
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.main_menu import MainMenuEntry
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
@ -32,8 +30,8 @@ class AssignmentCandidate(RelatedModelMixin, models.Model):
|
||||
class Meta:
|
||||
unique_together = ("assignment", "person")
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.person)
|
||||
def __str__(self):
|
||||
return str(self.person)
|
||||
|
||||
def get_related_model(self):
|
||||
"""
|
||||
@ -69,7 +67,7 @@ class Assignment(SlideMixin, AbsoluteUrlMixin, models.Model):
|
||||
ordering = ('name',)
|
||||
verbose_name = ugettext_noop('Election')
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self, link='detail'):
|
||||
@ -289,8 +287,8 @@ class AssignmentOption(BaseOption):
|
||||
candidate = PersonField()
|
||||
vote_class = AssignmentVote
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.candidate)
|
||||
def __str__(self):
|
||||
return str(self.candidate)
|
||||
|
||||
|
||||
class AssignmentPoll(SlideMixin, RelatedModelMixin, CollectDefaultVotesMixin,
|
||||
@ -306,7 +304,7 @@ class AssignmentPoll(SlideMixin, RelatedModelMixin, CollectDefaultVotesMixin,
|
||||
max_length=79, null=True, blank=True,
|
||||
verbose_name=ugettext_lazy("Comment on the ballot paper"))
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return _("Ballot %d") % self.get_ballot()
|
||||
|
||||
def get_absolute_url(self, link='update'):
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.personal_info import PersonalInfo
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from haystack import indexes
|
||||
from .models import Assignment
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openslides.projector.api import register_slide_model
|
||||
|
||||
from .models import Assignment, AssignmentPoll
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.dispatch import receiver
|
||||
|
||||
from openslides.utils.signals import template_manipulation
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from . import views
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.shortcuts import redirect
|
||||
@ -68,7 +66,7 @@ class AssignmentDetail(DetailView):
|
||||
user = form.cleaned_data['candidate']
|
||||
try:
|
||||
self.object.run(user, self.request.user)
|
||||
except NameError, e:
|
||||
except NameError as e:
|
||||
messages.error(self.request, e)
|
||||
else:
|
||||
messages.success(self.request, _(
|
||||
@ -106,7 +104,7 @@ class AssignmentSetStatusView(SingleObjectMixin, RedirectView):
|
||||
if status is not None:
|
||||
try:
|
||||
self.object.set_status(status)
|
||||
except ValueError, e:
|
||||
except ValueError as e:
|
||||
messages.error(self.request, e)
|
||||
else:
|
||||
messages.success(
|
||||
@ -124,7 +122,7 @@ class AssignmentRunView(SingleObjectMixin, PermissionMixin, View):
|
||||
assignment = self.get_object()
|
||||
try:
|
||||
assignment.run(self.request.user, self.request.user)
|
||||
except NameError, e:
|
||||
except NameError as e:
|
||||
messages.error(self.request, e)
|
||||
else:
|
||||
messages.success(
|
||||
@ -142,7 +140,8 @@ class AssignmentRunDeleteView(SingleObjectMixin, RedirectView):
|
||||
"assignment.can_manage_assignment"):
|
||||
try:
|
||||
self.object.delrun(self.request.user, blocked=True)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
# TODO: only catch relevant exception
|
||||
messages.error(self.request, e)
|
||||
else:
|
||||
messages.success(self.request, _(
|
||||
@ -168,7 +167,8 @@ class AssignmentRunOtherDeleteView(SingleObjectMixin, QuestionView):
|
||||
self._get_person_information()
|
||||
try:
|
||||
self.object.delrun(self.person, blocked=False)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
# TODO: only catch relevant exception
|
||||
self.error = e
|
||||
else:
|
||||
self.error = False
|
||||
@ -400,7 +400,7 @@ class AssignmentPDF(PDFView):
|
||||
|
||||
# Add result rows
|
||||
elected_candidates = list(assignment.elected)
|
||||
for candidate, poll_list in vote_results.iteritems():
|
||||
for candidate, poll_list in vote_results.items():
|
||||
row = []
|
||||
|
||||
candidate_string = candidate.clean_name
|
||||
@ -595,7 +595,7 @@ class AssignmentPollPDF(PDFView):
|
||||
cell.append(Spacer(0, 1.3 * cm))
|
||||
|
||||
# print ballot papers
|
||||
for user in xrange(number / 2):
|
||||
for user in range(number // 2):
|
||||
if len(options) > 13:
|
||||
data.append([cellcolumnA, cell])
|
||||
else:
|
||||
@ -629,7 +629,7 @@ class AssignmentPollPDF(PDFView):
|
||||
cell.append(Spacer(0, 0.75 * cm))
|
||||
|
||||
# print ballot papers
|
||||
for user in xrange(number / 2):
|
||||
for user in range(number // 2):
|
||||
if len(options) > 22:
|
||||
data.append([cellcolumnA, cell])
|
||||
else:
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.widgets import Widget
|
||||
|
@ -1,3 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import main_menu # noqa
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from .exceptions import ConfigError, ConfigNotFound
|
||||
from .models import ConfigStore
|
||||
from .signals import config_signal
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openslides.utils.exceptions import OpenSlidesError
|
||||
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.main_menu import MainMenuEntry
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openslides.config.api import config
|
||||
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_noop
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.dispatch import Signal
|
||||
|
||||
config_signal = Signal(providing_args=[])
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from openslides.utils.views import RedirectView
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
|
@ -1,3 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import main_menu, signals, slides, widgets # noqa
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
|
||||
from openslides.utils.forms import CssClassMixin
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.main_menu import MainMenuEntry
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.core.management.commands.syncdb import Command as _Command
|
||||
|
||||
from openslides.core.signals import post_database_setup
|
||||
|
@ -27,7 +27,7 @@ class CustomSlide(SlideMixin, AbsoluteUrlMixin, models.Model):
|
||||
('can_use_chat', ugettext_noop('Can use the chat')),
|
||||
)
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
def get_absolute_url(self, link='update'):
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
from django.dispatch import receiver, Signal
|
||||
from django.utils.translation import ugettext as _
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openslides.projector.api import register_slide_model
|
||||
|
||||
from .models import CustomSlide
|
||||
|
@ -35,9 +35,11 @@
|
||||
{% if forloop.first %}
|
||||
<ol class="searchresults">
|
||||
{% endif %}
|
||||
{% with result_template=result.app_label|add:"-results.html" %}
|
||||
{% include "search/"|add:result_template %}
|
||||
{% endwith %}
|
||||
{% if result.app_label %}
|
||||
{% with result_template=result.app_label|add:"-results.html" %}
|
||||
{% include "search/"|add:result_template %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% if forloop.last %}
|
||||
</ol>
|
||||
{% endif %}
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import template
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from openslides.utils.views import RedirectView
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import PermissionDenied
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.config.api import config
|
||||
|
@ -1,11 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import copy
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.main import filesystem2unicode
|
||||
from openslides.utils.plugins import collect_plugins
|
||||
|
||||
SITE_ROOT = os.path.realpath(os.path.dirname(__file__))
|
||||
@ -36,7 +33,7 @@ USE_I18N = True
|
||||
USE_L10N = True
|
||||
|
||||
LOCALE_PATHS = (
|
||||
filesystem2unicode(os.path.join(SITE_ROOT, 'locale')),
|
||||
os.path.join(SITE_ROOT, 'locale'),
|
||||
)
|
||||
|
||||
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
|
||||
@ -46,7 +43,7 @@ MEDIA_URL = '/media/'
|
||||
|
||||
# Absolute path to the directory that holds static media from ``collectstatic``
|
||||
# Example: "/home/media/static.lawrence.com/"
|
||||
STATIC_ROOT = filesystem2unicode(os.path.join(SITE_ROOT, '../collected-site-static'))
|
||||
STATIC_ROOT = os.path.join(SITE_ROOT, '../collected-site-static')
|
||||
|
||||
# URL that handles the media served from STATIC_ROOT. Make sure to use a
|
||||
# trailing slash if there is a path component (optional in other cases).
|
||||
|
@ -1,3 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import main_menu, slides, template, widgets # noqa
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.forms import ModelForm
|
||||
|
||||
from openslides.utils.forms import CssClassMixin
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.main_menu import MainMenuEntry
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import mimetypes
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
@ -53,7 +51,7 @@ class Mediafile(SlideMixin, AbsoluteUrlMixin, models.Model):
|
||||
('can_upload', ugettext_noop('Can upload files')),
|
||||
('can_manage', ugettext_noop('Can manage files')),)
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
"""
|
||||
Method for representation.
|
||||
"""
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from haystack import indexes
|
||||
from .models import Mediafile
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.dispatch import receiver
|
||||
|
||||
from openslides.utils.signals import template_manipulation
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from . import views
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.http import HttpResponse
|
||||
|
||||
from openslides.config.api import config
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.widgets import Widget
|
||||
|
@ -1,3 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import main_menu, personal_info, signals, slides, widgets # noqa
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# TODO: Rename the file to 'csv.py' when we drop python2 support. At the moment
|
||||
# the name csv has a conflict with the core-module. See:
|
||||
# http://docs.python.org/2/tutorial/modules.html#intra-package-references
|
||||
@ -38,12 +36,13 @@ def import_motions(csvfile, default_submitter, override, importing_person=None):
|
||||
csvfile.seek(0)
|
||||
|
||||
with transaction.commit_on_success():
|
||||
dialect = csv.Sniffer().sniff(csvfile.readline())
|
||||
dialect = csv.Sniffer().sniff(csvfile.readline().decode('utf8'))
|
||||
dialect = csv_ext.patchup(dialect)
|
||||
csvfile.seek(0)
|
||||
all_error_messages = []
|
||||
all_warning_messages = []
|
||||
for (line_no, line) in enumerate(csv.reader(csvfile, dialect=dialect)):
|
||||
for (line_no, line) in enumerate(csv.reader(
|
||||
(line.decode('utf8') for line in csvfile.readlines()), dialect=dialect)):
|
||||
warning = []
|
||||
if line_no < 1:
|
||||
# Do not read the header line
|
||||
@ -92,7 +91,7 @@ def import_motions(csvfile, default_submitter, override, importing_person=None):
|
||||
person_found = False
|
||||
if submitter:
|
||||
for person in Persons():
|
||||
if person.clean_name == submitter.decode('utf8'):
|
||||
if person.clean_name == submitter:
|
||||
if person_found:
|
||||
warning.append(_('Several suitable submitters found.'))
|
||||
person_found = False
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openslides.utils.exceptions import OpenSlidesError
|
||||
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.main_menu import MainMenuEntry
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import models
|
||||
from django.db.models import Max
|
||||
@ -84,7 +82,7 @@ class Motion(SlideMixin, AbsoluteUrlMixin, models.Model):
|
||||
ordering = ('identifier', )
|
||||
verbose_name = ugettext_noop('Motion')
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
"""
|
||||
Return a human readable name of this motion.
|
||||
"""
|
||||
@ -125,7 +123,7 @@ class Motion(SlideMixin, AbsoluteUrlMixin, models.Model):
|
||||
|
||||
# Solves the problem, that there can only be one motion with an empty
|
||||
# string as identifier.
|
||||
if not self.identifier and isinstance(self.identifier, basestring):
|
||||
if not self.identifier and isinstance(self.identifier, str):
|
||||
self.identifier = None
|
||||
|
||||
super(Motion, self).save(*args, **kwargs)
|
||||
@ -461,7 +459,7 @@ class Motion(SlideMixin, AbsoluteUrlMixin, models.Model):
|
||||
"""
|
||||
Return a title for the agenda.
|
||||
"""
|
||||
return unicode(self)
|
||||
return str(self)
|
||||
|
||||
def get_agenda_title_supplement(self):
|
||||
"""
|
||||
@ -551,7 +549,7 @@ class MotionVersion(AbsoluteUrlMixin, models.Model):
|
||||
class Meta:
|
||||
unique_together = ("motion", "version_number")
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
"""Return a string, representing this object."""
|
||||
counter = self.version_number or ugettext_lazy('new')
|
||||
return "Motion %s, Version %s" % (self.motion_id, counter)
|
||||
@ -587,9 +585,9 @@ class MotionSubmitter(RelatedModelMixin, models.Model):
|
||||
person = PersonField()
|
||||
"""The person, who is the submitter."""
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
"""Return the name of the submitter as string."""
|
||||
return unicode(self.person)
|
||||
return str(self.person)
|
||||
|
||||
def get_related_model(self):
|
||||
return self.motion
|
||||
@ -604,9 +602,9 @@ class MotionSupporter(models.Model):
|
||||
person = PersonField()
|
||||
"""The person, who is the supporter."""
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
"""Return the name of the supporter as string."""
|
||||
return unicode(self.person)
|
||||
return str(self.person)
|
||||
|
||||
|
||||
class Category(AbsoluteUrlMixin, models.Model):
|
||||
@ -619,7 +617,7 @@ class Category(AbsoluteUrlMixin, models.Model):
|
||||
Used to build the identifier of a motion.
|
||||
"""
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self, link='update'):
|
||||
@ -661,7 +659,7 @@ class MotionLog(models.Model):
|
||||
class Meta:
|
||||
ordering = ['-time']
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
"""
|
||||
Return a string, representing the log message.
|
||||
"""
|
||||
@ -721,7 +719,7 @@ class MotionPoll(SlideMixin, RelatedModelMixin, CollectDefaultVotesMixin,
|
||||
class Meta:
|
||||
unique_together = ("motion", "poll_number")
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
"""Return a string, representing the poll."""
|
||||
return _('Vote %d') % self.poll_number
|
||||
|
||||
@ -808,7 +806,7 @@ class State(models.Model):
|
||||
If true, the motion does not get an identifier if the state change to
|
||||
this one, else it does."""
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
"""Returns the name of the state."""
|
||||
return self.name
|
||||
|
||||
@ -843,7 +841,7 @@ class Workflow(models.Model):
|
||||
first_state = models.OneToOneField(State, related_name='+', null=True)
|
||||
"""A one-to-one relation to a state, the starting point for the workflow."""
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
"""Returns the name of the workflow."""
|
||||
return self.name
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from operator import attrgetter
|
||||
import random
|
||||
|
||||
@ -51,7 +49,7 @@ def motion_to_pdf(pdf, motion):
|
||||
cell1b = []
|
||||
cell1b.append(Spacer(0, 0.2 * cm))
|
||||
for submitter in motion.submitter.all():
|
||||
cell1b.append(Paragraph(unicode(submitter), stylesheet['Normal']))
|
||||
cell1b.append(Paragraph(str(submitter), stylesheet['Normal']))
|
||||
motion_data.append([cell1a, cell1b])
|
||||
|
||||
# TODO: choose this in workflow
|
||||
@ -74,7 +72,7 @@ def motion_to_pdf(pdf, motion):
|
||||
% _("Supporters"), stylesheet['Heading4']))
|
||||
supporters = motion.supporter.all()
|
||||
for supporter in supporters:
|
||||
cell3b.append(Paragraph("<seq id='counter'/>. %s" % unicode(supporter),
|
||||
cell3b.append(Paragraph("<seq id='counter'/>. %s" % str(supporter),
|
||||
stylesheet['Normal']))
|
||||
cell3b.append(Spacer(0, 0.2 * cm))
|
||||
motion_data.append([cell3a, cell3b])
|
||||
@ -200,7 +198,7 @@ def convert_html_to_reportlab(pdf, text):
|
||||
text = soup.body.contents
|
||||
paragraph_number = 1
|
||||
for paragraph in text:
|
||||
paragraph = unicode(paragraph)
|
||||
paragraph = str(paragraph)
|
||||
# ignore empty paragraphs (created by newlines/tabs of ckeditor)
|
||||
if paragraph == '\n' or paragraph == '\n\n' or paragraph == '\n\t':
|
||||
continue
|
||||
@ -271,11 +269,11 @@ def motion_poll_to_pdf(pdf, poll):
|
||||
cell.append(Paragraph(_("%d. Vote") % poll.poll_number, stylesheet['Ballot_description']))
|
||||
cell.append(Spacer(0, 0.5 * cm))
|
||||
cell.append(Paragraph("<font name='circlefont' size='15'>%s</font> <font name='Ubuntu'>%s</font>"
|
||||
% (circle, unicode(_("Yes"))), stylesheet['Ballot_option']))
|
||||
% (circle, _("Yes")), stylesheet['Ballot_option']))
|
||||
cell.append(Paragraph("<font name='circlefont' size='15'>%s</font> <font name='Ubuntu'>%s</font>"
|
||||
% (circle, unicode(_("No"))), stylesheet['Ballot_option']))
|
||||
% (circle, _("No")), stylesheet['Ballot_option']))
|
||||
cell.append(Paragraph("<font name='circlefont' size='15'>%s</font> <font name='Ubuntu'>%s</font>"
|
||||
% (circle, unicode(_("Abstention"))), stylesheet['Ballot_option']))
|
||||
% (circle, _("Abstention")), stylesheet['Ballot_option']))
|
||||
data = []
|
||||
# get ballot papers config values
|
||||
ballot_papers_selection = config["motion_pdf_ballot_papers_selection"]
|
||||
@ -299,7 +297,7 @@ def motion_poll_to_pdf(pdf, poll):
|
||||
# print ballot papers
|
||||
if number > 0:
|
||||
# TODO: try [cell, cell] * (number / 2)
|
||||
for user in xrange(number / 2):
|
||||
for user in range(number / 2):
|
||||
data.append([cell, cell])
|
||||
rest = number % 2
|
||||
if rest:
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.config.api import config
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from haystack import indexes
|
||||
from .models import Motion
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openslides.projector.api import register_slide_model
|
||||
|
||||
from .models import Motion, MotionPoll
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
# TODO: define the Views inhere
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
@ -121,7 +119,7 @@ class MotionEditMixin(object):
|
||||
active_slide = get_active_slide()
|
||||
active_slide_pk = active_slide.get('pk', None)
|
||||
if (active_slide['callback'] == 'motion' and
|
||||
unicode(self.object.pk) == unicode(active_slide_pk)):
|
||||
str(self.object.pk) == str(active_slide_pk)):
|
||||
update_projector()
|
||||
|
||||
messages.success(self.request, self.get_success_message())
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.widgets import Widget
|
||||
|
@ -1,3 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import main_menu, signals, slides, widgets # noqa
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from random import choice
|
||||
|
||||
from .models import Group, User
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import csv
|
||||
|
||||
from django.db import transaction
|
||||
@ -21,12 +19,12 @@ def import_users(csvfile):
|
||||
csvfile.seek(0)
|
||||
|
||||
with transaction.commit_on_success():
|
||||
dialect = csv.Sniffer().sniff(csvfile.readline())
|
||||
dialect = csv.Sniffer().sniff(csvfile.readline().decode('utf-8'))
|
||||
dialect = csv_ext.patchup(dialect)
|
||||
csvfile.seek(0)
|
||||
|
||||
for (line_no, line) in enumerate(csv.reader(csvfile,
|
||||
dialect=dialect)):
|
||||
for (line_no, line) in enumerate(csv.reader(
|
||||
(line.decode('utf8') for line in csvfile.readlines()), dialect=dialect)):
|
||||
if line_no:
|
||||
try:
|
||||
(title, first_name, last_name, gender, email, groups,
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import Permission
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from openslides.utils.main_menu import MainMenuEntry
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.contrib.auth.middleware import AuthenticationMiddleware as _AuthenticationMiddleware
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.contrib.auth.models import Group as DjangoGroup
|
||||
from django.contrib.auth.models import User as DjangoUser
|
||||
from django.contrib.auth.models import Permission
|
||||
@ -56,7 +54,7 @@ class User(SlideMixin, PersonMixin, Person, AbsoluteUrlMixin, DjangoUser):
|
||||
)
|
||||
ordering = ('last_name',)
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
if self.name_suffix:
|
||||
return u"%s (%s)" % (self.clean_name, self.name_suffix)
|
||||
return u"%s" % self.clean_name
|
||||
@ -125,8 +123,8 @@ class Group(SlideMixin, PersonMixin, Person, AbsoluteUrlMixin, DjangoGroup):
|
||||
class Meta:
|
||||
ordering = ('name',)
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.name)
|
||||
def __str__(self):
|
||||
return str(self.name)
|
||||
|
||||
def get_absolute_url(self, link='detail'):
|
||||
"""
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from reportlab.graphics.barcode.qr import QrCodeWidget
|
||||
from reportlab.graphics.shapes import Drawing
|
||||
@ -30,7 +28,7 @@ def participants_to_pdf(pdf):
|
||||
groups = ''
|
||||
for group in user.groups.all():
|
||||
if group.pk != 2:
|
||||
groups += "%s<br/>" % unicode(_(group.name))
|
||||
groups += "%s<br/>" % _(group.name)
|
||||
data.append([
|
||||
counter,
|
||||
Paragraph(user.title, stylesheet['Tablecell']),
|
||||
@ -82,7 +80,7 @@ def participants_passwords_to_pdf(pdf):
|
||||
qrcode_wlan_draw.add(qrcode_wlan)
|
||||
|
||||
for user in User.objects.all().order_by(sort):
|
||||
pdf.append(Paragraph(unicode(user), stylesheet['h1']))
|
||||
pdf.append(Paragraph(user, stylesheet['h1']))
|
||||
pdf.append(Spacer(0, 1 * cm))
|
||||
data = []
|
||||
# WLAN access data
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from haystack import indexes
|
||||
from .models import User
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openslides.projector.api import register_slide_model
|
||||
|
||||
from .models import Group, User
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from . import views
|
||||
|
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.forms import PasswordChangeForm
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user