├── .gitignore ├── AUTHORS ├── CHANGELOG ├── INSTALL ├── LICENSE ├── MANIFEST.in ├── README ├── docs ├── Makefile ├── backend-api.rst ├── conf.py ├── default-backend.rst ├── faq.rst ├── forms.rst ├── index.rst ├── make.bat ├── quickstart.rst ├── release-notes.rst ├── signals.rst ├── simple-backend.rst ├── upgrade.rst └── views.rst ├── registration ├── __init__.py ├── admin.py ├── auth_urls.py ├── backends │ ├── __init__.py │ ├── default │ │ ├── __init__.py │ │ └── urls.py │ └── simple │ │ ├── __init__.py │ │ └── urls.py ├── forms.py ├── locale │ ├── ar │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── bg │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── da │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── de │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── el │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── en │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── es │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── es_AR │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── fr │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── he │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── is │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── it │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ja │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ko │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── nl │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── pl │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── pt_BR │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── ru │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── sl │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── sr │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── sv │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ ├── zh_CN │ │ └── LC_MESSAGES │ │ │ ├── django.mo │ │ │ └── django.po │ └── zh_TW │ │ └── LC_MESSAGES │ │ ├── django.mo │ │ └── django.po ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── cleanupregistration.py ├── models.py ├── signals.py ├── templates │ ├── base.html │ └── registration │ │ ├── activate.html │ │ ├── activation_complete.html │ │ ├── activation_email.txt │ │ ├── activation_email_subject.txt │ │ ├── base_registration.html │ │ ├── login.html │ │ ├── logout.html │ │ ├── registration_closed.html │ │ ├── registration_complete.html │ │ └── registration_form.html ├── tests │ ├── __init__.py │ ├── backends.py │ ├── forms.py │ ├── models.py │ ├── urls.py │ └── views.py ├── urls.py └── views.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | docs/_build 4 | .hg* 5 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | The primary author of django-registration is James Bennett 2 | , who may be found online at 3 | . 4 | 5 | 6 | Others who have contributed to the application: 7 | 8 | * Samuel Adam (French translation) 9 | * Jannis Leidel (German translation) 10 | * Rapahel Hertzog (helpful suggestions on packaging and distribution) 11 | * Panos Laganakos (Greek translation) 12 | * Ilya Filippov and Andy Mikhailenko (Russian translation) 13 | * Jarek Zgoda (Polish translation) 14 | * Meir Kriheli (Hebrew translation) 15 | * Italo Maia (Brazilian Portuguese translation) 16 | * Shinya Okano (Japanese translation) 17 | * A. Al-Ibrahim (Arabic translation) 18 | * Ernesto Rico Schmidt (Spanish translation) 19 | * Vladislav Mitov (Bulgarian translation) 20 | * Leonardo Manuel Rocha (Argentinean Spanish translation) 21 | * Emil Stenström (Swedish translation) 22 | * Liang Feng (Chinese translations) 23 | * Nebojsa Djordjevic (Serbian translation) 24 | * Nicola Larosa (Italian translation) 25 | * Joost Cassee (Dutch translation) 26 | * Björn Kristinsson (Icelandic translation) 27 | * Rune Bromer (Danish translation) 28 | * Domen Kožar (Slovenian translation) 29 | * Young Gyu Park (Korean translation) 30 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | ============================= 2 | django-registration changelog 3 | ============================= 4 | 5 | 6 | Version 0.7, 6 November 2008: 7 | ----------------------------- 8 | 9 | * Project hosting moved from Google Code to Bitbucket, and from a 10 | Subversion repository to Mercurial. 11 | 12 | * Added test suite. 13 | 14 | * Full Django 1.0 compatibility. 15 | 16 | * Registration and activation views now accept an ``extra_context`` 17 | argument, identical to the way that argument works in Django's 18 | generic views. 19 | 20 | * Added a custom management command for cleaning up expired 21 | registrations; you can now run ``manage.py cleanupregistration`` to 22 | handle this. 23 | 24 | * BACKWARDS-INCOMPATIBLE CHANGE: The "username" field in 25 | ``RegistrationForm`` is now a ``RegexField``. 26 | 27 | * BACKWARDS-INCOMPATIBLE CHANGE: Removed the standalone script for 28 | deleting expired user registrations; use the new management command 29 | instead. 30 | 31 | 32 | Version 0.6, 29 July 2008: 33 | -------------------------- 34 | 35 | * Packaged from revision 166 in Subversion. 36 | 37 | * Fixed a multiple-objects exception in 38 | ``RegistrationFormUniqueEmail`` when multiple users already have the 39 | same email address. 40 | 41 | * Changed the ``success_url`` of the ``register()`` view to use 42 | reverse URL resolution. 43 | 44 | * Added an ``extra_context`` argument to the ``register`` and 45 | ``activate`` views, mimicking its functionality in Django's generic 46 | views. 47 | 48 | * BACKWARDS-INCOMPATIBLE CHANGE: Switched the admin declaration to be 49 | compliant with the newforms-admin refactor; the admin declaration 50 | now lives in ``registration/admin.py``. 51 | 52 | * BACKWARDS-INCOMPATIBLE CHANGE: Switched form imports from using 53 | ``django.newforms`` to using ``django.forms``; the old style now 54 | raises a deprecation warning on Django trunk and on Django 1.0 55 | alpha. 56 | 57 | 58 | Version 0.5, 4 June 2008: 59 | ------------------------- 60 | 61 | * Packaged from revision 155 in Subversion. 62 | 63 | * Added Serbian translation. 64 | 65 | * Added Italian translation. 66 | 67 | * Username/email uniqueness checks are now case-insensitive. This is 68 | potentially backwards-incompatible if you relied on them being 69 | case-sensitive, but I don't know of any reason why you'd be doing 70 | that. 71 | 72 | * Included forms now use lazy translations. 73 | 74 | * The ``register`` view can now handle files submitted for use in form 75 | processing. 76 | 77 | * Reactivation of a manually-deactivated account is now prevented by 78 | changing the activation key, on successful activation, to a dummy 79 | string which will fail on subsequent activation attempts. 80 | 81 | 82 | Version 0.4p2, 10 Feburary 2008: 83 | -------------------------------- 84 | 85 | * Added Brazilian Portuguese translation. 86 | 87 | * Added Japanese translation. 88 | 89 | * Added Hebrew translation. 90 | 91 | * Minor documentation fixes. 92 | 93 | 94 | Version 0.4p1, 16 December 2007: 95 | -------------------------------- 96 | 97 | * Packaged from revision 129 in Subversion. 98 | 99 | * Added Polish translation. 100 | 101 | 102 | Version 0.4, 8 December 2007: 103 | ----------------------------- 104 | 105 | * Packaged from revision 122 in Subversion. 106 | 107 | * Added Greek translation. 108 | 109 | * Added Russian translation. 110 | 111 | * Changed ``maxlength`` to ``max_length`` now that Django issues a 112 | deprecation warning for it. 113 | 114 | * BACKWARDS-INCOMPATIBLE CHANGE: Changed the password validation to be 115 | on ``clean()`` instead of ``clean_password2()``. This means that 116 | errors from this must be accessed via ``non_field_errors()``. 117 | 118 | 119 | Version 0.3p5, 6 October 2007: 120 | ------------------------------ 121 | 122 | * Packaged from revision 112 in Subversion. 123 | 124 | * Added German translation. 125 | 126 | * Fixed a mismatch between the default ``RegistrationForm``'s maximum 127 | length on email addresses and the actual maximum length on Django's 128 | ``User`` model. 129 | 130 | * Fixed a situation where bad input for the ``password1`` field on 131 | ``RegistrationForm`` could cause validation of ``password2`` to fail 132 | with an exception. 133 | 134 | 135 | Version 0.3p4, 4 October 2007: 136 | ------------------------------ 137 | 138 | * Packaged from revision 101 in Subversion. 139 | 140 | * BACKWARDS-INCOMPATIBLE CHANGE: In response to larger numbers of 141 | complaints from people trying to use the example templates as-is, 142 | the example templates have been removed. 143 | 144 | 145 | Version 0.3p2, 23 September 2007: 146 | --------------------------------- 147 | 148 | * Packaged from revision 100 in Subversion. 149 | 150 | * Fixed ``activate`` view to actually take the ``template_name`` 151 | argument. 152 | 153 | 154 | Version 0.3p1, 22 September 2007: 155 | --------------------------------- 156 | 157 | * Packaged from revision 99 in Subversion. 158 | 159 | * Fixed a typo in docs/overview.txt. 160 | 161 | * Fixed a typo in bin/delete_expired_users.py. 162 | 163 | * Added French translation. 164 | 165 | 166 | Version 0.3, 19 September 2007: 167 | ------------------------------- 168 | 169 | Packaged from revision 89 in Subversion; download at 170 | http://django-registration.googlecode.com/files/registration-0.3.tar.gz 171 | 172 | * Changed ``register`` and ``activate`` views to accept 173 | ``template_name`` keyword argument for selecting a custom template. 174 | 175 | * Changed ``register`` view to accept ``form_class`` keyword 176 | argument specifying the form to use. 177 | 178 | * BACKWARDS-INCOMPATIBLE CHANGE: Changed 179 | ``RegistrationManager.create_inactive_user`` to use a template for 180 | the subject of the activation email. 181 | 182 | * BACKWARDS-INCOMPATIBLE CHANGE: Removed the ``tos`` field from 183 | ``RegistrationForm``; if you were relying on it, switch to using 184 | ``RegistrationFormTermsOfService`` instead. 185 | 186 | * BACKWARDS-INCOMPATIBLE CHANGE: The activation email template now 187 | receives the current ``Site`` object as the context variable 188 | ``site``, and the ``current_site`` variable, which only held the 189 | domain, is no longer available. 190 | 191 | * Added script ``bin/delete_expired_users.py`` with instructions on 192 | how to use it as a cron job to clean up expired/inactive accounts. 193 | 194 | * Marked strings for translation and added ``locale`` directory so 195 | that translations can be added. 196 | 197 | * Updated to deal with merge of Django's Unicode branch into trunk; 198 | now using Unicode-aware functions everywhere. 199 | 200 | 201 | Version 0.2, 29 May 2007: 202 | ------------------------- 203 | 204 | Packaged from revision 76 in Subversion; download at 205 | http://django-registration.googlecode.com/files/registration-0.2.tar.gz 206 | 207 | * Added ability to specify a callback in 208 | ``RegistrationManager.create_inactive_user`` or in the ``register`` 209 | view to enable creation of site-specific user profile. 210 | 211 | * Separated out the logic of creating the profile into a new method on 212 | ``RegistrationManager``: ``create_profile``. 213 | 214 | * Added URLConf support for various useful views in 215 | ``django.contrib.auth``. 216 | 217 | * BACKWARDS-INCOMPATIBLE CHANGE: removed the ``key_generated`` field 218 | from ``RegistrationProfile``; activation key expiration is now 219 | calculated based on the ``date_joined`` field in the ``User`` model. 220 | Drop the ``key_generated`` column from your database when upgrading 221 | from 0.1. 222 | 223 | 224 | Version 0.1, 23 May 2007: 225 | ------------------------- 226 | 227 | Packaged from revision 56 in Subversion; download at 228 | http://django-registration.googlecode.com/files/registration-0.1.tar.gz 229 | 230 | * First packaged version using distutils. 231 | 232 | * Added docs/ directory and overview. 233 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Thanks for downloading django-registration. 2 | 3 | To install it, run the following command inside this directory: 4 | 5 | python setup.py install 6 | 7 | If you have the Python ``easy_install`` utility available, you can 8 | also type the following to download and install in one step:: 9 | 10 | easy_install -Z django-registration 11 | 12 | (the ``-Z`` flag is required to force ``easy_install`` to do a normal 13 | source install rather than a zipped egg; django-registration cannot be 14 | used from a zipped egg install) 15 | 16 | Or if you're using ``pip``:: 17 | 18 | pip install django-registration 19 | 20 | Or if you'd prefer you can simply place the included ``registration`` 21 | directory somewhere on your Python path, or symlink to it from 22 | somewhere on your Python path; this is useful if you're working from a 23 | Mercurial checkout. 24 | 25 | Note that this application requires Python 2.3 or later, and a 26 | functional installation of Django 1.` or newer. You can obtain Python 27 | from http://www.python.org/ and Django from 28 | http://www.djangoproject.com/. 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007-2010, James Bennett 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following 12 | disclaimer in the documentation and/or other materials provided 13 | with the distribution. 14 | * Neither the name of the author nor the names of other 15 | contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CHANGELOG 2 | include INSTALL 3 | include LICENSE 4 | include MANIFEST.in 5 | include README 6 | include AUTHORS 7 | recursive-include docs * 8 | recursive-include registration/locale * 9 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ======================== 2 | Django user registration 3 | ======================== 4 | 5 | This is a fairly simple user-registration application for Django_, 6 | designed to make allowing user signups as painless as possible. It 7 | requires a functional installation of Django 1.1 or newer, but has no 8 | other dependencies. 9 | 10 | For installation instructions, see the file "INSTALL" in this 11 | directory; for instructions on how to use this application, and on 12 | what it provides, see the file "quickstart.rst" in the "docs/" 13 | directory. -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | 9 | # Internal variables. 10 | PAPEROPT_a4 = -D latex_paper_size=a4 11 | PAPEROPT_letter = -D latex_paper_size=letter 12 | ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 13 | 14 | .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest 15 | 16 | help: 17 | @echo "Please use \`make ' where is one of" 18 | @echo " html to make standalone HTML files" 19 | @echo " dirhtml to make HTML files named index.html in directories" 20 | @echo " pickle to make pickle files" 21 | @echo " json to make JSON files" 22 | @echo " htmlhelp to make HTML files and a HTML help project" 23 | @echo " qthelp to make HTML files and a qthelp project" 24 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 25 | @echo " changes to make an overview of all changed/added/deprecated items" 26 | @echo " linkcheck to check all external links for integrity" 27 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 28 | 29 | clean: 30 | -rm -rf _build/* 31 | 32 | html: 33 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html 34 | @echo 35 | @echo "Build finished. The HTML pages are in _build/html." 36 | 37 | dirhtml: 38 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml 39 | @echo 40 | @echo "Build finished. The HTML pages are in _build/dirhtml." 41 | 42 | pickle: 43 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle 44 | @echo 45 | @echo "Build finished; now you can process the pickle files." 46 | 47 | json: 48 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json 49 | @echo 50 | @echo "Build finished; now you can process the JSON files." 51 | 52 | htmlhelp: 53 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp 54 | @echo 55 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 56 | ".hhp project file in _build/htmlhelp." 57 | 58 | qthelp: 59 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp 60 | @echo 61 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 62 | ".qhcp project file in _build/qthelp, like this:" 63 | @echo "# qcollectiongenerator _build/qthelp/django-registration.qhcp" 64 | @echo "To view the help file:" 65 | @echo "# assistant -collectionFile _build/qthelp/django-registration.qhc" 66 | 67 | latex: 68 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex 69 | @echo 70 | @echo "Build finished; the LaTeX files are in _build/latex." 71 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 72 | "run these through (pdf)latex." 73 | 74 | changes: 75 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes 76 | @echo 77 | @echo "The overview file is in _build/changes." 78 | 79 | linkcheck: 80 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck 81 | @echo 82 | @echo "Link check complete; look for any errors in the above output " \ 83 | "or in _build/linkcheck/output.txt." 84 | 85 | doctest: 86 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest 87 | @echo "Testing of doctests in the sources finished, look at the " \ 88 | "results in _build/doctest/output.txt." 89 | -------------------------------------------------------------------------------- /docs/backend-api.rst: -------------------------------------------------------------------------------- 1 | .. _backend-api: 2 | 3 | User registration backends 4 | ========================== 5 | 6 | At its core, django-registration is built around the idea of pluggable 7 | backends which can implement different workflows for user 8 | registration. Although :ref:`the default backend ` 9 | uses a common two-phase system (registration followed by activation), 10 | backends are generally free to implement any workflow desired by their 11 | authors. 12 | 13 | This is deliberately meant to be complementary to Django's own 14 | `pluggable authentication backends 15 | `_; 16 | a site which uses an OpenID authentication backend, for example, can 17 | and should make use of a registration backend which handles signups 18 | via OpenID. And, like a Django authentication backend, a registration 19 | backend is simply a class which implements a particular standard API 20 | (described below). 21 | 22 | This allows for a great deal of flexibility in the actual workflow of 23 | registration; backends can, for example, implement any of the 24 | following (not an exhaustive list): 25 | 26 | * One-step (register, and done) or multi-step (register and activate) 27 | signup. 28 | 29 | * Invitation-based registration. 30 | 31 | * Selectively allowing or disallowing registration (e.g., by requiring 32 | particular credentials to register). 33 | 34 | * Enabling/disabling registration entirely. 35 | 36 | * Registering via sources other than a standard username/password, 37 | such as OpenID. 38 | 39 | * Selective customization of the registration process (e.g., using 40 | different forms or imposing different requirements for different 41 | types of users). 42 | 43 | 44 | Specifying the backend to use 45 | ----------------------------- 46 | 47 | To determine which backend to use, the :ref:`views in 48 | django-registration ` accept a keyword argument ``backend``; in 49 | all cases, this should be a string containing the full dotted Python 50 | import path to the backend class to be used. So, for example, to use 51 | the default backend, you'd pass the string 52 | ``'registration.backends.default.DefaultBackend'`` as the value of the 53 | ``backend`` argument (and the default URLconf included with that 54 | backend does so). The specified backend class will then be imported 55 | and instantiated (by calling its constructor with no arguments), and 56 | the resulting instance will be used for all backend-specific 57 | functionality. 58 | 59 | If the specified backend class cannot be imported, django-registration 60 | will raise ``django.core.exceptions.ImproperlyConfigured``. 61 | 62 | 63 | Backend API 64 | ----------- 65 | 66 | To be used as a registration backend, a class must implement the 67 | following methods. For many cases, subclassing the default backend and 68 | selectively overriding behavior will be suitable, but for other 69 | situations (e.g., workflows significantly different from the default) 70 | a full implementation is needed. 71 | 72 | 73 | register(request, \*\*kwargs) 74 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 75 | 76 | This method implements the logic of actually creating the new user 77 | account. Often, but not necessarily always, this will involve creating 78 | an instance of ``django.contrib.auth.models.User`` from the supplied 79 | data. 80 | 81 | This method will only be called after a signup form has been 82 | displayed, and the data collected by the form has been properly 83 | validated. 84 | 85 | Arguments to this method are: 86 | 87 | ``request`` 88 | The Django `HttpRequest 89 | `_ 90 | object in which a new user is attempting to register. 91 | 92 | ``**kwargs`` 93 | A dictionary of the ``cleaned_data`` from the signup form. 94 | 95 | After creating the new user account, this method should create or 96 | obtain an instance of ``django.contrib.auth.models.User`` representing 97 | that account. It should then send the signal 98 | :data:`registration.signals.user_registered`, with three arguments: 99 | 100 | ``sender`` 101 | The backend class (e.g., ``self.__class__``). 102 | 103 | ``user`` 104 | The ``User`` instance representing the new account. 105 | 106 | ``request`` 107 | The ``HttpRequest`` in which the user registered. 108 | 109 | Finally, this method should return the ``User`` instance. 110 | 111 | 112 | activate(request, \*\*kwargs) 113 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 114 | 115 | For workflows which require a separate activation step, this method 116 | should implement the necessary logic for account activation. 117 | 118 | Arguments to this method are: 119 | 120 | ``request`` 121 | The Django ``HttpRequest`` object in which the account is being 122 | activated. 123 | 124 | ``**kwargs`` 125 | A dictionary of any additional arguments (e.g., information 126 | captured from the URL, such as an activation key) received by the 127 | :func:`~registration.views.activate` view. The combination of the 128 | ``HttpRequest`` and this additional information must be sufficient 129 | to identify the account which will be activated. 130 | 131 | If the account cannot be successfully activated (for example, in the 132 | default backend if the activation period has expired), this method 133 | should return ``False``. 134 | 135 | If the account is successfully activated, this method should create or 136 | obtain an instance of ``django.contrib.auth.models.User`` representing 137 | the activated account. It should then send the signal 138 | :data:`registration.signals.user_activated`, with three arguments: 139 | 140 | ``sender`` 141 | The backend class. 142 | 143 | ``user`` 144 | The ``User`` instance representing the activated account. 145 | 146 | ``request`` 147 | The ``HttpRequest`` in which the user activated. 148 | 149 | This method should then return the ``User`` instance. 150 | 151 | For workflows which do not require a separate activation step, this 152 | method can and should raise ``NotImplementedError``. 153 | 154 | 155 | registration_allowed(request) 156 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 157 | 158 | This method returns a boolean value indicating whether the given 159 | ``HttpRequest`` is permitted to register a new account (``True`` if 160 | registration is permitted, ``False`` otherwise). It may determine this 161 | based on some aspect of the ``HttpRequest`` (e.g., the presence or 162 | absence of an invitation code in the URL), based on a setting (in the 163 | default backend, a setting can be used to disable registration), 164 | information in the database or any other information it can access. 165 | 166 | Arguments to this method are: 167 | 168 | ``request`` 169 | The Django ``HttpRequest`` object in which a new user is 170 | attempting to register. 171 | 172 | If this method returns ``False``, the 173 | :func:`~registration.views.register` view will not display a form for 174 | account creation; instead, it will issue a redirect to a URL 175 | explaining that registration is not permitted. 176 | 177 | 178 | get_form_class(request) 179 | ~~~~~~~~~~~~~~~~~~~~~~~ 180 | 181 | This method should return a form class -- a subclass of 182 | ``django.forms.Form`` -- suitable for use in registering users with 183 | this backend. As such, it should collect and validate any information 184 | required by the backend's ``register`` method. 185 | 186 | Arguments to this method are: 187 | 188 | ``request`` 189 | The Django ``HttpRequest`` object in which a new user is 190 | attempting to register. 191 | 192 | 193 | post_registration_redirect(request, user) 194 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 195 | 196 | This method should return a location to which the user will be 197 | redirected after successful registration. This should be a tuple of 198 | ``(to, args, kwargs)``, suitable for use as the arguments to `Django's 199 | "redirect" shortcut 200 | `_. 201 | 202 | Arguments to this method are: 203 | 204 | ``request`` 205 | The Django ``HttpRequest`` object in which the user registered. 206 | 207 | ``user`` 208 | The ``User`` instance representing the new user account. 209 | 210 | 211 | post_activation_redirect(request, user) 212 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 213 | 214 | For workflows which require a separate activation step, this method 215 | should return a location to which the user will be redirected after 216 | successful activation. This should be a tuple of ``(to, args, 217 | kwargs)``, suitable for use as the arguments to `Django's "redirect" 218 | shortcut 219 | `_. 220 | 221 | Arguments to this method are: 222 | 223 | ``request`` 224 | The Django ``HttpRequest`` object in which the user activated. 225 | 226 | ``user`` 227 | The ``User`` instance representing the activated user account. 228 | 229 | For workflows which do not require a separate activation step, this 230 | method can and should raise ``NotImplementedError``. 231 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # django-registration documentation build configuration file, created by 4 | # sphinx-quickstart on Mon Jun 22 02:57:42 2009. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.append(os.path.abspath('.')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # Add any Sphinx extension module names here, as strings. They can be extensions 24 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 25 | extensions = [] 26 | 27 | # Add any paths that contain templates here, relative to this directory. 28 | templates_path = ['_templates'] 29 | 30 | # The suffix of source filenames. 31 | source_suffix = '.rst' 32 | 33 | # The encoding of source files. 34 | #source_encoding = 'utf-8' 35 | 36 | # The master toctree document. 37 | master_doc = 'index' 38 | 39 | # General information about the project. 40 | project = u'django-registration' 41 | copyright = u'2009, James Bennett' 42 | 43 | # The version info for the project you're documenting, acts as replacement for 44 | # |version| and |release|, also used in various other places throughout the 45 | # built documents. 46 | # 47 | # The short X.Y version. 48 | version = '0.8' 49 | # The full version, including alpha/beta/rc tags. 50 | release = '0.8' 51 | 52 | # The language for content autogenerated by Sphinx. Refer to documentation 53 | # for a list of supported languages. 54 | #language = None 55 | 56 | # There are two options for replacing |today|: either, you set today to some 57 | # non-false value, then it is used: 58 | #today = '' 59 | # Else, today_fmt is used as the format for a strftime call. 60 | #today_fmt = '%B %d, %Y' 61 | 62 | # List of documents that shouldn't be included in the build. 63 | #unused_docs = [] 64 | 65 | # List of directories, relative to source directory, that shouldn't be searched 66 | # for source files. 67 | exclude_trees = ['_build'] 68 | 69 | # The reST default role (used for this markup: `text`) to use for all documents. 70 | #default_role = None 71 | 72 | # If true, '()' will be appended to :func: etc. cross-reference text. 73 | #add_function_parentheses = True 74 | 75 | # If true, the current module name will be prepended to all description 76 | # unit titles (such as .. function::). 77 | #add_module_names = True 78 | 79 | # If true, sectionauthor and moduleauthor directives will be shown in the 80 | # output. They are ignored by default. 81 | #show_authors = False 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | pygments_style = 'sphinx' 85 | 86 | # A list of ignored prefixes for module index sorting. 87 | #modindex_common_prefix = [] 88 | 89 | 90 | # -- Options for HTML output --------------------------------------------------- 91 | 92 | # The theme to use for HTML and HTML Help pages. Major themes that come with 93 | # Sphinx are currently 'default' and 'sphinxdoc'. 94 | html_theme = 'default' 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | #html_theme_options = {} 100 | 101 | # Add any paths that contain custom themes here, relative to this directory. 102 | #html_theme_path = [] 103 | 104 | # The name for this set of Sphinx documents. If None, it defaults to 105 | # " v documentation". 106 | #html_title = None 107 | 108 | # A shorter title for the navigation bar. Default is the same as html_title. 109 | #html_short_title = None 110 | 111 | # The name of an image file (relative to this directory) to place at the top 112 | # of the sidebar. 113 | #html_logo = None 114 | 115 | # The name of an image file (within the static path) to use as favicon of the 116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 117 | # pixels large. 118 | #html_favicon = None 119 | 120 | # Add any paths that contain custom static files (such as style sheets) here, 121 | # relative to this directory. They are copied after the builtin static files, 122 | # so a file named "default.css" will overwrite the builtin "default.css". 123 | html_static_path = ['_static'] 124 | 125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 126 | # using the given strftime format. 127 | #html_last_updated_fmt = '%b %d, %Y' 128 | 129 | # If true, SmartyPants will be used to convert quotes and dashes to 130 | # typographically correct entities. 131 | #html_use_smartypants = True 132 | 133 | # Custom sidebar templates, maps document names to template names. 134 | #html_sidebars = {} 135 | 136 | # Additional templates that should be rendered to pages, maps page names to 137 | # template names. 138 | #html_additional_pages = {} 139 | 140 | # If false, no module index is generated. 141 | #html_use_modindex = True 142 | 143 | # If false, no index is generated. 144 | #html_use_index = True 145 | 146 | # If true, the index is split into individual pages for each letter. 147 | #html_split_index = False 148 | 149 | # If true, links to the reST sources are added to the pages. 150 | #html_show_sourcelink = True 151 | 152 | # If true, an OpenSearch description file will be output, and all pages will 153 | # contain a tag referring to it. The value of this option must be the 154 | # base URL from which the finished HTML is served. 155 | #html_use_opensearch = '' 156 | 157 | # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). 158 | #html_file_suffix = '' 159 | 160 | # Output file base name for HTML help builder. 161 | htmlhelp_basename = 'django-registrationdoc' 162 | 163 | 164 | # -- Options for LaTeX output -------------------------------------------------- 165 | 166 | # The paper size ('letter' or 'a4'). 167 | #latex_paper_size = 'letter' 168 | 169 | # The font size ('10pt', '11pt' or '12pt'). 170 | #latex_font_size = '10pt' 171 | 172 | # Grouping the document tree into LaTeX files. List of tuples 173 | # (source start file, target name, title, author, documentclass [howto/manual]). 174 | latex_documents = [ 175 | ('index', 'django-registration.tex', u'django-registration Documentation', 176 | u'James Bennett', 'manual'), 177 | ] 178 | 179 | # The name of an image file (relative to this directory) to place at the top of 180 | # the title page. 181 | #latex_logo = None 182 | 183 | # For "manual" documents, if this is true, then toplevel headings are parts, 184 | # not chapters. 185 | #latex_use_parts = False 186 | 187 | # Additional stuff for the LaTeX preamble. 188 | #latex_preamble = '' 189 | 190 | # Documents to append as an appendix to all manuals. 191 | #latex_appendices = [] 192 | 193 | # If false, no module index is generated. 194 | #latex_use_modindex = True 195 | -------------------------------------------------------------------------------- /docs/default-backend.rst: -------------------------------------------------------------------------------- 1 | .. _default-backend: 2 | .. module:: registration.backends.default 3 | 4 | The default backend 5 | =================== 6 | 7 | A default :ref:`registration backend ` is bundled with 8 | django-registration, as the class 9 | ``registration.backends.default.DefaultBackend``, and implements a 10 | simple two-step workflow in which a new user first registers, then 11 | confirms and activates the new account by following a link sent to the 12 | email address supplied during registration. 13 | 14 | 15 | Default behavior and configuration 16 | ---------------------------------- 17 | 18 | This backend makes use of the following settings: 19 | 20 | ``ACCOUNT_ACTIVATION_DAYS`` 21 | This is the number of days users will have to activate their 22 | accounts after registering. Failing to activate during that period 23 | will leave the account inactive (and possibly subject to 24 | deletion). This setting is required, and must be an integer. 25 | 26 | ``REGISTRATION_OPEN`` 27 | A boolean (either ``True`` or ``False``) indicating whether 28 | registration of new accounts is currently permitted. This setting 29 | is optional, and a default of ``True`` will be assumed if it is 30 | not supplied. 31 | 32 | By default, this backend uses 33 | :class:`registration.forms.RegistrationForm` as its form class for 34 | user registration; this can be overridden by passing the keyword 35 | argument ``form_class`` to the :func:`~registration.views.register` 36 | view. 37 | 38 | Upon successful registration -- not activation -- the default redirect 39 | is to the URL pattern named ``registration_complete``; this can be 40 | overridden by passing the keyword argument ``success_url`` to the 41 | :func:`~registration.views.register` view. 42 | 43 | Upon successful activation, the default redirect is to the URL pattern 44 | named ``registration_activation_complete``; this can be overridden by 45 | passing the keyword argument ``success_url`` to the 46 | :func:`~registration.views.activate` view. 47 | 48 | 49 | How account data is stored for activation 50 | ----------------------------------------- 51 | 52 | During registration, a new instance of 53 | ``django.contrib.auth.models.User`` is created to represent the new 54 | account, with the ``is_active`` field set to ``False``. An email is 55 | then sent to the email address of the account, containing a link the 56 | user must click to activate the account; at that point the 57 | ``is_active`` field is set to ``True``, and the user may log in 58 | normally. 59 | 60 | Activation is handled by generating and storing an activation key in 61 | the database, using the following model: 62 | 63 | 64 | .. currentmodule:: registration.models 65 | 66 | .. class:: RegistrationProfile 67 | 68 | A simple representation of the information needed to activate a new 69 | user account. This is **not** a user profile; it simply provides a 70 | place to temporarily store the activation key and determine whether 71 | a given account has been activated. 72 | 73 | Has the following fields: 74 | 75 | .. attribute:: user 76 | 77 | A ``ForeignKey`` to ``django.contrib.auth.models.User``, 78 | representing the user account for which activation information 79 | is being stored. 80 | 81 | .. attribute:: activation_key 82 | 83 | A 40-character ``CharField``, storing the activation key for the 84 | account. Initially, the activation key is the hexdigest of a 85 | SHA1 hash; after activation, this is reset to :attr:`ACTIVATED`. 86 | 87 | Additionally, one class attribute exists: 88 | 89 | .. attribute:: ACTIVATED 90 | 91 | A constant string used as the value of :attr:`activation_key` 92 | for accounts which have been activated. 93 | 94 | And the following methods: 95 | 96 | .. method:: activation_key_expired() 97 | 98 | Determines whether this account's activation key has expired, 99 | and returns a boolean (``True`` if expired, ``False`` 100 | otherwise). Uses the following algorithm: 101 | 102 | 1. If :attr:`activation_key` is :attr:`ACTIVATED`, the account 103 | has already been activated and so the key is considered to 104 | have expired. 105 | 106 | 2. Otherwise, the date of registration (obtained from the 107 | ``date_joined`` field of :attr:`user`) is compared to the 108 | current date; if the span between them is greater than the 109 | value of the setting ``ACCOUNT_ACTIVATION_DAYS``, the key is 110 | considered to have expired. 111 | 112 | :rtype: bool 113 | 114 | .. method:: send_activation_email(site) 115 | 116 | Sends an activation email to the address of the account. 117 | 118 | The activation email will make use of two templates: 119 | ``registration/activation_email_subject.txt`` and 120 | ``registration/activation_email.txt``, which are used for the 121 | subject of the email and the body of the email, 122 | respectively. Each will receive the following context: 123 | 124 | ``activation_key`` 125 | The value of :attr:`activation_key`. 126 | 127 | ``expiration_days`` 128 | The number of days the user has to activate, taken from the 129 | setting ``ACCOUNT_ACTIVATION_DAYS``. 130 | 131 | ``site`` 132 | An object representing the site on which the account was 133 | registered; depending on whether ``django.contrib.sites`` is 134 | installed, this may be an instance of either 135 | ``django.contrib.sites.models.Site`` (if the sites 136 | application is installed) or 137 | ``django.contrib.sites.models.RequestSite`` (if 138 | not). Consult `the documentation for the Django sites 139 | framework 140 | `_ 141 | for details regarding these objects' interfaces. 142 | 143 | Because email subjects must be a single line of text, the 144 | rendered output of ``registration/activation_email_subject.txt`` 145 | will be forcibly condensed to a single line. 146 | 147 | :param site: An object representing the site on which account 148 | was registered. 149 | :type site: ``django.contrib.sites.models.Site`` or 150 | ``django.contrib.sites.models.RequestSite`` 151 | :rtype: ``None`` 152 | 153 | 154 | Additionally, :class:`RegistrationProfile` has a custom manager 155 | (accessed as ``RegistrationProfile.objects``): 156 | 157 | 158 | .. class:: RegistrationManager 159 | 160 | This manager provides several convenience methods for creating and 161 | working with instances of :class:`RegistrationProfile`: 162 | 163 | .. method:: activate_user(activation_key) 164 | 165 | Validates ``activation_key`` and, if valid, activates the 166 | associated account by setting its ``is_active`` field to 167 | ``True``. To prevent re-activation of accounts, the 168 | :attr:`~RegistrationProfile.activation_key` of the 169 | :class:`RegistrationProfile` for the account will be set to 170 | :attr:`RegistrationProfile.ACTIVATED` after successful 171 | activation. 172 | 173 | Returns the ``User`` instance representing the account if 174 | activation is successful, ``False`` otherwise. 175 | 176 | :param activation_key: The activation key to use for the 177 | activation. 178 | :type activation_key: string, a 40-character SHA1 hexdigest 179 | :rtype: ``User`` or bool 180 | 181 | .. method:: delete_expired_users 182 | 183 | Removes expired instances of :class:`RegistrationProfile`, and 184 | their associated user accounts, from the database. This is 185 | useful as a periodic maintenance task to clean out accounts 186 | which registered but never activated. 187 | 188 | Accounts to be deleted are identified by searching for instances 189 | of :class:`RegistrationProfile` with expired activation keys and 190 | with associated user accounts which are inactive (have their 191 | ``is_active`` field set to ``False``). To disable a user account 192 | without having it deleted, simply delete its associated 193 | :class:`RegistrationProfile`; any ``User`` which does not have 194 | an associated :class:`RegistrationProfile` will not be deleted. 195 | 196 | A custom management command is provided which will execute this 197 | method, suitable for use in cron jobs or other scheduled 198 | maintenance tasks: ``manage.py cleanupregistration``. 199 | 200 | :rtype: ``None`` 201 | 202 | .. method:: create_inactive_user(username, email, password, site[, send_email]) 203 | 204 | Creates a new, inactive user account and an associated instance 205 | of :class:`RegistrationProfile`, sends the activation email and 206 | returns the new ``User`` object representing the account. 207 | 208 | :param username: The username to use for the new account. 209 | :type username: string 210 | :param email: The email address to use for the new account. 211 | :type email: string 212 | :param password: The password to use for the new account. 213 | :type password: string 214 | :param site: An object representing the site on which the 215 | account is being registered. 216 | :type site: ``django.contrib.sites.models.Site`` or 217 | ``django.contrib.sites.models.RequestSite`` 218 | :param send_email: If ``True``, the activation email will be 219 | sent to the account (by calling 220 | :meth:`RegistrationProfile.send_activation_email`). If 221 | ``False``, no email will be sent (but the account will still 222 | be inactive) 223 | :type send_email: bool 224 | :rtype: ``User`` 225 | 226 | .. method:: create_profile(user) 227 | 228 | Creates and returns a :class:`RegistrationProfile` instance for 229 | the account represented by ``user``. 230 | 231 | The ``RegistrationProfile`` created by this method will have its 232 | :attr:`~RegistrationProfile.activation_key` set to a SHA1 hash 233 | generated from a combination of the account's username and a 234 | random salt. 235 | 236 | :param user: The user account; an instance of 237 | ``django.contrib.auth.models.User``. 238 | :type user: ``User`` 239 | :rtype: ``RegistrationProfile`` 240 | -------------------------------------------------------------------------------- /docs/faq.rst: -------------------------------------------------------------------------------- 1 | .. _faq: 2 | 3 | Frequently-asked questions 4 | ========================== 5 | 6 | The following are miscellaneous common questions and answers related 7 | to installing/using django-registration, culled from bug reports, 8 | emails and other sources. 9 | 10 | 11 | General 12 | ------- 13 | 14 | **What license is django-registration under?** 15 | django-registration is offered under a three-clause BSD-style 16 | license; this is `an OSI-approved open-source license 17 | `_, and allows 18 | you a large degree of freedom in modifiying and redistributing the 19 | code. For the full terms, see the file ``LICENSE`` which came with 20 | your copy of django-registration; if you did not receive a copy of 21 | this file, you can view it online at 22 | . 23 | 24 | **Why are the forms and models for the default backend not in the default backend?** 25 | The model and manager used by :ref:`the default backend 26 | ` are in ``registration.models``, and the default 27 | form class (and various subclasses) are in ``registration.forms``; 28 | logically, they might be expected to exist in 29 | ``registration.backends.default``, but there are several reasons 30 | why that's not such a good idea: 31 | 32 | 1. Older versions of django-registration made use of the model and 33 | form classes, and moving them would create an unnecessary 34 | backwards incompatibility: ``import`` statements would need to 35 | be changed, and some database updates would be needed to 36 | reflect the new location of the 37 | :class:`~registration.models.RegistrationProfile` model. 38 | 39 | 2. Due to the design of Django's ORM, the ``RegistrationProfile`` 40 | model would end up with an ``app_label`` of ``default``, which 41 | isn't particularly descriptive and may conflict with other 42 | applications. By keeping it in ``registration.models``, it 43 | retains an ``app_label`` of ``registration``, which more 44 | accurately reflects what it does and is less likely to cause 45 | problems. 46 | 47 | 3. Although the ``RegistrationProfile`` model and the various 48 | :ref:`form classes ` are used by the default backend, 49 | they can and are meant to be reused as needed by other 50 | backends. Any backend which uses an activation step should feel 51 | free to reuse the ``RegistrationProfile`` model, for example, 52 | and the registration form classes are in no way tied to a 53 | specific backend (and cover a number of common use cases which 54 | will crop up regardless of the specific backend logic in use). 55 | 56 | 57 | Installation and setup 58 | ---------------------- 59 | 60 | **How do I install django-registration?** 61 | Full instructions are available in :ref:`the quick start guide `. 62 | 63 | **Do I need to put a copy of django-registration in every project I use it in?** 64 | No; putting applications in your project directory is a very bad 65 | habit, and you should stop doing it. If you followed the 66 | instructions mentioned above, django-registration was installed 67 | into a location that's on your Python import path, so you'll only 68 | ever need to add ``registration`` to your ``INSTALLED_APPS`` 69 | setting (in any project, or in any number of projects), and it 70 | will work. 71 | 72 | **Does django-registration come with any sample templates I can use right away?** 73 | No, for two reasons: 74 | 75 | 1. Providing default templates with an application is generally 76 | hard to impossible, because different sites can have such 77 | wildly different design and template structure. Any attempt to 78 | provide templates which would work with all the possibilities 79 | would probably end up working with none of them. 80 | 81 | 2. A number of things in django-registration depend on the 82 | specific :ref:`registration backend ` you use, 83 | including the variables which end up in template 84 | contexts. Since django-registration has no way of knowing in 85 | advance what backend you're going to be using, it also has no 86 | way of knowing what your templates will need to look like. 87 | 88 | Fortunately, however, django-registration has good documentation 89 | which explains what context variables will be available to 90 | templates, and so it should be easy for anyone who knows Django's 91 | template system to create templates which integrate with their own 92 | site. 93 | 94 | 95 | Configuration 96 | ------------- 97 | 98 | **Do I need to rewrite the views to change the way they behave?** 99 | No. There are several ways you can customize behavior without 100 | making any changes whatsoever: 101 | 102 | * Pass custom arguments -- e.g., to specify forms, template names, 103 | etc. -- to :ref:`the registration views `. 104 | 105 | * Use the :ref:`signals ` sent by the views to add custom 106 | behavior. 107 | 108 | * Write a custom :ref:`registration backend ` which 109 | implements the behavior you need, and have the views use your 110 | backend. 111 | 112 | If none of these are sufficient, your best option is likely to 113 | simply write your own views; however, it is hoped that the level 114 | of customization exposed by these options will be sufficient for 115 | nearly all user-registration workflows. 116 | 117 | **How do I pass custom arguments to the views?** 118 | Part 3 of the official Django tutorial, when it `introduces 119 | generic views 120 | `_, 121 | covers the necessary mechanism: simply provide a dictionary of 122 | keyword arguments in your URLconf. 123 | 124 | **Does that mean I should rewrite django-registration's default URLconf?** 125 | No; if you'd like to pass custom arguments to the registration 126 | views, simply write and include your own URLconf instead of 127 | including the default one provided with django-registration. 128 | 129 | **I don't want to write my own URLconf because I don't want to write patterns for all the auth views!** 130 | You're in luck, then; django-registration provides a URLconf which 131 | *only* contains the patterns for the auth views, and which you can 132 | include in your own URLconf anywhere you'd like; it lives at 133 | ``registration.auth_urls``. 134 | 135 | **I don't like the names you've given to the URL patterns!** 136 | In that case, you should feel free to set up your own URLconf 137 | which uses the names you want. 138 | 139 | 140 | Troubleshooting 141 | --------------- 142 | 143 | **I've got functions listening for the registration/activation signals, but they're not getting called!** 144 | 145 | The most common cause of this is placing django-registration in a 146 | sub-directory that's on your Python import path, rather than 147 | installing it directly onto the import path as normal. Importing 148 | from django-registration in that case can cause various issues, 149 | including incorrectly connecting signal handlers. For example, if 150 | you were to place django-registration inside a directory named 151 | ``django_apps``, and refer to it in that manner, you would end up 152 | with a situation where your code does this:: 153 | 154 | from django_apps.registration.signals import user_registered 155 | 156 | But django-registration will be doing:: 157 | 158 | from registration.signals import user_registered 159 | 160 | From Python's point of view, these import statements refer to two 161 | different objects in two different modules, and so signal handlers 162 | connected to the signal from the first import will not be called 163 | when the signal is sent using the second import. 164 | 165 | To avoid this problem, follow the standard practice of installing 166 | django-registration directly on your import path and always 167 | referring to it by its own module name: ``registration`` (and in 168 | general, it is always a good idea to follow normal Python 169 | practices for installing and using Django applications). 170 | 171 | 172 | Tips and tricks 173 | --------------- 174 | 175 | **How do I log a user in immediately after registration or activation?** 176 | You can most likely do this simply by writing a function which 177 | listens for the appropriate :ref:`signal `; your function 178 | should set the ``backend`` attribute of the user to the correct 179 | authentication backend, and then call 180 | ``django.contrib.auth.login()`` to log the user in. 181 | 182 | **How do I re-send an activation email?** 183 | Assuming you're using :ref:`the default backend 184 | `, a `custom admin action 185 | `_ 186 | is provided for this; in the admin for the 187 | :class:`~registration.models.RegistrationProfile` model, simply 188 | click the checkbox for the user(s) you'd like to re-send the email 189 | for, then select the "Re-send activation emails" action. 190 | 191 | **How do I manually activate a user?** 192 | In the default backend, a custom admin action is provided for 193 | this. In the admin for the ``RegistrationProfile`` model, click 194 | the checkbox for the user(s) you'd like to activate, then select 195 | the "Activate users" action. -------------------------------------------------------------------------------- /docs/forms.rst: -------------------------------------------------------------------------------- 1 | .. _forms: 2 | .. module:: registration.forms 3 | 4 | Forms for user registration 5 | =========================== 6 | 7 | Several form classes are provided with django-registration, covering 8 | common cases for gathering account information and implementing common 9 | constraints for user registration. These forms were designed with 10 | django-registration's :ref:`default backend ` in 11 | mind, but may also be useful in other situations. 12 | 13 | 14 | .. class:: RegistrationForm 15 | 16 | A simple form for registering an account. Has the following fields, 17 | all of which are required: 18 | 19 | ``username`` 20 | The username to use for the new account. This is represented as 21 | a text input which validates that the username is unique, 22 | consists entirely of alphanumeric characters and underscores 23 | and is at most 30 characters in length. 24 | 25 | ``email`` 26 | The email address to use for the new account. This is 27 | represented as a text input which accepts email addresses up to 28 | 75 characters in length. 29 | 30 | ``password1`` 31 | The password to use for the new account. This represented as a 32 | password input (``input type="password"`` in the rendered HTML). 33 | 34 | ``password2`` 35 | The password to use for the new account. This represented as a 36 | password input (``input type="password"`` in the rendered HTML). 37 | 38 | The constraints on usernames and email addresses match those 39 | enforced by Django's default authentication backend for instances 40 | of ``django.contrib.auth.models.User``. The repeated entry of the 41 | password serves to catch typos. 42 | 43 | Because it does not apply to any single field of the form, the 44 | validation error for mismatched passwords is attached to the form 45 | itself, and so must be accessed via the form's 46 | ``non_field_errors()`` method. 47 | 48 | 49 | .. class:: RegistrationFormTermsOfService 50 | 51 | A subclass of :class:`RegistrationForm` which adds one additional, 52 | required field: 53 | 54 | ``tos`` 55 | A checkbox indicating agreement to the site's terms of 56 | service/user agreement. 57 | 58 | 59 | .. class:: RegistrationFormUniqueEmail 60 | 61 | A subclass of :class:`RegistrationForm` which enforces uniqueness 62 | of email addresses in addition to uniqueness of usernames. 63 | 64 | 65 | .. class:: RegistrationFormNoFreeEmail 66 | 67 | A subclass of :class:`RegistrationForm` which disallows 68 | registration using addresses from some common free email 69 | providers. This can, in some cases, cut down on automated 70 | registration by spambots. 71 | 72 | By default, the following domains are disallowed for email 73 | addresses: 74 | 75 | * ``aim.com`` 76 | 77 | * ``aol.com`` 78 | 79 | * ``email.com`` 80 | 81 | * ``gmail.com`` 82 | 83 | * ``googlemail.com`` 84 | 85 | * ``hotmail.com`` 86 | 87 | * ``hushmail.com`` 88 | 89 | * ``msn.com`` 90 | 91 | * ``mail.ru`` 92 | 93 | * ``mailinator.com`` 94 | 95 | * ``live.com`` 96 | 97 | * ``yahoo.com`` 98 | 99 | To change this, subclass this form and set the class attribute 100 | ``bad_domains`` to a list of domains you wish to disallow. 101 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. django-registration documentation master file, created by 2 | sphinx-quickstart on Mon Jun 22 02:57:42 2009. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | django-registration 0.8 documentation 7 | ===================================== 8 | 9 | This documentation covers the 0.8 release of django-registration, a 10 | simple but extensible application providing user registration 11 | functionality for `Django `_-powered 12 | websites. 13 | 14 | Although nearly all aspects of the registration process are 15 | customizable, the default setup of django-registration attempts to 16 | cover the most common use case: two-phase registration, consisting of 17 | initial signup followed by a confirmation email which contains 18 | instructions for activating the new account. 19 | 20 | To get up and running quickly, consult the :ref:`quick-start guide 21 | `, which describes all the necessary steps to install 22 | django-registration and configure it for the default workflow. For 23 | more detailed information, including how to customize the registration 24 | process (and support for alternate registration systems), read through 25 | the documentation listed below. 26 | 27 | If you are upgrading from a previous release, please read the 28 | :ref:`upgrade guide ` for information on what's changed. 29 | 30 | Contents: 31 | 32 | .. toctree:: 33 | :maxdepth: 1 34 | 35 | quickstart 36 | release-notes 37 | upgrade 38 | backend-api 39 | default-backend 40 | simple-backend 41 | forms 42 | views 43 | signals 44 | faq 45 | 46 | .. seealso:: 47 | 48 | * `Django's authentication documentation 49 | `_; Django's 50 | authentication system is used by django-registration's default 51 | configuration. 52 | 53 | * `django-profiles 54 | `_, an 55 | application which provides simple user-profile management. 56 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | set SPHINXBUILD=sphinx-build 6 | set ALLSPHINXOPTS=-d _build/doctrees %SPHINXOPTS% . 7 | if NOT "%PAPER%" == "" ( 8 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 9 | ) 10 | 11 | if "%1" == "" goto help 12 | 13 | if "%1" == "help" ( 14 | :help 15 | echo.Please use `make ^` where ^ is one of 16 | echo. html to make standalone HTML files 17 | echo. dirhtml to make HTML files named index.html in directories 18 | echo. pickle to make pickle files 19 | echo. json to make JSON files 20 | echo. htmlhelp to make HTML files and a HTML help project 21 | echo. qthelp to make HTML files and a qthelp project 22 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 23 | echo. changes to make an overview over all changed/added/deprecated items 24 | echo. linkcheck to check all external links for integrity 25 | echo. doctest to run all doctests embedded in the documentation if enabled 26 | goto end 27 | ) 28 | 29 | if "%1" == "clean" ( 30 | for /d %%i in (_build\*) do rmdir /q /s %%i 31 | del /q /s _build\* 32 | goto end 33 | ) 34 | 35 | if "%1" == "html" ( 36 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% _build/html 37 | echo. 38 | echo.Build finished. The HTML pages are in _build/html. 39 | goto end 40 | ) 41 | 42 | if "%1" == "dirhtml" ( 43 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% _build/dirhtml 44 | echo. 45 | echo.Build finished. The HTML pages are in _build/dirhtml. 46 | goto end 47 | ) 48 | 49 | if "%1" == "pickle" ( 50 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% _build/pickle 51 | echo. 52 | echo.Build finished; now you can process the pickle files. 53 | goto end 54 | ) 55 | 56 | if "%1" == "json" ( 57 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% _build/json 58 | echo. 59 | echo.Build finished; now you can process the JSON files. 60 | goto end 61 | ) 62 | 63 | if "%1" == "htmlhelp" ( 64 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% _build/htmlhelp 65 | echo. 66 | echo.Build finished; now you can run HTML Help Workshop with the ^ 67 | .hhp project file in _build/htmlhelp. 68 | goto end 69 | ) 70 | 71 | if "%1" == "qthelp" ( 72 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% _build/qthelp 73 | echo. 74 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 75 | .qhcp project file in _build/qthelp, like this: 76 | echo.^> qcollectiongenerator _build\qthelp\django-registration.qhcp 77 | echo.To view the help file: 78 | echo.^> assistant -collectionFile _build\qthelp\django-registration.ghc 79 | goto end 80 | ) 81 | 82 | if "%1" == "latex" ( 83 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% _build/latex 84 | echo. 85 | echo.Build finished; the LaTeX files are in _build/latex. 86 | goto end 87 | ) 88 | 89 | if "%1" == "changes" ( 90 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% _build/changes 91 | echo. 92 | echo.The overview file is in _build/changes. 93 | goto end 94 | ) 95 | 96 | if "%1" == "linkcheck" ( 97 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% _build/linkcheck 98 | echo. 99 | echo.Link check complete; look for any errors in the above output ^ 100 | or in _build/linkcheck/output.txt. 101 | goto end 102 | ) 103 | 104 | if "%1" == "doctest" ( 105 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% _build/doctest 106 | echo. 107 | echo.Testing of doctests in the sources finished, look at the ^ 108 | results in _build/doctest/output.txt. 109 | goto end 110 | ) 111 | 112 | :end 113 | -------------------------------------------------------------------------------- /docs/release-notes.rst: -------------------------------------------------------------------------------- 1 | .. _release-notes: 2 | 3 | Release notes 4 | ============= 5 | 6 | The |version| release of django-registration represents a complete 7 | rewrite of the previous codebase, and as such introduces a number of 8 | new features and greatly enhances the flexibility and customizability 9 | of django-registration. This document summarizes those features; for a 10 | list of changes which impact existing installations, consult :ref:`the 11 | upgrade guide `. 12 | 13 | 14 | The backend system 15 | ------------------ 16 | 17 | The largest overall change consists of factoring out the logic of user 18 | registration into pluggable/swappable backend classes. The 19 | :ref:`registration views ` now accept a (required) argument, 20 | ``backend``, which indicates the backend class to use, and that class 21 | has full control over the registration (and, if needed, activation) 22 | process, including: 23 | 24 | * Determining whether registration will be allowed at all, on a 25 | per-request basis. 26 | 27 | * Specifying a form class to use for account registration. 28 | 29 | * Implementing the actual process of account creation. 30 | 31 | * Determining whether a separate activation step is needed, and if so 32 | what it will entail. 33 | 34 | * Specifying actions to take (e.g., redirects, automatic login, etc.) 35 | following successful registration or activation. 36 | 37 | For full details, see the documentation for :ref:`the backend API 38 | `. 39 | 40 | The workflow used by previous releases of django-registration 41 | (two-step registration/activation) has been implemented using this 42 | system, and is shipped as :ref:`the default backend ` 43 | in django-registration |version|. 44 | 45 | 46 | Other new features 47 | ------------------ 48 | 49 | An alternate :ref:`one-step registration system ` is 50 | provided, for use by sites which do not require a two-step 51 | registration/activation system. 52 | 53 | During the registration and (optional) activation process, 54 | :ref:`custom signals ` are now sent, allowing easy injection 55 | of custom processing into the registration workflow without needing to 56 | write a full backend. 57 | 58 | The default backend now supplies several `custom admin actions 59 | `_ to 60 | make the process of administering a site with django-registration 61 | simpler. 62 | 63 | The :func:`~registration.views.activate` view now supplies any 64 | captured keyword arguments from the URL (in the case of the default 65 | backend, this is the activation key) to its template in case of 66 | unsuccessful activation; this greatly simplifies the process of 67 | determining why activation failed and displaying appropriate error 68 | messages. 69 | 70 | -------------------------------------------------------------------------------- /docs/signals.rst: -------------------------------------------------------------------------------- 1 | .. _signals: 2 | .. module:: registration.signals 3 | 4 | 5 | Custom signals used by django-registration 6 | ========================================== 7 | 8 | Much of django-registration's customizability comes through the 9 | ability to write and use :ref:`registration backends ` 10 | implementing different workflows for user registration. However, there 11 | are many cases where only a small bit of additional logic needs to be 12 | injected into the registration process, and writing a custom backend 13 | to support this represents an unnecessary amount of work. A more 14 | lightweight customization option is provided through two custom 15 | signals which backends are required to send at specific points during 16 | the registration process; functions listening for these signals can 17 | then add whatever logic is needed. 18 | 19 | For general documentation on signals and the Django dispatcher, 20 | consult `Django's signals documentation 21 | `_. This 22 | documentation assumes that you are familiar with how signals work and 23 | the process of writing and connecting functions which will listen for 24 | signals. 25 | 26 | 27 | .. data:: user_activated 28 | 29 | Sent when a user account is activated (not applicable to all 30 | backends). Provides the following arguments: 31 | 32 | ``sender`` 33 | The backend class used to activate the user. 34 | 35 | ``user`` 36 | An instance of ``django.contrib.auth.models.User`` 37 | representing the activated account. 38 | 39 | ``request`` 40 | The ``HttpRequest`` in which the account was activated. 41 | 42 | 43 | .. data:: user_registered 44 | 45 | Sent when a new user account is registered. Provides the following 46 | arguments: 47 | 48 | ``sender`` 49 | The backend class used to register the account. 50 | 51 | ``user`` 52 | An instance of ``django.contrib.auth.models.User`` 53 | representing the new account. 54 | 55 | ``request`` 56 | The ``HttpRequest`` in which the new account was registered. 57 | -------------------------------------------------------------------------------- /docs/simple-backend.rst: -------------------------------------------------------------------------------- 1 | .. _simple-backend: 2 | .. module:: registration.backends.simple 3 | 4 | The "simple" (one-step) backend 5 | =============================== 6 | 7 | As an alternative to :ref:`the default backend `, and 8 | an example of writing :ref:`registration backends `, 9 | django-registration bundles a one-step registration system in 10 | ``registration.backend.simple``. This backend's workflow is 11 | deliberately as simple as possible: 12 | 13 | 1. A user signs up by filling out a registration form. 14 | 15 | 2. The user's account is created and is active immediately, with no 16 | intermediate confirmation or activation step. 17 | 18 | 3. The new user is logged in immediately. 19 | 20 | 21 | Configuration 22 | ------------- 23 | 24 | To use this backend, simply include the URLconf 25 | ``registration.backends.simple.urls`` somewhere in your site's own URL 26 | configuration. For example:: 27 | 28 | (r'^accounts/', include('registration.backends.simple.urls')), 29 | 30 | No additional settings are required, but one optional setting is 31 | supported: 32 | 33 | ``REGISTRATION_OPEN`` 34 | A boolean (either ``True`` or ``False``) indicating whether 35 | registration of new accounts is currently permitted. A default of 36 | ``True`` will be assumed if this setting is not supplied. 37 | 38 | Upon successful registration, the default redirect is to the URL 39 | specified by the ``get_absolute_url()`` method of the newly-created 40 | ``User`` object; by default, this will be ``/users//``, 41 | although it can be overridden in either of two ways: 42 | 43 | 1. Specify a custom URL pattern for the 44 | :func:`~registration.views.register` view, passing the keyword 45 | argument ``success_url``. 46 | 47 | 2. Override the default ``get_absolute_url()`` of the ``User`` model 48 | in your Django configuration, as covered in `Django's settings 49 | documentation 50 | `_. 51 | 52 | The default form class used for account registration will be 53 | :class:`registration.forms.RegistrationForm`, although this can be 54 | overridden by supplying a custom URL pattern for the ``register()`` 55 | view and passing the keyword argument ``form_class``. 56 | 57 | Note that because this backend does not use an activation step, 58 | attempting to use the :func:`~registration.views.activate` view with 59 | this backend or calling the backend's ``activate()`` or 60 | ``post_activation_redirect()`` methods will raise 61 | ``NotImplementedError``. 62 | -------------------------------------------------------------------------------- /docs/upgrade.rst: -------------------------------------------------------------------------------- 1 | .. _upgrade: 2 | 3 | Upgrade guide 4 | ============= 5 | 6 | The |version| release of django-registration represents a complete 7 | rewrite of the previous codebase, and introduces several new features 8 | which greatly enhance the customizability and extensibility of 9 | django-registration. Whenever possible, changes were made in ways 10 | which preserve backwards compatibility with previous releases, but 11 | some changes to existing installations will still be required in order 12 | to upgrade to |version|. This document provides a summary of those 13 | changes, and of the new features available in the |version| release. 14 | 15 | 16 | Django version requirement 17 | -------------------------- 18 | 19 | As of |version|, django-registration requires Django 1.1 or newer; 20 | older Django releases will not work, as django-registration |version| 21 | takes advantage of several Django features which are only present as 22 | of 1.1. 23 | 24 | 25 | Backwards-incompatible changes 26 | ------------------------------ 27 | 28 | If you're upgrading from an older release of django-registration, and 29 | if you were using the default setup (i.e., the included default 30 | URLconf and no custom URL patterns or custom arguments to views), most 31 | things will continue to work as normal (although you will need to 32 | create one new template; see the section on views below). However, the 33 | old default URLconf has been deprecated and will be removed in version 34 | 1.0 of django-registration, so it is recommended that you begin 35 | migrating now. To do so, change any use of ``registration.urls`` to 36 | ``registration.backends.default.urls``. For example, if you had the 37 | following in your root URLconf:: 38 | 39 | (r'^accounts/', include('registration.urls')), 40 | 41 | you should change it to:: 42 | 43 | (r'^accounts/', include('registration.backends.default.urls')), 44 | 45 | The older include will continue to work until django-registration 1.0; 46 | in |version| it raises a ``PendingDeprecationWarning`` (which is 47 | ignored by default in Python), in 0.9 it will raise 48 | ``DeprecationWarning`` (which will begin printing warning messages on 49 | import) and in 1.0 it will be removed entirely. 50 | 51 | 52 | Changes to registration views 53 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 | 55 | :ref:`The views used to handle user registration ` have changed 56 | significantly as of django-registration |version|. Both views now 57 | require the keyword argument ``backend``, which specifies the 58 | :ref:`registration backend ` to use, and so any URL 59 | pattern for these views must supply that argument. The URLconf 60 | provided with :ref:`the default backend ` properly 61 | passes this argument. 62 | 63 | The ``profile_callback`` argument of the 64 | :func:`~registration.views.register` view has been removed; the 65 | functionality it provided can now be implemented easily via a custom 66 | backend, or by connecting listeners to :ref:`the signals sent during 67 | the registration process `. 68 | 69 | The :func:`~registration.views.activate` view now issues a redirect 70 | upon successful activation; in the default backend this is to the URL 71 | pattern named ``registration_activation_complete``; in the default 72 | setup, this will redirect to a view which renders the template 73 | ``registration/activation_complete.html``, and so this template should 74 | be present when using the default backend and default 75 | configuration. Other backends can specify the location to redirect to 76 | through their ``post_activation_redirect()`` method, and this can be 77 | overridden on a case-by-case basis by passing the (new) keyword 78 | argument ``success_url`` to the ``activate()`` view. On unsuccessful 79 | activation, the ``activate()`` view still displays the same template, 80 | but its context has changed: the context will simply consist of any 81 | keyword arguments captured in the URL and passed to the view. 82 | 83 | 84 | Changes to registration forms 85 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 86 | 87 | Previously, the form used to collect data during registration was 88 | expected to implement a ``save()`` method which would create the new 89 | user account. This is no longer the case; creating the account is 90 | handled by the backend, and so any custom logic should be moved into a 91 | custom backend, or by connecting listeners to :ref:`the signals sent 92 | during the registration process `. 93 | 94 | 95 | Changes to the :class:`~registration.models.RegistrationProfile` model 96 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 97 | 98 | The 99 | :meth:`~registration.models.RegistrationManager.create_inactive_user` 100 | method of :class:`~registration.models.RegistrationManager` now has an 101 | additional required argument: ``site``. This allows 102 | django-registration to easily be used regardless of whether 103 | ``django.contrib.sites`` is installed, since a ``RequestSite`` object 104 | can be passed in place of a regular ``Site`` object. 105 | 106 | The :data:`~registration.signals.user_registered` signal is no longer 107 | sent by ``create_inactive_user()``, and the 108 | :data:`~registration.signals.user_activated` signal is no longer sent 109 | by :meth:`~registration.models.RegistrationManager.activate_user`; 110 | these signals are now sent by the backend after these methods have 111 | been called. Note that :ref:`these signals ` were added after 112 | the django-registration 0.7 release but before the refactoring which 113 | introduced :ref:`the backend API `, so only installations 114 | which were tracking the in-development codebase will have made use of 115 | them. 116 | 117 | The sending of activation emails has been factored out of 118 | ``create_inactive_user()``, and now exists as the method 119 | :meth:`~registration.models.RegistrationProfile.send_activation_email` 120 | on instances of ``RegistrationProfile``. 121 | -------------------------------------------------------------------------------- /docs/views.rst: -------------------------------------------------------------------------------- 1 | .. _views: 2 | .. module:: registration.views 3 | 4 | Registration views 5 | ================== 6 | 7 | In order to allow users to register using whatever workflow is 8 | implemented by the :ref:`registration backend ` in use, 9 | django-registration provides two views. Both are designed to allow 10 | easy configurability without writing or rewriting view code. 11 | 12 | .. function:: activate(request, backend[, template_name[, success_url[, extra_context[, **kwargs]]]]) 13 | 14 | Activate a user's account, for workflows which require a separate 15 | activation step. 16 | 17 | The actual activation of the account will be delegated to the 18 | backend specified by the ``backend`` keyword argument; the 19 | backend's ``activate()`` method will be called, passing the 20 | ``HttpRequest`` and any keyword arguments captured from the URL, 21 | and will be assumed to return a ``User`` if activation was 22 | successful, or a value which evaluates to ``False`` in boolean 23 | context if not. 24 | 25 | Upon successful activation, the backend's 26 | ``post_activation_redirect()`` method will be called, passing the 27 | ``HttpRequest`` and the activated ``User`` to determine the URL to 28 | redirect the user to. To override this, pass the argument 29 | ``success_url`` (see below). 30 | 31 | On unsuccessful activation, will render the template 32 | ``registration/activate.html`` to display an error message; to 33 | override thise, pass the argument ``template_name`` (see below). 34 | 35 | **Context** 36 | 37 | The context will be populated from the keyword arguments captured 38 | in the URL. This view uses ``RequestContext``, so variables 39 | populated by context processors will also be present in the 40 | context. 41 | 42 | :param backend: The dotted Python path to the backend class to use. 43 | :type backend: string 44 | :param extra_context: Optionally, variables to add to the template 45 | context. Any callable object in this dictionary will be called 46 | to produce the final result which appears in the context. 47 | :type extra_context: dict 48 | :param template_name: Optional. A custom template name to use. If 49 | not specified, this will default to 50 | ``registration/activate.html``. 51 | :type template_name: string 52 | :param **kwargs: Any keyword arguments captured from the URL, such 53 | as an activation key, which will be passed to the backend's 54 | ``activate()`` method. 55 | 56 | 57 | .. function:: register(request, backend[, success_url[, form_class[, disallowed_url[, template_name[, extra_context]]]]]) 58 | 59 | Allow a new user to register an account. 60 | 61 | The actual registration of the account will be delegated to the 62 | backend specified by the ``backend`` keyword argument. The backend 63 | is used as follows: 64 | 65 | 1. The backend's ``registration_allowed()`` method will be called, 66 | passing the ``HttpRequest``, to determine whether registration 67 | of an account is to be allowed; if not, a redirect is issued to 68 | a page indicating that registration is not permitted. 69 | 70 | 2. The form to use for account registration will be obtained by 71 | calling the backend's ``get_form_class()`` method, passing the 72 | ``HttpRequest``. To override this, pass the keyword argument 73 | ``form_class``. 74 | 75 | 3. If valid, the form's ``cleaned_data`` will be passed (as keyword 76 | arguments, and along with the ``HttpRequest``) to the backend's 77 | ``register()`` method, which should return a ``User`` object 78 | representing the new account. 79 | 80 | 4. Upon successful registration, the backend's 81 | ``post_registration_redirect()`` method will be called, passing 82 | the ``HttpRequest`` and the new ``User``, to determine the URL 83 | to redirect to. To override this, pass the keyword argument 84 | ``success_url``. 85 | 86 | **Context** 87 | 88 | ``form`` 89 | The form instance being used to collect registration data. 90 | 91 | This view uses ``RequestContext``, so variables populated by 92 | context processors will also be present in the context. 93 | 94 | :param backend: The dotted Python path to the backend class to use. 95 | :type backend: string 96 | :param disallowed_url: The URL to redirect to if registration is 97 | not permitted (e.g., if registration is closed). This should be 98 | a string suitable for passing as the ``to`` argument to 99 | `Django's "redirect" shortcut 100 | `_. If 101 | not specified, this will default to ``registration_disallowed``. 102 | :type disallowed_url: string 103 | :param extra_context: Optionally, variables to add to the template 104 | context. Any callable object in this dictionary will be called 105 | to produce the final result which appears in the context. 106 | :type extra_context: dict 107 | :param form_class: The form class to use for registration; this 108 | should be some subclass of ``django.forms.Form``. If not 109 | specified, the backend's ``get_form_class()`` method will be 110 | called to obtain the form class. 111 | :type form_class: subclass of ``django.forms.Form`` 112 | :param success_url: The URL to redirect to after successful 113 | registration. This should be a string suitable for passing as 114 | the ``to`` argument to `Django's "redirect" shortcut 115 | `_. If 116 | not specified, the backend's ``post_registration_redirect()`` 117 | method will be called to obtain the URL. 118 | :type success_url: string 119 | :param template_name: Optional. A custom template name to use. If 120 | not specified, this will default to 121 | ``registration/registration_form.html``. 122 | :type template_name: string 123 | -------------------------------------------------------------------------------- /registration/__init__.py: -------------------------------------------------------------------------------- 1 | VERSION = (0, 8, 0, 'alpha', 1) 2 | 3 | def get_version(): 4 | version = '%s.%s' % (VERSION[0], VERSION[1]) 5 | if VERSION[2]: 6 | version = '%s.%s' % (version, VERSION[2]) 7 | if VERSION[3:] == ('alpha', 0): 8 | version = '%s pre-alpha' % version 9 | else: 10 | if VERSION[3] != 'final': 11 | version = "%s %s" % (version, VERSION[3]) 12 | if VERSION[4] != 0: 13 | version = '%s %s' % (version, VERSION[4]) 14 | return version 15 | -------------------------------------------------------------------------------- /registration/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.sites.models import RequestSite 3 | from django.contrib.sites.models import Site 4 | from django.utils.translation import ugettext_lazy as _ 5 | 6 | from registration.models import RegistrationProfile 7 | 8 | 9 | class RegistrationAdmin(admin.ModelAdmin): 10 | actions = ['activate_users', 'resend_activation_email'] 11 | list_display = ('user', 'activation_key_expired') 12 | raw_id_fields = ['user'] 13 | search_fields = ('user__username', 'user__first_name') 14 | 15 | def activate_users(self, request, queryset): 16 | """ 17 | Activates the selected users, if they are not alrady 18 | activated. 19 | 20 | """ 21 | for profile in queryset: 22 | RegistrationProfile.objects.activate_user(profile.activation_key) 23 | activate_users.short_description = _("Activate users") 24 | 25 | def resend_activation_email(self, request, queryset): 26 | """ 27 | Re-sends activation emails for the selected users. 28 | 29 | Note that this will *only* send activation emails for users 30 | who are eligible to activate; emails will not be sent to users 31 | whose activation keys have expired or who have already 32 | activated. 33 | 34 | """ 35 | if Site._meta.installed: 36 | site = Site.objects.get_current() 37 | else: 38 | site = RequestSite(request) 39 | 40 | for profile in queryset: 41 | if not profile.activation_key_expired(): 42 | profile.send_activation_email(site) 43 | resend_activation_email.short_description = _("Re-send activation emails") 44 | 45 | 46 | admin.site.register(RegistrationProfile, RegistrationAdmin) 47 | -------------------------------------------------------------------------------- /registration/auth_urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URL patterns for the views included in ``django.contrib.auth``. 3 | 4 | Including these URLs (via the ``include()`` directive) will set up the 5 | following patterns based at whatever URL prefix they are included 6 | under: 7 | 8 | * User login at ``login/``. 9 | 10 | * User logout at ``logout/``. 11 | 12 | * The two-step password change at ``password/change/`` and 13 | ``password/change/done/``. 14 | 15 | * The four-step password reset at ``password/reset/``, 16 | ``password/reset/confirm/``, ``password/reset/complete/`` and 17 | ``password/reset/done/``. 18 | 19 | The default registration backend already has an ``include()`` for 20 | these URLs, so under the default setup it is not necessary to manually 21 | include these views. Other backends may or may not include them; 22 | consult a specific backend's documentation for details. 23 | 24 | """ 25 | 26 | from django.conf.urls.defaults import * 27 | 28 | from django.contrib.auth import views as auth_views 29 | 30 | 31 | urlpatterns = patterns('', 32 | url(r'^login/$', 33 | auth_views.login, 34 | {'template_name': 'registration/login.html'}, 35 | name='auth_login'), 36 | url(r'^logout/$', 37 | auth_views.logout, 38 | {'template_name': 'registration/logout.html'}, 39 | name='auth_logout'), 40 | url(r'^password/change/$', 41 | auth_views.password_change, 42 | name='auth_password_change'), 43 | url(r'^password/change/done/$', 44 | auth_views.password_change_done, 45 | name='auth_password_change_done'), 46 | url(r'^password/reset/$', 47 | auth_views.password_reset, 48 | name='auth_password_reset'), 49 | url(r'^password/reset/confirm/(?P[0-9A-Za-z]+)-(?P.+)/$', 50 | auth_views.password_reset_confirm, 51 | name='auth_password_reset_confirm'), 52 | url(r'^password/reset/complete/$', 53 | auth_views.password_reset_complete, 54 | name='auth_password_reset_complete'), 55 | url(r'^password/reset/done/$', 56 | auth_views.password_reset_done, 57 | name='auth_password_reset_done'), 58 | ) 59 | -------------------------------------------------------------------------------- /registration/backends/__init__.py: -------------------------------------------------------------------------------- 1 | from django.core.exceptions import ImproperlyConfigured 2 | 3 | 4 | # Python 2.7 has an importlib with import_module; for older Pythons, 5 | # Django's bundled copy provides it. 6 | try: 7 | from importlib import import_module 8 | except ImportError: 9 | from django.utils.importlib import import_module 10 | 11 | def get_backend(path): 12 | """ 13 | Return an instance of a registration backend, given the dotted 14 | Python import path (as a string) to the backend class. 15 | 16 | If the backend cannot be located (e.g., because no such module 17 | exists, or because the module does not contain a class of the 18 | appropriate name), ``django.core.exceptions.ImproperlyConfigured`` 19 | is raised. 20 | 21 | """ 22 | i = path.rfind('.') 23 | module, attr = path[:i], path[i+1:] 24 | try: 25 | mod = import_module(module) 26 | except ImportError, e: 27 | raise ImproperlyConfigured('Error loading registration backend %s: "%s"' % (module, e)) 28 | try: 29 | backend_class = getattr(mod, attr) 30 | except AttributeError: 31 | raise ImproperlyConfigured('Module "%s" does not define a registration backend named "%s"' % (module, attr)) 32 | return backend_class() 33 | -------------------------------------------------------------------------------- /registration/backends/default/__init__.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.contrib.sites.models import RequestSite 3 | from django.contrib.sites.models import Site 4 | 5 | from registration import signals 6 | from registration.forms import RegistrationForm 7 | from registration.models import RegistrationProfile 8 | 9 | 10 | class DefaultBackend(object): 11 | """ 12 | A registration backend which follows a simple workflow: 13 | 14 | 1. User signs up, inactive account is created. 15 | 16 | 2. Email is sent to user with activation link. 17 | 18 | 3. User clicks activation link, account is now active. 19 | 20 | Using this backend requires that 21 | 22 | * ``registration`` be listed in the ``INSTALLED_APPS`` setting 23 | (since this backend makes use of models defined in this 24 | application). 25 | 26 | * The setting ``ACCOUNT_ACTIVATION_DAYS`` be supplied, specifying 27 | (as an integer) the number of days from registration during 28 | which a user may activate their account (after that period 29 | expires, activation will be disallowed). 30 | 31 | * The creation of the templates 32 | ``registration/activation_email_subject.txt`` and 33 | ``registration/activation_email.txt``, which will be used for 34 | the activation email. See the notes for this backends 35 | ``register`` method for details regarding these templates. 36 | 37 | Additionally, registration can be temporarily closed by adding the 38 | setting ``REGISTRATION_OPEN`` and setting it to 39 | ``False``. Omitting this setting, or setting it to ``True``, will 40 | be interpreted as meaning that registration is currently open and 41 | permitted. 42 | 43 | Internally, this is accomplished via storing an activation key in 44 | an instance of ``registration.models.RegistrationProfile``. See 45 | that model and its custom manager for full documentation of its 46 | fields and supported operations. 47 | 48 | """ 49 | def register(self, request, **kwargs): 50 | """ 51 | Given a username, email address and password, register a new 52 | user account, which will initially be inactive. 53 | 54 | Along with the new ``User`` object, a new 55 | ``registration.models.RegistrationProfile`` will be created, 56 | tied to that ``User``, containing the activation key which 57 | will be used for this account. 58 | 59 | An email will be sent to the supplied email address; this 60 | email should contain an activation link. The email will be 61 | rendered using two templates. See the documentation for 62 | ``RegistrationProfile.send_activation_email()`` for 63 | information about these templates and the contexts provided to 64 | them. 65 | 66 | After the ``User`` and ``RegistrationProfile`` are created and 67 | the activation email is sent, the signal 68 | ``registration.signals.user_registered`` will be sent, with 69 | the new ``User`` as the keyword argument ``user`` and the 70 | class of this backend as the sender. 71 | 72 | """ 73 | username, email, password = kwargs['username'], kwargs['email'], kwargs['password1'] 74 | if Site._meta.installed: 75 | site = Site.objects.get_current() 76 | else: 77 | site = RequestSite(request) 78 | new_user = RegistrationProfile.objects.create_inactive_user(username, email, 79 | password, site) 80 | signals.user_registered.send(sender=self.__class__, 81 | user=new_user, 82 | request=request) 83 | return new_user 84 | 85 | def activate(self, request, activation_key): 86 | """ 87 | Given an an activation key, look up and activate the user 88 | account corresponding to that key (if possible). 89 | 90 | After successful activation, the signal 91 | ``registration.signals.user_activated`` will be sent, with the 92 | newly activated ``User`` as the keyword argument ``user`` and 93 | the class of this backend as the sender. 94 | 95 | """ 96 | activated = RegistrationProfile.objects.activate_user(activation_key) 97 | if activated: 98 | signals.user_activated.send(sender=self.__class__, 99 | user=activated, 100 | request=request) 101 | return activated 102 | 103 | def registration_allowed(self, request): 104 | """ 105 | Indicate whether account registration is currently permitted, 106 | based on the value of the setting ``REGISTRATION_OPEN``. This 107 | is determined as follows: 108 | 109 | * If ``REGISTRATION_OPEN`` is not specified in settings, or is 110 | set to ``True``, registration is permitted. 111 | 112 | * If ``REGISTRATION_OPEN`` is both specified and set to 113 | ``False``, registration is not permitted. 114 | 115 | """ 116 | return getattr(settings, 'REGISTRATION_OPEN', True) 117 | 118 | def get_form_class(self, request): 119 | """ 120 | Return the default form class used for user registration. 121 | 122 | """ 123 | return RegistrationForm 124 | 125 | def post_registration_redirect(self, request, user): 126 | """ 127 | Return the name of the URL to redirect to after successful 128 | user registration. 129 | 130 | """ 131 | return ('registration_complete', (), {}) 132 | 133 | def post_activation_redirect(self, request, user): 134 | """ 135 | Return the name of the URL to redirect to after successful 136 | account activation. 137 | 138 | """ 139 | return ('registration_activation_complete', (), {}) 140 | -------------------------------------------------------------------------------- /registration/backends/default/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URLconf for registration and activation, using django-registration's 3 | default backend. 4 | 5 | If the default behavior of these views is acceptable to you, simply 6 | use a line like this in your root URLconf to set up the default URLs 7 | for registration:: 8 | 9 | (r'^accounts/', include('registration.backends.default.urls')), 10 | 11 | This will also automatically set up the views in 12 | ``django.contrib.auth`` at sensible default locations. 13 | 14 | If you'd like to customize the behavior (e.g., by passing extra 15 | arguments to the various views) or split up the URLs, feel free to set 16 | up your own URL patterns for these views instead. 17 | 18 | """ 19 | 20 | 21 | from django.conf.urls.defaults import * 22 | from django.views.generic.simple import direct_to_template 23 | 24 | from registration.views import activate 25 | from registration.views import register 26 | 27 | 28 | urlpatterns = patterns('', 29 | url(r'^activate/complete/$', 30 | direct_to_template, 31 | {'template': 'registration/activation_complete.html'}, 32 | name='registration_activation_complete'), 33 | # Activation keys get matched by \w+ instead of the more specific 34 | # [a-fA-F0-9]{40} because a bad activation key should still get to the view; 35 | # that way it can return a sensible "invalid key" message instead of a 36 | # confusing 404. 37 | url(r'^activate/(?P\w+)/$', 38 | activate, 39 | {'backend': 'registration.backends.default.DefaultBackend'}, 40 | name='registration_activate'), 41 | url(r'^register/$', 42 | register, 43 | {'backend': 'registration.backends.default.DefaultBackend'}, 44 | name='registration_register'), 45 | url(r'^register/complete/$', 46 | direct_to_template, 47 | {'template': 'registration/registration_complete.html'}, 48 | name='registration_complete'), 49 | url(r'^register/closed/$', 50 | direct_to_template, 51 | {'template': 'registration/registration_closed.html'}, 52 | name='registration_disallowed'), 53 | (r'', include('registration.auth_urls')), 54 | ) 55 | -------------------------------------------------------------------------------- /registration/backends/simple/__init__.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.contrib.auth import authenticate 3 | from django.contrib.auth import login 4 | from django.contrib.auth.models import User 5 | 6 | from registration import signals 7 | from registration.forms import RegistrationForm 8 | 9 | 10 | class SimpleBackend(object): 11 | """ 12 | A registration backend which implements the simplest possible 13 | workflow: a user supplies a username, email address and password 14 | (the bare minimum for a useful account), and is immediately signed 15 | up and logged in. 16 | 17 | """ 18 | def register(self, request, **kwargs): 19 | """ 20 | Create and immediately log in a new user. 21 | 22 | """ 23 | username, email, password = kwargs['username'], kwargs['email'], kwargs['password1'] 24 | User.objects.create_user(username, email, password) 25 | 26 | # authenticate() always has to be called before login(), and 27 | # will return the user we just created. 28 | new_user = authenticate(username=username, password=password) 29 | login(request, new_user) 30 | signals.user_registered.send(sender=self.__class__, 31 | user=new_user, 32 | request=request) 33 | return new_user 34 | 35 | def activate(self, **kwargs): 36 | raise NotImplementedError 37 | 38 | def registration_allowed(self, request): 39 | """ 40 | Indicate whether account registration is currently permitted, 41 | based on the value of the setting ``REGISTRATION_OPEN``. This 42 | is determined as follows: 43 | 44 | * If ``REGISTRATION_OPEN`` is not specified in settings, or is 45 | set to ``True``, registration is permitted. 46 | 47 | * If ``REGISTRATION_OPEN`` is both specified and set to 48 | ``False``, registration is not permitted. 49 | 50 | """ 51 | return getattr(settings, 'REGISTRATION_OPEN', True) 52 | 53 | def get_form_class(self, request): 54 | return RegistrationForm 55 | 56 | def post_registration_redirect(self, request, user): 57 | """ 58 | After registration, redirect to the user's account page. 59 | 60 | """ 61 | return (user.get_absolute_url(), (), {}) 62 | 63 | def post_activation_redirect(self, request, user): 64 | raise NotImplementedError 65 | -------------------------------------------------------------------------------- /registration/backends/simple/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URLconf for registration and activation, using django-registration's 3 | one-step backend. 4 | 5 | If the default behavior of these views is acceptable to you, simply 6 | use a line like this in your root URLconf to set up the default URLs 7 | for registration:: 8 | 9 | (r'^accounts/', include('registration.backends.simple.urls')), 10 | 11 | This will also automatically set up the views in 12 | ``django.contrib.auth`` at sensible default locations. 13 | 14 | If you'd like to customize the behavior (e.g., by passing extra 15 | arguments to the various views) or split up the URLs, feel free to set 16 | up your own URL patterns for these views instead. 17 | 18 | """ 19 | 20 | 21 | from django.conf.urls.defaults import * 22 | from django.views.generic.simple import direct_to_template 23 | 24 | from registration.views import activate 25 | from registration.views import register 26 | 27 | 28 | urlpatterns = patterns('', 29 | url(r'^register/$', 30 | register, 31 | {'backend': 'registration.backends.simple.SimpleBackend'}, 32 | name='registration_register'), 33 | url(r'^register/closed/$', 34 | direct_to_template, 35 | {'template': 'registration/registration_closed.html'}, 36 | name='registration_disallowed'), 37 | (r'', include('registration.auth_urls')), 38 | ) 39 | -------------------------------------------------------------------------------- /registration/forms.py: -------------------------------------------------------------------------------- 1 | """ 2 | Forms and validation code for user registration. 3 | 4 | """ 5 | 6 | 7 | from django.contrib.auth.models import User 8 | from django import forms 9 | from django.utils.translation import ugettext_lazy as _ 10 | 11 | 12 | # I put this on all required fields, because it's easier to pick up 13 | # on them with CSS or JavaScript if they have a class of "required" 14 | # in the HTML. Your mileage may vary. If/when Django ticket #3515 15 | # lands in trunk, this will no longer be necessary. 16 | attrs_dict = {'class': 'required'} 17 | 18 | 19 | class RegistrationForm(forms.Form): 20 | """ 21 | Form for registering a new user account. 22 | 23 | Validates that the requested username is not already in use, and 24 | requires the password to be entered twice to catch typos. 25 | 26 | Subclasses should feel free to add any additional validation they 27 | need, but should avoid defining a ``save()`` method -- the actual 28 | saving of collected user data is delegated to the active 29 | registration backend. 30 | 31 | """ 32 | username = forms.RegexField(regex=r'^\w+$', 33 | max_length=30, 34 | widget=forms.TextInput(attrs=attrs_dict), 35 | label=_("Username"), 36 | error_messages={'invalid': _("This value must contain only letters, numbers and underscores.")}) 37 | email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict, 38 | maxlength=75)), 39 | label=_("Email address")) 40 | password1 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict, render_value=False), 41 | label=_("Password")) 42 | password2 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict, render_value=False), 43 | label=_("Password (again)")) 44 | 45 | def clean_username(self): 46 | """ 47 | Validate that the username is alphanumeric and is not already 48 | in use. 49 | 50 | """ 51 | try: 52 | user = User.objects.get(username__iexact=self.cleaned_data['username']) 53 | except User.DoesNotExist: 54 | return self.cleaned_data['username'] 55 | raise forms.ValidationError(_("A user with that username already exists.")) 56 | 57 | def clean(self): 58 | """ 59 | Verifiy that the values entered into the two password fields 60 | match. Note that an error here will end up in 61 | ``non_field_errors()`` because it doesn't apply to a single 62 | field. 63 | 64 | """ 65 | if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data: 66 | if self.cleaned_data['password1'] != self.cleaned_data['password2']: 67 | raise forms.ValidationError(_("The two password fields didn't match.")) 68 | return self.cleaned_data 69 | 70 | 71 | class RegistrationFormTermsOfService(RegistrationForm): 72 | """ 73 | Subclass of ``RegistrationForm`` which adds a required checkbox 74 | for agreeing to a site's Terms of Service. 75 | 76 | """ 77 | tos = forms.BooleanField(widget=forms.CheckboxInput(attrs=attrs_dict), 78 | label=_(u'I have read and agree to the Terms of Service'), 79 | error_messages={'required': _("You must agree to the terms to register")}) 80 | 81 | 82 | class RegistrationFormUniqueEmail(RegistrationForm): 83 | """ 84 | Subclass of ``RegistrationForm`` which enforces uniqueness of 85 | email addresses. 86 | 87 | """ 88 | def clean_email(self): 89 | """ 90 | Validate that the supplied email address is unique for the 91 | site. 92 | 93 | """ 94 | if User.objects.filter(email__iexact=self.cleaned_data['email']): 95 | raise forms.ValidationError(_("This email address is already in use. Please supply a different email address.")) 96 | return self.cleaned_data['email'] 97 | 98 | 99 | class RegistrationFormNoFreeEmail(RegistrationForm): 100 | """ 101 | Subclass of ``RegistrationForm`` which disallows registration with 102 | email addresses from popular free webmail services; moderately 103 | useful for preventing automated spam registrations. 104 | 105 | To change the list of banned domains, subclass this form and 106 | override the attribute ``bad_domains``. 107 | 108 | """ 109 | bad_domains = ['aim.com', 'aol.com', 'email.com', 'gmail.com', 110 | 'googlemail.com', 'hotmail.com', 'hushmail.com', 111 | 'msn.com', 'mail.ru', 'mailinator.com', 'live.com', 112 | 'yahoo.com'] 113 | 114 | def clean_email(self): 115 | """ 116 | Check the supplied email address against a list of known free 117 | webmail domains. 118 | 119 | """ 120 | email_domain = self.cleaned_data['email'].split('@')[1] 121 | if email_domain in self.bad_domains: 122 | raise forms.ValidationError(_("Registration using free email addresses is prohibited. Please supply a different email address.")) 123 | return self.cleaned_data['email'] 124 | -------------------------------------------------------------------------------- /registration/locale/ar/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/ar/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/ar/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "اسم المستخدم" 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "عنوان البريد الالكتروني" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "كلمة المرور" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "تأكيد كلمة المرور" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "يمكن أن يحتوي اسم المستخدم على احرف، ارقام وشرطات سطرية فقط" 38 | 39 | #: forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "اسم المستخدم مسجل مسبقا. يرجى اختيار اسم اخر." 42 | 43 | #: forms.py:68 44 | msgid "You must type the same password each time" 45 | msgstr "يجب ادخال كلمة المرور مطابقة كل مرة" 46 | 47 | #: forms.py:96 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "أقر بقراءة والموافقة على شروط الخدمة" 50 | 51 | #: forms.py:105 52 | msgid "You must agree to the terms to register" 53 | msgstr "يجب الموافقة على الشروط للتسجيل" 54 | 55 | #: forms.py:124 56 | msgid "" 57 | "This email address is already in use. Please supply a different email " 58 | "address." 59 | msgstr "عنوان البريد الالكتروني مسجل مسبقا. يرجى تزويد عنوان بريد الكتروني مختلف." 60 | 61 | #: forms.py:149 62 | msgid "" 63 | "Registration using free email addresses is prohibited. Please supply a " 64 | "different email address." 65 | msgstr "يمنع التسجيل باستخدام عناوين بريد الكترونية مجانية. يرجى تزويد عنوان بريد الكتروني مختلف." 66 | 67 | #: models.py:188 68 | msgid "user" 69 | msgstr "مستخدم" 70 | 71 | #: models.py:189 72 | msgid "activation key" 73 | msgstr "رمز التفعيل" 74 | 75 | #: models.py:194 76 | msgid "registration profile" 77 | msgstr "ملف التسجيل الشخصي" 78 | 79 | #: models.py:195 80 | msgid "registration profiles" 81 | msgstr "ملفات التسجيل الشخصية" 82 | -------------------------------------------------------------------------------- /registration/locale/bg/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/bg/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/bg/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: PACKAGE VERSION\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 11 | "PO-Revision-Date: 2008-03-05 12:37+0200\n" 12 | "Last-Translator: Vladislav \n" 13 | "Language-Team: LANGUAGE \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | "X-Poedit-Bookmarks: -1,-1,-1,-1,10,-1,-1,-1,-1,-1\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "Потребителско име " 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "Електронна поща" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "Парола" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "Парола (проверка)" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "Потребителските имена могат да съдържат букви, цифри и подчертавки" 38 | 39 | #: forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "Потребителското име е заето. Моля изберето друго." 42 | 43 | #: forms.py:68 44 | msgid "You must type the same password each time" 45 | msgstr "Грешка при проверка на паролата." 46 | 47 | #: forms.py:96 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "Прочел съм и съм съгласен с условията за експлоатация" 50 | 51 | #: forms.py:105 52 | msgid "You must agree to the terms to register" 53 | msgstr "Трябва да сте съгласни с условията за да се регистрирате." 54 | 55 | #: forms.py:124 56 | msgid "This email address is already in use. Please supply a different email address." 57 | msgstr "Адреса на електронната поща е използван. Моля въведете друг адрес." 58 | 59 | #: forms.py:149 60 | msgid "Registration using free email addresses is prohibited. Please supply a different email address." 61 | msgstr "Регистрациите с безплатни адреси е забранен. Моля въведете различен адрес за електронна поща" 62 | 63 | #: models.py:188 64 | msgid "user" 65 | msgstr "Потребител" 66 | 67 | #: models.py:189 68 | msgid "activation key" 69 | msgstr "Ключ за активация" 70 | 71 | #: models.py:194 72 | msgid "registration profile" 73 | msgstr "регистрационен профил" 74 | 75 | #: models.py:195 76 | msgid "registration profiles" 77 | msgstr "регистрационни профили" 78 | 79 | -------------------------------------------------------------------------------- /registration/locale/da/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/da/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/da/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Rune Bromer , 2007-2009. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: django-registration 0.8 \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: \n" 12 | "PO-Revision-Date: \n" 13 | "Last-Translator: Rune Bromer \n" 14 | "Language-Team: \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: admin.py:23 20 | msgid "Activate users" 21 | msgstr "Aktiver brugere" 22 | 23 | #: admin.py:43 24 | msgid "Re-send activation emails" 25 | msgstr "Gensend aktiveringsemails" 26 | 27 | #: forms.py:35 28 | msgid "Username" 29 | msgstr "Brugernavn" 30 | 31 | #: forms.py:36 32 | msgid "This value must contain only letters, numbers and underscores." 33 | msgstr "V¾rdien mŒ kun indeholde bogstaver, tal og underscore." 34 | 35 | #: forms.py:39 36 | msgid "Email address" 37 | msgstr "E-mailadresse" 38 | 39 | #: forms.py:41 40 | msgid "Password" 41 | msgstr "Password" 42 | 43 | #: forms.py:43 44 | msgid "Password (again)" 45 | msgstr "Password (gentag)" 46 | 47 | #: forms.py:55 48 | msgid "A user with that username already exists." 49 | msgstr "Der findes allerede en bruger med dette brugernavn." 50 | 51 | #: forms.py:67 52 | msgid "The two password fields didn't match." 53 | msgstr "De 2 passwordfelter er ikke ens." 54 | 55 | #: forms.py:78 56 | msgid "I have read and agree to the Terms of Service" 57 | msgstr "I har l¾st og accepterer betingelserne." 58 | 59 | #: forms.py:79 60 | msgid "You must agree to the terms to register" 61 | msgstr "Du skal acceptere betingelserne for at registere" 62 | 63 | #: forms.py:95 64 | msgid "" 65 | "This email address is already in use. Please supply a different email " 66 | "address." 67 | msgstr "" 68 | "Denne emailadresse er allerede i brug. Benyt venligst en anden. " 69 | 70 | #: forms.py:122 71 | msgid "" 72 | "Registration using free email addresses is prohibited. Please supply a " 73 | "different email address." 74 | msgstr "" 75 | "Registrering med gratis emailadresser er ikke muligt. V¾lg venligst en " 76 | "anden emailadresse" 77 | 78 | #: models.py:165 79 | msgid "user" 80 | msgstr "bruger" 81 | 82 | #: models.py:166 83 | msgid "activation key" 84 | msgstr "Aktiveringsn¿gle" 85 | 86 | #: models.py:171 87 | msgid "registration profile" 88 | msgstr "Registreringsprofil" 89 | 90 | #: models.py:172 91 | msgid "registration profiles" 92 | msgstr "Registreringprofiler" 93 | -------------------------------------------------------------------------------- /registration/locale/de/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/de/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/de/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Jannis Leidel , 2007-2009. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: django-registration 0.8 \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2009-10-18 21:32+0200\n" 12 | "PO-Revision-Date: 2007-09-29 16:50+0200\n" 13 | "Last-Translator: Jannis Leidel \n" 14 | "Language-Team: Deutsch \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: admin.py:23 20 | msgid "Activate users" 21 | msgstr "Benutzer aktivieren" 22 | 23 | #: admin.py:43 24 | msgid "Re-send activation emails" 25 | msgstr "Aktivierungs-E-Mail erneut senden" 26 | 27 | #: forms.py:35 28 | msgid "Username" 29 | msgstr "Benutzername" 30 | 31 | #: forms.py:36 32 | msgid "This value must contain only letters, numbers and underscores." 33 | msgstr "Dieser Wert darf nur Buchstaben, Ziffern und Unterstriche enthalten." 34 | 35 | #: forms.py:39 36 | msgid "Email address" 37 | msgstr "E-Mail-Adresse" 38 | 39 | #: forms.py:41 40 | msgid "Password" 41 | msgstr "Passwort" 42 | 43 | #: forms.py:43 44 | msgid "Password (again)" 45 | msgstr "Passwort (wiederholen)" 46 | 47 | #: forms.py:55 48 | msgid "A user with that username already exists." 49 | msgstr "Dieser Benutzername ist bereits vergeben." 50 | 51 | #: forms.py:67 52 | msgid "The two password fields didn't match." 53 | msgstr "Die beiden Passwörter sind nicht identisch." 54 | 55 | #: forms.py:78 56 | msgid "I have read and agree to the Terms of Service" 57 | msgstr "Ich habe die Nutzungsvereinbarung gelesen und stimme ihr zu" 58 | 59 | #: forms.py:79 60 | msgid "You must agree to the terms to register" 61 | msgstr "Sie müssen der Nutzungsvereinbarung zustimmen, um sich zu registrieren" 62 | 63 | #: forms.py:95 64 | msgid "" 65 | "This email address is already in use. Please supply a different email " 66 | "address." 67 | msgstr "" 68 | "Diese E-Mail-Adresse wird schon genutzt. Bitte geben Sie eine andere E-Mail-" 69 | "Adresse an." 70 | 71 | #: forms.py:122 72 | msgid "" 73 | "Registration using free email addresses is prohibited. Please supply a " 74 | "different email address." 75 | msgstr "" 76 | "Die Registrierung mit einer kostenlosen E-Mail-Adresse ist untersagt. Bitte " 77 | "geben Sie eine andere E-Mail-Adresse an." 78 | 79 | #: models.py:165 80 | msgid "user" 81 | msgstr "Benutzer" 82 | 83 | #: models.py:166 84 | msgid "activation key" 85 | msgstr "Aktivierungsschlüssel" 86 | 87 | #: models.py:171 88 | msgid "registration profile" 89 | msgstr "Registrierungsprofil" 90 | 91 | #: models.py:172 92 | msgid "registration profiles" 93 | msgstr "Registrierungsprofile" 94 | -------------------------------------------------------------------------------- /registration/locale/el/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/el/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/el/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Panos Laganakos , 2007. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 12 | "PO-Revision-Date: 2007-11-14 21:50+0200\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "όνομα χρήστη" 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "διεύθυνση ηλεκτρονικού ταχυδρομείου" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "συνθηματικό" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "συνθηματικό (ξανά)" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "Τα ονόματα χρηστών μπορούν να περιλαμβάνουν μόνο γράμματα, αριθμούς και υπογραμμίσεις" 38 | 39 | #: forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "Αυτό το όνομα χρήστη χρησιμοποίειται ήδη. Παρακαλώ διαλέξτε ένα άλλο." 42 | 43 | #: forms.py:68 44 | msgid "You must type the same password each time" 45 | msgstr "Πρέπει να εισάγετε το ίδιο συνθηματικό κάθε φορά" 46 | 47 | #: forms.py:96 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "Διάβασα και συμφωνώ με τους Όρους της Υπηρεσίας" 50 | 51 | #: forms.py:105 52 | msgid "You must agree to the terms to register" 53 | msgstr "Πρέπει να συμφωνείται με τους όρους για να εγγραφείτε" 54 | 55 | #: forms.py:124 56 | msgid "" 57 | "This email address is already in use. Please supply a different email " 58 | "address." 59 | msgstr "" 60 | "Η συγκεκριμένη διεύθυνση ηλεκτρονικού ταχυδρομείου χρησιμοποιείται ήδη. " 61 | "Παρακαλώ δώστε κάποια άλλη." 62 | 63 | #: forms.py:149 64 | msgid "" 65 | "Registration using free email addresses is prohibited. Please supply a " 66 | "different email address." 67 | msgstr "" 68 | "Η εγγραφή μέσω δωρεάν διευθύνσεων ηλεκτρονικού ταχυδρομείου απαγορεύεται. ""Παρακαλώ δώστε κάποια άλλη." 69 | 70 | #: models.py:188 71 | msgid "user" 72 | msgstr "χρήστης" 73 | 74 | #: models.py:189 75 | msgid "activation key" 76 | msgstr "κλειδί ενεργοποίησης" 77 | 78 | #: models.py:194 79 | msgid "registration profile" 80 | msgstr "προφίλ εγγραφής" 81 | 82 | #: models.py:195 83 | msgid "registration profiles" 84 | msgstr "προφίλ εγγραφών" 85 | -------------------------------------------------------------------------------- /registration/locale/en/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/en/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/en/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2009-10-12 14:09-0500\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: admin.py:23 20 | msgid "Activate users" 21 | msgstr "" 22 | 23 | #: admin.py:43 24 | msgid "Re-send activation emails" 25 | msgstr "" 26 | 27 | #: forms.py:35 28 | msgid "username" 29 | msgstr "" 30 | 31 | #: forms.py:36 32 | msgid "This value must contain only letters, numbers and underscores." 33 | msgstr "" 34 | 35 | #: forms.py:39 36 | msgid "Email address" 37 | msgstr "" 38 | 39 | #: forms.py:41 40 | msgid "Password" 41 | msgstr "" 42 | 43 | #: forms.py:43 44 | msgid "Password (again)" 45 | msgstr "" 46 | 47 | #: forms.py:55 48 | msgid "A user with that username already exists." 49 | msgstr "" 50 | 51 | #: forms.py:67 52 | msgid "The two password fields didn't match." 53 | msgstr "" 54 | 55 | #: forms.py:78 56 | msgid "I have read and agree to the Terms of Service" 57 | msgstr "" 58 | 59 | #: forms.py:79 60 | msgid "You must agree to the terms to register" 61 | msgstr "" 62 | 63 | #: forms.py:95 64 | msgid "" 65 | "This email address is already in use. Please supply a different email " 66 | "address." 67 | msgstr "" 68 | 69 | #: forms.py:122 70 | msgid "" 71 | "Registration using free email addresses is prohibited. Please supply a " 72 | "different email address." 73 | msgstr "" 74 | 75 | #: models.py:165 76 | msgid "user" 77 | msgstr "" 78 | 79 | #: models.py:166 80 | msgid "activation key" 81 | msgstr "" 82 | 83 | #: models.py:171 84 | msgid "registration profile" 85 | msgstr "" 86 | 87 | #: models.py:172 88 | msgid "registration profiles" 89 | msgstr "" 90 | -------------------------------------------------------------------------------- /registration/locale/es/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/es/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/es/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # Spanish translation for django-registration. 2 | # Copyright (C) 2007, James Bennet 3 | # This file is distributed under the same license as the registration package. 4 | # Ernesto Rico Schmidt , 2008. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: django-registration 0.3 \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2008-03-11 00:19-0400\n" 12 | "PO-Revision-Date: 2008-03-11 00:19-0400\n" 13 | "Last-Translator: Ernesto Rico Schmidt \n" 14 | "Language-Team: Español \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "nombre de usuario" 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "dirección de coreo electrónico" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "contraseña" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "contraseña (otra vez)" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "Los nombres de usuarios sólo pueden contener letras, números y guiones bajos" 38 | 39 | #: forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "Este nombre de usuario ya está ocupado. Por favor escoge otro" 42 | 43 | #: forms.py:71 44 | msgid "You must type the same password each time" 45 | msgstr "Tienes que introducir la misma contraseña cada vez" 46 | 47 | #: forms.py:100 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "He leído y acepto los términos de servicio" 50 | 51 | #: forms.py:109 52 | msgid "You must agree to the terms to register" 53 | msgstr "Tienes que aceptar los términos para registrarte" 54 | 55 | #: forms.py:128 56 | msgid "" 57 | "This email address is already in use. Please supply a different email " 58 | "address." 59 | msgstr "" 60 | "La dirección de correo electrónico ya está siendo usada. Por favor" 61 | "proporciona otra dirección." 62 | 63 | #: forms.py:153 64 | msgid "" 65 | "Registration using free email addresses is prohibited. Please supply a " 66 | "different email address." 67 | msgstr "" 68 | "El registro usando una dirección de correo electrónico gratis está prohibido." 69 | "Por favor proporciona otra dirección." 70 | 71 | #: models.py:188 72 | msgid "user" 73 | msgstr "usuario" 74 | 75 | #: models.py:189 76 | msgid "activation key" 77 | msgstr "clave de activación" 78 | 79 | #: models.py:194 80 | msgid "registration profile" 81 | msgstr "perfil de registro" 82 | 83 | #: models.py:195 84 | msgid "registration profiles" 85 | msgstr "perfiles de registro" 86 | -------------------------------------------------------------------------------- /registration/locale/es_AR/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/es_AR/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/es_AR/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) 2008 Leonardo Manuel Rocha 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "nombre de usuario" 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "dirección de e-mail" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "contraseña" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "contraseña (nuevamente)" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "El nombre de usuario solo puede contener letras, números y guiones bajos" 38 | 39 | #: forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "Ese nombre de usuario ya está asignado. Por favor elija otro." 42 | 43 | #: forms.py:68 44 | msgid "You must type the same password each time" 45 | msgstr "Debe tipear la misma contraseña cada vez" 46 | 47 | #: forms.py:96 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "He leído y estoy de acuerdo con las Condiciones de Servicio" 50 | 51 | #: forms.py:105 52 | msgid "You must agree to the terms to register" 53 | msgstr "Debe estar de acuerdo con las Condiciones para poder registrarse" 54 | 55 | #: forms.py:124 56 | msgid "" 57 | "This email address is already in use. Please supply a different email " 58 | "address." 59 | msgstr "Esa dirección de e-mail ya está en uso. Por favor provea otra " 60 | "dirección." 61 | 62 | #: forms.py:149 63 | msgid "" 64 | "Registration using free email addresses is prohibited. Please supply a " 65 | "different email address." 66 | msgstr "La registración con un e-mail gratuito está prohibida. Por favor " 67 | "de una dirección de e-mail diferente." 68 | 69 | #: models.py:188 70 | msgid "user" 71 | msgstr "usuario" 72 | 73 | #: models.py:189 74 | msgid "activation key" 75 | msgstr "clave de activación" 76 | 77 | #: models.py:194 78 | msgid "registration profile" 79 | msgstr "perfil de registro" 80 | 81 | #: models.py:195 82 | msgid "registration profiles" 83 | msgstr "perfiles de registro" 84 | -------------------------------------------------------------------------------- /registration/locale/fr/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/fr/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/fr/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Samuel Adam , 2007. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: django-registration 0.3 \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 12 | "PO-Revision-Date: 2007-09-20 10:30+0100\n" 13 | "Last-Translator: Samuel Adam \n" 14 | "Language-Team: Français \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "pseudo" 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "adresse email" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "mot de passe" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "mot de passe (vérification)" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "Le pseudo ne peut contenir que des lettres, chiffres et le caractère souligné." 38 | 39 | #: forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "Ce pseudo est déjà utilisé. Veuillez en choisir un autre." 42 | 43 | #: forms.py:68 44 | msgid "You must type the same password each time" 45 | msgstr "Veuillez indiquer le même mot de passe dans les deux champs" 46 | 47 | #: forms.py:96 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "J'ai lu et accepté les Conditions Générales d'Utilisation" 50 | 51 | #: forms.py:105 52 | msgid "You must agree to the terms to register" 53 | msgstr "Vous devez accepter les conditions d'utilisation pour vous inscrire" 54 | 55 | #: forms.py:124 56 | msgid "" 57 | "This email address is already in use. Please supply a different email " 58 | "address." 59 | msgstr "Cette adresse email est déjà utilisée. Veuillez en indiquer une autre." 60 | 61 | #: forms.py:149 62 | msgid "" 63 | "Registration using free email addresses is prohibited. Please supply a " 64 | "different email address." 65 | msgstr "L'inscription avec une adresse email d'un compte gratuit est interdite. Veuillez en indiquer une autre." 66 | 67 | #: models.py:188 68 | msgid "user" 69 | msgstr "utilisateur" 70 | 71 | #: models.py:189 72 | msgid "activation key" 73 | msgstr "clé d'activation" 74 | 75 | #: models.py:194 76 | msgid "registration profile" 77 | msgstr "profil d'inscription" 78 | 79 | #: models.py:195 80 | msgid "registration profiles" 81 | msgstr "profils d'inscription" 82 | -------------------------------------------------------------------------------- /registration/locale/he/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/he/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/he/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # translation of registration. 2 | # Copyright (C) 2008 THE registration'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the registration package. 4 | # <>, 2008. 5 | # , fuzzy 6 | # <>, 2008. 7 | # 8 | # 9 | msgid "" 10 | msgstr "" 11 | "Project-Id-Version: registration\n" 12 | "Report-Msgid-Bugs-To: \n" 13 | "POT-Creation-Date: 2008-02-10 02:01+0200\n" 14 | "PO-Revision-Date: 2008-02-10 02:05+0200\n" 15 | "Last-Translator: Meir Kriheli \n" 16 | "Language-Team: Hebrew\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: 8bit" 20 | 21 | #: forms.py:38 22 | msgid "username" 23 | msgstr "שם משתמש" 24 | 25 | #: forms.py:41 26 | msgid "email address" 27 | msgstr "דואר אלקטרוני" 28 | 29 | #: forms.py:43 30 | msgid "password" 31 | msgstr "סיסמה" 32 | 33 | #: forms.py:45 34 | msgid "password (again)" 35 | msgstr "סיסמה (שוב)" 36 | 37 | #: forms.py:54 38 | msgid "Usernames can only contain letters, numbers and underscores" 39 | msgstr "שמות משתמש יכולים להכיל רק אותיות, ספרות וקווים תחתונים" 40 | 41 | #: forms.py:59 42 | msgid "This username is already taken. Please choose another." 43 | msgstr "שם המשתמש תפוס כבר. נא לבחור אחר." 44 | 45 | #: forms.py:64 46 | msgid "You must type the same password each time" 47 | msgstr "יש להקליד את אותה הסיסמה פעמיים" 48 | 49 | #: forms.py:93 50 | msgid "I have read and agree to the Terms of Service" 51 | msgstr "קראתי והסכמתי לתנאי השימוש" 52 | 53 | #: forms.py:102 54 | msgid "You must agree to the terms to register" 55 | msgstr "עליך להסכים לתנאי השימוש" 56 | 57 | #: forms.py:121 58 | msgid "" 59 | "This email address is already in use. Please supply a different email " 60 | "address." 61 | msgstr "" 62 | "כתובת הדואר האלקטרוני תפוסה כבר. נא לספק כתובת דואר אחרת." 63 | 64 | #: forms.py:146 65 | msgid "" 66 | "Registration using free email addresses is prohibited. Please supply a " 67 | "different email address." 68 | msgstr "" 69 | "הרישום בעזרת תיבת דואר אלקטרוני חינמית אסור. נא לספק כתובת אחרת." 70 | 71 | #: models.py:188 72 | msgid "user" 73 | msgstr "משתמש" 74 | 75 | #: models.py:189 76 | msgid "activation key" 77 | msgstr "מפתח הפעלה" 78 | 79 | #: models.py:194 80 | msgid "registration profile" 81 | msgstr "פרופיל רישום" 82 | 83 | #: models.py:195 84 | msgid "registration profiles" 85 | msgstr "פרופילי רישום" 86 | 87 | -------------------------------------------------------------------------------- /registration/locale/is/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/is/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/is/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # Icelandic translation of django-registration 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the django-registration 4 | # package. 5 | # Björn Kristinsson , 2009. 6 | # 7 | #, fuzzy 8 | msgid "" 9 | msgstr "" 10 | "Project-Id-Version: PACKAGE VERSION\n" 11 | "Report-Msgid-Bugs-To: \n" 12 | "POT-Creation-Date: 2009-01-22 12:49+0100\n" 13 | "PO-Revision-Date: 2009-01-22 12:49+0100\n" 14 | "Last-Translator: Björn Kristinsson \n" 15 | "Language-Team: Icelandic\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: forms.py:36 21 | msgid "username" 22 | msgstr "notandanafn" 23 | 24 | #: forms.py:39 25 | msgid "email address" 26 | msgstr "netfang" 27 | 28 | #: forms.py:41 29 | msgid "password" 30 | msgstr "lykilorð" 31 | 32 | #: forms.py:43 33 | msgid "password (again)" 34 | msgstr "lykilorð (aftur)" 35 | 36 | #: forms.py:55 37 | msgid "This username is already taken. Please choose another." 38 | msgstr "Þetta notendanafn er þegar á skrá. Vinsamlega reyndu annað." 39 | 40 | #: forms.py:67 41 | msgid "You must type the same password each time" 42 | msgstr "Lykilorðin verða að vera eins " 43 | 44 | #: forms.py:90 45 | msgid "I have read and agree to the Terms of Service" 46 | msgstr "Ég hef lesið og samþykki skilmálana" 47 | 48 | #: forms.py:107 49 | msgid "" 50 | "This email address is already in use. Please supply a different email " 51 | "address." 52 | msgstr "Þetta netfang er þegar á skrá. Vinsamlegast notaðu annað netfang." 53 | 54 | #: forms.py:133 55 | msgid "" 56 | "Registration using free email addresses is prohibited. Please supply a " 57 | "different email address." 58 | msgstr "Óheimilt er að nota ókeypis netföng. Vinsamlegast notaðu annað netfang." 59 | 60 | #: models.py:218 61 | msgid "user" 62 | msgstr "notandi" 63 | 64 | #: models.py:219 65 | msgid "activation key" 66 | msgstr "einkennislykill" 67 | 68 | #: models.py:224 69 | msgid "registration profile" 70 | msgstr "skráningarprófíll" 71 | 72 | #: models.py:225 73 | msgid "registration profiles" 74 | msgstr "skráningarprófílar" 75 | -------------------------------------------------------------------------------- /registration/locale/it/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/it/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/it/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # translation of django.po to Italiano 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # 5 | # Nicola Larosa , 2008. 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: django\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 11 | "PO-Revision-Date: 2008-05-27 15:05+0200\n" 12 | "Last-Translator: Nicola Larosa \n" 13 | "Language-Team: Italiano\n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | "X-Generator: KBabel 1.11.4\n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | 20 | #: forms.py:38 21 | msgid "username" 22 | msgstr "nome utente" 23 | 24 | #: forms.py:41 25 | msgid "email address" 26 | msgstr "indirizzo email" 27 | 28 | #: forms.py:43 29 | msgid "password" 30 | msgstr "password" 31 | 32 | #: forms.py:45 33 | msgid "password (again)" 34 | msgstr "password (di nuovo)" 35 | 36 | #: forms.py:54 37 | msgid "Usernames can only contain letters, numbers and underscores" 38 | msgstr "I nomi utente possono contenere solo lettere, numeri e sottolineature" 39 | 40 | #: forms.py:59 41 | msgid "This username is already taken. Please choose another." 42 | msgstr "Questo nome utente è già usato. Scegline un altro." 43 | 44 | #: forms.py:68 45 | msgid "You must type the same password each time" 46 | msgstr "Bisogna inserire la stessa password ogni volta" 47 | 48 | #: forms.py:96 49 | msgid "I have read and agree to the Terms of Service" 50 | msgstr "Dichiaro di aver letto e di approvare le Condizioni di Servizio" 51 | 52 | #: forms.py:105 53 | msgid "You must agree to the terms to register" 54 | msgstr "Per registrarsi bisogna approvare le condizioni" 55 | 56 | #: forms.py:124 57 | msgid "This email address is already in use. Please supply a different email " 58 | "address." 59 | msgstr "Questo indirizzo email è già in uso. Inserisci un altro indirizzo email." 60 | 61 | #: forms.py:149 62 | msgid "Registration using free email addresses is prohibited. Please supply a " 63 | "different email address." 64 | msgstr "La registrazione con indirizzi email gratis non è permessa. " 65 | "Inserisci un altro indirizzo email." 66 | 67 | #: models.py:188 68 | msgid "user" 69 | msgstr "utente" 70 | 71 | #: models.py:189 72 | msgid "activation key" 73 | msgstr "chiave di attivazione" 74 | 75 | #: models.py:194 76 | msgid "registration profile" 77 | msgstr "profilo di registrazione" 78 | 79 | #: models.py:195 80 | msgid "registration profiles" 81 | msgstr "profili di registrazione" 82 | 83 | -------------------------------------------------------------------------------- /registration/locale/ja/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/ja/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/ja/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Shinya Okano , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: django-registration 0.4 \n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 12 | "PO-Revision-Date: 2008-01-31 10:20+0900\n" 13 | "Last-Translator: Shinya Okano \n" 14 | "Language-Team: Japanese \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "ユーザ名" 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "メールアドレス" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "パスワード" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "パスワード (確認)" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "ユーザ名には半角英数とアンダースコアのみが使用できます。" 38 | 39 | #: forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "このユーザ名は既に使用されています。他のユーザ名を指定してください。" 42 | 43 | #: forms.py:68 44 | msgid "You must type the same password each time" 45 | msgstr "同じパスワードを入力する必要があります。" 46 | 47 | #: forms.py:96 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "サービス利用規約を読み、同意します。" 50 | 51 | #: forms.py:105 52 | msgid "You must agree to the terms to register" 53 | msgstr "登録するためには規約に同意する必要があります。" 54 | 55 | #: forms.py:124 56 | msgid "This email address is already in use. Please supply a different email address." 57 | msgstr "このメールアドレスは既に使用されています。他のメールアドレスを指定して下さい。" 58 | 59 | #: forms.py:149 60 | msgid "Registration using free email addresses is prohibited. Please supply a different email address." 61 | msgstr "自由なメールアドレスを使用した登録は禁止されています。他のメールアドレスを指定してください。" 62 | 63 | #: models.py:188 64 | msgid "user" 65 | msgstr "ユーザ" 66 | 67 | #: models.py:189 68 | msgid "activation key" 69 | msgstr "アクティベーションキー" 70 | 71 | #: models.py:194 72 | msgid "registration profile" 73 | msgstr "登録プロファイル" 74 | 75 | #: models.py:195 76 | msgid "registration profiles" 77 | msgstr "登録プロファイル" 78 | 79 | -------------------------------------------------------------------------------- /registration/locale/ko/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/ko/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/ko/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # Young Gyu Park , 2009. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2009-10-12 14:09-0500\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: Young Gyu Park \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: admin.py:23 20 | msgid "Activate users" 21 | msgstr "활동 사용자" 22 | 23 | #: admin.py:43 24 | msgid "Re-send activation emails" 25 | msgstr "이 메일 제 전송" 26 | 27 | #: forms.py:35 28 | msgid "username" 29 | msgstr "사용자 아이디" 30 | 31 | #: forms.py:36 32 | msgid "This value must contain only letters, numbers and underscores." 33 | msgstr "이 곳에는 숫자, _, 영문 글자만 가능합니다." 34 | 35 | #: forms.py:39 36 | msgid "Email address" 37 | msgstr "이메일 주소" 38 | 39 | #: forms.py:41 40 | msgid "Password" 41 | msgstr "사용자 패스워드" 42 | 43 | #: forms.py:43 44 | msgid "Password (again)" 45 | msgstr "패스워드 (재입력)" 46 | 47 | #: forms.py:55 48 | msgid "A user with that username already exists." 49 | msgstr "이미 같은 아이디로 사용자가 등록되어 있습니다." 50 | 51 | #: forms.py:67 52 | msgid "The two password fields didn't match." 53 | msgstr "패스워드가 서로 일치하지 않습니다." 54 | 55 | #: forms.py:78 56 | msgid "I have read and agree to the Terms of Service" 57 | msgstr "약관을 읽었고 그 내용에 동의합니다." 58 | 59 | #: forms.py:79 60 | msgid "You must agree to the terms to register" 61 | msgstr "약관에 동의 하셔야만 합니다." 62 | 63 | #: forms.py:95 64 | msgid "" 65 | "This email address is already in use. Please supply a different email " 66 | "address." 67 | msgstr "이메일이 이미 사용중입니다. 다른 이메일을 등록해 주세요." 68 | 69 | #: forms.py:122 70 | msgid "" 71 | "Registration using free email addresses is prohibited. Please supply a " 72 | "different email address." 73 | msgstr "무료 이메일 계정으로 등록하실 수 없습니다. 다른 이메일을 등록해 주세요" 74 | 75 | #: models.py:165 76 | msgid "user" 77 | msgstr "사용자" 78 | 79 | #: models.py:166 80 | msgid "activation key" 81 | msgstr "활성화 키" 82 | 83 | #: models.py:171 84 | msgid "registration profile" 85 | msgstr "등록 프로파일" 86 | 87 | #: models.py:172 88 | msgid "registration profiles" 89 | msgstr "등록 프로파일" 90 | -------------------------------------------------------------------------------- /registration/locale/nl/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/nl/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/nl/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: registration\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2008-08-14 13:25+0200\n" 11 | "PO-Revision-Date: 2008-08-14 13:25+0200\n" 12 | "Last-Translator: Joost Cassee \n" 13 | "Language-Team: LANGUAGE \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "gebruikersnaam" 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "e-mail adres" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "wachtwoord" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "wachtwoord (opnieuw)" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "Gebruikersnamen kunnen alleen letters, nummer en liggende streepjes bevatten." 38 | 39 | #: forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "Deze gebruikersnaam is reeds in gebruik. Kiest u alstublieft een andere gebruikersnaam." 42 | 43 | #: forms.py:71 44 | msgid "You must type the same password each time" 45 | msgstr "U moet twee maal hetzelfde wachtwoord typen." 46 | 47 | #: forms.py:100 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "Ik heb de servicevoorwaarden gelezen en ga akkoord." 50 | 51 | #: forms.py:109 52 | msgid "You must agree to the terms to register" 53 | msgstr "U moet akkoord gaan met de servicevoorwaarden om u te registreren." 54 | 55 | #: forms.py:125 56 | msgid "This email address is already in use. Please supply a different email address." 57 | msgstr "Dit e-mail adres is reeds in gebruik. Kiest u alstublieft een ander e-mail adres." 58 | 59 | #: forms.py:151 60 | msgid "Registration using free email addresses is prohibited. Please supply a different email address." 61 | msgstr "U kunt u niet registreren met een gratis e-mail adres. Kiest u alstublieft een ander e-mail adres." 62 | 63 | #: models.py:191 64 | msgid "user" 65 | msgstr "gebruiker" 66 | 67 | #: models.py:192 68 | msgid "activation key" 69 | msgstr "activatiecode" 70 | 71 | #: models.py:197 72 | msgid "registration profile" 73 | msgstr "registratieprofiel" 74 | 75 | #: models.py:198 76 | msgid "registration profiles" 77 | msgstr "registratieprofielen" 78 | -------------------------------------------------------------------------------- /registration/locale/pl/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/pl/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/pl/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # Polish translation for django-registration. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the django-registration package. 4 | # Jarek Zgoda , 2007. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: 0.4\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 12 | "PO-Revision-Date: 2007-12-15 12:45+0100\n" 13 | "Last-Translator: Jarek Zgoda \n" 14 | "Language-Team: Polish \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "nazwa użytkownika" 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "adres email" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "hasło" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "hasło (ponownie)" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "" 38 | "Nazwa użytkownika może zawierać tylko litery, cyfry i znaki podkreślenia" 39 | 40 | #: forms.py:59 41 | msgid "This username is already taken. Please choose another." 42 | msgstr "Ta nazwa użytkownika jest już zajęta. Wybierz inną." 43 | 44 | #: forms.py:68 45 | msgid "You must type the same password each time" 46 | msgstr "Musisz wpisać to samo hasło w obu polach" 47 | 48 | #: forms.py:96 49 | msgid "I have read and agree to the Terms of Service" 50 | msgstr "Przeczytałem regulamin i akceptuję go" 51 | 52 | #: forms.py:105 53 | msgid "You must agree to the terms to register" 54 | msgstr "Musisz zaakceptować regulamin, aby się zarejestrować" 55 | 56 | #: forms.py:124 57 | msgid "" 58 | "This email address is already in use. Please supply a different email " 59 | "address." 60 | msgstr "Ten adres email jest już używany. Użyj innego adresu email." 61 | 62 | #: forms.py:149 63 | msgid "" 64 | "Registration using free email addresses is prohibited. Please supply a " 65 | "different email address." 66 | msgstr "" 67 | "Nie ma możliwości rejestracji przy użyciu darmowego adresu email. Użyj " 68 | "innego adresu email." 69 | 70 | #: models.py:188 71 | msgid "user" 72 | msgstr "użytkownik" 73 | 74 | #: models.py:189 75 | msgid "activation key" 76 | msgstr "klucz aktywacyjny" 77 | 78 | #: models.py:194 79 | msgid "registration profile" 80 | msgstr "profil rejestracji" 81 | 82 | #: models.py:195 83 | msgid "registration profiles" 84 | msgstr "profile rejestracji" 85 | -------------------------------------------------------------------------------- /registration/locale/pt_BR/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/pt_BR/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/pt_BR/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: forms.py:38 20 | msgid "username" 21 | msgstr "usuário" 22 | 23 | #: forms.py:41 24 | msgid "email address" 25 | msgstr "endereço de email" 26 | 27 | #: forms.py:43 28 | msgid "password" 29 | msgstr "" 30 | 31 | #: forms.py:45 32 | msgid "password (again)" 33 | msgstr "senha (novamente)" 34 | 35 | #: forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "Nomes de usuário apenas podem conter letras, números, e underscore" 38 | 39 | #: forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "Este nome de usuário já existe. Por favor, escolha outro." 42 | 43 | #: forms.py:68 44 | msgid "You must type the same password each time" 45 | msgstr "Você deve escrever a mesma senha nos dois campos" 46 | 47 | #: forms.py:96 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "Eu lí e concordo com os Termos de Uso do serviço" 50 | 51 | #: forms.py:105 52 | msgid "You must agree to the terms to register" 53 | msgstr "Você deve concordar com os termos para registrar-se" 54 | 55 | #: forms.py:124 56 | msgid "" 57 | "This email address is already in use. Please supply a different email " 58 | "address." 59 | msgstr "Este endereço de email já está em uso. Por favor, informe um endereço de email diferente." 60 | 61 | #: forms.py:149 62 | msgid "" 63 | "Registration using free email addresses is prohibited. Please supply a " 64 | "different email address." 65 | msgstr "Registrar-se com contas de email gratuitos está proibido. Por favor, informe um endereço de email diferente." 66 | 67 | #: models.py:188 68 | msgid "user" 69 | msgstr "usuário" 70 | 71 | #: models.py:189 72 | msgid "activation key" 73 | msgstr "chave de ativação" 74 | 75 | #: models.py:194 76 | msgid "registration profile" 77 | msgstr "profile de registro" 78 | 79 | #: models.py:195 80 | msgid "registration profiles" 81 | msgstr "profiles de registro" 82 | -------------------------------------------------------------------------------- /registration/locale/ru/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/ru/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/ru/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: PACKAGE VERSION\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2009-10-21 20:12+0600\n" 11 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 12 | "Last-Translator: FULL NAME \n" 13 | "Language-Team: LANGUAGE \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | 18 | #: admin.py:23 19 | msgid "Activate users" 20 | msgstr "Активировать учетные записи" 21 | 22 | #: admin.py:43 23 | msgid "Re-send activation emails" 24 | msgstr "Выслать ключи активации заново" 25 | 26 | #: forms.py:35 27 | msgid "Username" 28 | msgstr "Имя пользователя" 29 | 30 | #: forms.py:36 31 | msgid "This value must contain only letters, numbers and underscores." 32 | msgstr "Это поле может содержать только буквы, цифры и подчеркивания" 33 | 34 | #: forms.py:39 35 | msgid "Email address" 36 | msgstr "Адрес электронной почты" 37 | 38 | #: forms.py:41 39 | msgid "Password" 40 | msgstr "Пароль" 41 | 42 | #: forms.py:43 43 | msgid "Password (again)" 44 | msgstr "Пароль (снова)" 45 | 46 | #: forms.py:55 47 | msgid "A user with that username already exists." 48 | msgstr "Пользователь с таким именем уже существует." 49 | 50 | #: forms.py:67 51 | msgid "The two password fields didn't match." 52 | msgstr "Введенные пароли не совпадают." 53 | 54 | #: forms.py:78 55 | msgid "I have read and agree to the Terms of Service" 56 | msgstr "Я прочитал Правила Использования и согласен с ними" 57 | 58 | #: forms.py:79 59 | msgid "You must agree to the terms to register" 60 | msgstr "Для регистрации Вы должны согласиться с Правилами" 61 | 62 | #: forms.py:95 63 | msgid "" 64 | "This email address is already in use. Please supply a different email " 65 | "address." 66 | msgstr "" 67 | "Этот адрес электронной почты уже используется. Пожалуйста, введите другой " 68 | "адрес." 69 | 70 | #: forms.py:122 71 | msgid "" 72 | "Registration using free email addresses is prohibited. Please supply a " 73 | "different email address." 74 | msgstr "" 75 | "Регистрация с использованием свободных почтовых серверов запрещена. " 76 | "Пожалуйста, введите другой адрес электронной почты." 77 | 78 | #: models.py:165 79 | msgid "user" 80 | msgstr "пользователь" 81 | 82 | #: models.py:166 83 | msgid "activation key" 84 | msgstr "ключ активации" 85 | 86 | #: models.py:171 87 | msgid "registration profile" 88 | msgstr "карточка регистрации" 89 | 90 | #: models.py:172 91 | msgid "registration profiles" 92 | msgstr "карточки регистрации" 93 | -------------------------------------------------------------------------------- /registration/locale/sl/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/sl/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/sl/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: 0.8.1beta\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2009-10-12 14:09-0500\n" 11 | "PO-Revision-Date: 2009-10-23 15:49+0100\n" 12 | "Last-Translator: Domen Kožar \n" 13 | "Language-Team: Slovenian \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=utf-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | "X-Poedit-Language: Slovenian\n" 18 | "X-Poedit-Country: SLOVENIA\n" 19 | 20 | #: admin.py:23 21 | msgid "Activate users" 22 | msgstr "Aktiviraj uporabnike" 23 | 24 | #: admin.py:43 25 | msgid "Re-send activation emails" 26 | msgstr "Ponovno pošlju aktivacijske emaile" 27 | 28 | #: forms.py:35 29 | msgid "username" 30 | msgstr "uporabniško ime" 31 | 32 | #: forms.py:36 33 | msgid "This value must contain only letters, numbers and underscores." 34 | msgstr "Vrednost lahko vsebuje samo črke, cifre in podčrtaje." 35 | 36 | #: forms.py:39 37 | msgid "Email address" 38 | msgstr "Elektronska pošta" 39 | 40 | #: forms.py:41 41 | msgid "Password" 42 | msgstr "Geslo" 43 | 44 | #: forms.py:43 45 | msgid "Password (again)" 46 | msgstr "Geslo (ponovno)" 47 | 48 | #: forms.py:55 49 | msgid "A user with that username already exists." 50 | msgstr "Uporabnik z tem uporabniškim imenom že obstaja." 51 | 52 | #: forms.py:67 53 | msgid "The two password fields didn't match." 54 | msgstr "Polji z gesli se ne ujemata." 55 | 56 | #: forms.py:78 57 | msgid "I have read and agree to the Terms of Service" 58 | msgstr "Strinjam se z pogoji uporable" 59 | 60 | #: forms.py:79 61 | msgid "You must agree to the terms to register" 62 | msgstr "Za registracijo se morate strinjati z pogoji uporabe" 63 | 64 | #: forms.py:95 65 | msgid "This email address is already in use. Please supply a different email address." 66 | msgstr "Email je že v uporabi, prosimo vnesite drugega." 67 | 68 | #: forms.py:122 69 | msgid "Registration using free email addresses is prohibited. Please supply a different email address." 70 | msgstr "Registracija ni mogoča z brezplačnimi email naslovi. Prosimo vnesite drug email naslov." 71 | 72 | #: models.py:165 73 | msgid "user" 74 | msgstr "Uporabnik" 75 | 76 | #: models.py:166 77 | msgid "activation key" 78 | msgstr "Aktivacijski ključ" 79 | 80 | #: models.py:171 81 | msgid "registration profile" 82 | msgstr "Registracijski profil" 83 | 84 | #: models.py:172 85 | msgid "registration profiles" 86 | msgstr "Registracijski profili" 87 | 88 | -------------------------------------------------------------------------------- /registration/locale/sr/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/sr/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/sr/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: django-registration trunk\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2008-04-05 13:51+0200\n" 11 | "PO-Revision-Date: 2008-04-05 14:00+0100\n" 12 | "Last-Translator: Nebojsa Djordjevic \n" 13 | "Language-Team: \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" 18 | "X-Poedit-Language: Serbian\n" 19 | "X-Poedit-Country: YUGOSLAVIA\n" 20 | 21 | #: forms.py:38 22 | msgid "username" 23 | msgstr "korisničko ime" 24 | 25 | #: forms.py:41 26 | msgid "email address" 27 | msgstr "email adresa" 28 | 29 | #: forms.py:43 30 | msgid "password" 31 | msgstr "šifra" 32 | 33 | #: forms.py:45 34 | msgid "password (again)" 35 | msgstr "šifra (ponovo)" 36 | 37 | #: forms.py:54 38 | msgid "Usernames can only contain letters, numbers and underscores" 39 | msgstr "Korisničko ime može da se sastoji samo od slova, brojeva i donje crte (\"_\")" 40 | 41 | #: forms.py:59 42 | msgid "This username is already taken. Please choose another." 43 | msgstr "Korisničko ime je već zauzeto. Izaberite drugo." 44 | 45 | #: forms.py:71 46 | msgid "You must type the same password each time" 47 | msgstr "Unete šifre se ne slažu" 48 | 49 | #: forms.py:100 50 | msgid "I have read and agree to the Terms of Service" 51 | msgstr "Pročitao sam i slažem se sa uslovima korišćenja" 52 | 53 | #: forms.py:109 54 | msgid "You must agree to the terms to register" 55 | msgstr "Morate se složiti sa uslovima korišćenja da bi ste se registrovali" 56 | 57 | #: forms.py:128 58 | msgid "This email address is already in use. Please supply a different email address." 59 | msgstr "Ova e-mail adresa je već u upotrebi. Morate koristiti drugu e-mail adresu." 60 | 61 | #: forms.py:153 62 | msgid "Registration using free email addresses is prohibited. Please supply a different email address." 63 | msgstr "Registracija korišćenjem besplatnig e-mail adresa je zabranjena. Morate uneti drugu e-mail adresu." 64 | 65 | #: models.py:188 66 | msgid "user" 67 | msgstr "korisnik" 68 | 69 | #: models.py:189 70 | msgid "activation key" 71 | msgstr "aktivacioni ključ" 72 | 73 | #: models.py:194 74 | msgid "registration profile" 75 | msgstr "registracioni profil" 76 | 77 | #: models.py:195 78 | msgid "registration profiles" 79 | msgstr "registracioni profili" 80 | 81 | -------------------------------------------------------------------------------- /registration/locale/sv/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/sv/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/sv/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: PACKAGE VERSION\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2008-03-23 18:59+0100\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: Emil Stenström \n" 14 | "Language-Team: LANGUAGE \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: .\forms.py:38 20 | msgid "username" 21 | msgstr "Användarnamn" 22 | 23 | #: .\forms.py:41 24 | msgid "email address" 25 | msgstr "E-postadress" 26 | 27 | #: .\forms.py:43 28 | msgid "password" 29 | msgstr "Lösenord" 30 | 31 | #: .\forms.py:45 32 | msgid "password (again)" 33 | msgstr "Lösenord (igen)" 34 | 35 | #: .\forms.py:54 36 | msgid "Usernames can only contain letters, numbers and underscores" 37 | msgstr "Användarnamn får bara innehålla bokstäver, siffror och understreck" 38 | 39 | #: .\forms.py:59 40 | msgid "This username is already taken. Please choose another." 41 | msgstr "Det användarnamnet är upptaget. Prova ett annat." 42 | 43 | #: .\forms.py:71 44 | msgid "You must type the same password each time" 45 | msgstr "Båda lösenord måste vara lika" 46 | 47 | #: .\forms.py:100 48 | msgid "I have read and agree to the Terms of Service" 49 | msgstr "Jag har läst och accepterar avtalet" 50 | 51 | #: .\forms.py:109 52 | msgid "You must agree to the terms to register" 53 | msgstr "Du måste acceptera avtalet för att registrera dig" 54 | 55 | #: .\forms.py:128 56 | msgid "" 57 | "This email address is already in use. Please supply a different email " 58 | "address." 59 | msgstr "Den e-postadressen är upptagen, använd an annan adress." 60 | 61 | #: .\forms.py:153 62 | msgid "" 63 | "Registration using free email addresses is prohibited. Please supply a " 64 | "different email address." 65 | msgstr "Gratis e-postadresser är inte tillåtna, använd en annan adress." 66 | 67 | #: .\models.py:188 68 | msgid "user" 69 | msgstr "Användare" 70 | 71 | #: .\models.py:189 72 | msgid "activation key" 73 | msgstr "Aktiveringsnyckel" 74 | 75 | #: .\models.py:194 76 | msgid "registration profile" 77 | msgstr "Profil" 78 | 79 | #: .\models.py:195 80 | msgid "registration profiles" 81 | msgstr "Profiler" 82 | -------------------------------------------------------------------------------- /registration/locale/zh_CN/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/zh_CN/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/zh_CN/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: PACKAGE VERSION\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 11 | "PO-Revision-Date: 2008-03-20 23:22+0800\n" 12 | "Last-Translator: hutuworm \n" 13 | "Language-Team: LANGUAGE \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | 18 | #: forms.py:38 19 | msgid "username" 20 | msgstr "用户名" 21 | 22 | #: forms.py:41 23 | msgid "email address" 24 | msgstr "Email 地址" 25 | 26 | #: forms.py:43 27 | msgid "password" 28 | msgstr "密码" 29 | 30 | #: forms.py:45 31 | msgid "password (again)" 32 | msgstr "密码(重复)" 33 | 34 | #: forms.py:54 35 | msgid "Usernames can only contain letters, numbers and underscores" 36 | msgstr "用户名只能包含字母、数字和下划线" 37 | 38 | #: forms.py:59 39 | msgid "This username is already taken. Please choose another." 40 | msgstr "该用户名已被占用,请另选一个。" 41 | 42 | #: forms.py:68 43 | msgid "You must type the same password each time" 44 | msgstr "您必须输入两遍同样的密码" 45 | 46 | #: forms.py:96 47 | msgid "I have read and agree to the Terms of Service" 48 | msgstr "我已阅读并同意该服务条款" 49 | 50 | #: forms.py:105 51 | msgid "You must agree to the terms to register" 52 | msgstr "您必须同意注册条款" 53 | 54 | #: forms.py:124 55 | msgid "This email address is already in use. Please supply a different email address." 56 | msgstr "该 Email 地址已有人使用,请提供一个另外的 Email 地址。" 57 | 58 | #: forms.py:149 59 | msgid "Registration using free email addresses is prohibited. Please supply a different email address." 60 | msgstr "禁止使用免费 Email 地址注册,请提供一个另外的 Email 地址。" 61 | 62 | #: models.py:188 63 | msgid "user" 64 | msgstr "用户" 65 | 66 | #: models.py:189 67 | msgid "activation key" 68 | msgstr "激活密钥" 69 | 70 | #: models.py:194 71 | msgid "registration profile" 72 | msgstr "注册信息" 73 | 74 | #: models.py:195 75 | msgid "registration profiles" 76 | msgstr "注册信息" 77 | 78 | -------------------------------------------------------------------------------- /registration/locale/zh_TW/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/locale/zh_TW/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /registration/locale/zh_TW/LC_MESSAGES/django.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: PACKAGE VERSION\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2007-09-19 19:30-0500\n" 11 | "PO-Revision-Date: 2008-03-20 23:22+0800\n" 12 | "Last-Translator: hutuworm \n" 13 | "Language-Team: LANGUAGE \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | 18 | #: forms.py:38 19 | msgid "username" 20 | msgstr "用戶名" 21 | 22 | #: forms.py:41 23 | msgid "email address" 24 | msgstr "Email 地址" 25 | 26 | #: forms.py:43 27 | msgid "password" 28 | msgstr "密碼" 29 | 30 | #: forms.py:45 31 | msgid "password (again)" 32 | msgstr "密碼(重復)" 33 | 34 | #: forms.py:54 35 | msgid "Usernames can only contain letters, numbers and underscores" 36 | msgstr "用戶名只能包含字母、數字和下劃線" 37 | 38 | #: forms.py:59 39 | msgid "This username is already taken. Please choose another." 40 | msgstr "該用戶名已被佔用,請另選一個。" 41 | 42 | #: forms.py:68 43 | msgid "You must type the same password each time" 44 | msgstr "您必須輸入兩遍同樣的密碼" 45 | 46 | #: forms.py:96 47 | msgid "I have read and agree to the Terms of Service" 48 | msgstr "我已閱讀並同意該服務條款" 49 | 50 | #: forms.py:105 51 | msgid "You must agree to the terms to register" 52 | msgstr "您必須同意注冊條款" 53 | 54 | #: forms.py:124 55 | msgid "This email address is already in use. Please supply a different email address." 56 | msgstr "該 Email 地址已有人使用,請提供一個另外的 Email 地址。" 57 | 58 | #: forms.py:149 59 | msgid "Registration using free email addresses is prohibited. Please supply a different email address." 60 | msgstr "禁止使用免費 Email 地址注冊,請提供一個另外的 Email 地址。" 61 | 62 | #: models.py:188 63 | msgid "user" 64 | msgstr "用戶" 65 | 66 | #: models.py:189 67 | msgid "activation key" 68 | msgstr "激活密鑰" 69 | 70 | #: models.py:194 71 | msgid "registration profile" 72 | msgstr "注冊信息" 73 | 74 | #: models.py:195 75 | msgid "registration profiles" 76 | msgstr "注冊信息" 77 | 78 | -------------------------------------------------------------------------------- /registration/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/management/__init__.py -------------------------------------------------------------------------------- /registration/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nathanborror/django-registration/dc0b564b7bfb79f58592fe8ad836729a85ec17ae/registration/management/commands/__init__.py -------------------------------------------------------------------------------- /registration/management/commands/cleanupregistration.py: -------------------------------------------------------------------------------- 1 | """ 2 | A management command which deletes expired accounts (e.g., 3 | accounts which signed up but never activated) from the database. 4 | 5 | Calls ``RegistrationProfile.objects.delete_expired_users()``, which 6 | contains the actual logic for determining which accounts are deleted. 7 | 8 | """ 9 | 10 | from django.core.management.base import NoArgsCommand 11 | 12 | from registration.models import RegistrationProfile 13 | 14 | 15 | class Command(NoArgsCommand): 16 | help = "Delete expired user registrations from the database" 17 | 18 | def handle_noargs(self, **options): 19 | RegistrationProfile.objects.delete_expired_users() 20 | -------------------------------------------------------------------------------- /registration/models.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import random 3 | import re 4 | 5 | from django.conf import settings 6 | from django.contrib.auth.models import User 7 | from django.db import models 8 | from django.db import transaction 9 | from django.template.loader import render_to_string 10 | from django.utils.hashcompat import sha_constructor 11 | from django.utils.translation import ugettext_lazy as _ 12 | 13 | 14 | SHA1_RE = re.compile('^[a-f0-9]{40}$') 15 | 16 | 17 | class RegistrationManager(models.Manager): 18 | """ 19 | Custom manager for the ``RegistrationProfile`` model. 20 | 21 | The methods defined here provide shortcuts for account creation 22 | and activation (including generation and emailing of activation 23 | keys), and for cleaning out expired inactive accounts. 24 | 25 | """ 26 | def activate_user(self, activation_key): 27 | """ 28 | Validate an activation key and activate the corresponding 29 | ``User`` if valid. 30 | 31 | If the key is valid and has not expired, return the ``User`` 32 | after activating. 33 | 34 | If the key is not valid or has expired, return ``False``. 35 | 36 | If the key is valid but the ``User`` is already active, 37 | return ``False``. 38 | 39 | To prevent reactivation of an account which has been 40 | deactivated by site administrators, the activation key is 41 | reset to the string constant ``RegistrationProfile.ACTIVATED`` 42 | after successful activation. 43 | 44 | """ 45 | # Make sure the key we're trying conforms to the pattern of a 46 | # SHA1 hash; if it doesn't, no point trying to look it up in 47 | # the database. 48 | if SHA1_RE.search(activation_key): 49 | try: 50 | profile = self.get(activation_key=activation_key) 51 | except self.model.DoesNotExist: 52 | return False 53 | if not profile.activation_key_expired(): 54 | user = profile.user 55 | user.is_active = True 56 | user.save() 57 | profile.activation_key = self.model.ACTIVATED 58 | profile.save() 59 | return user 60 | return False 61 | 62 | def create_inactive_user(self, username, email, password, 63 | site, send_email=True): 64 | """ 65 | Create a new, inactive ``User``, generate a 66 | ``RegistrationProfile`` and email its activation key to the 67 | ``User``, returning the new ``User``. 68 | 69 | By default, an activation email will be sent to the new 70 | user. To disable this, pass ``send_email=False``. 71 | 72 | """ 73 | new_user = User.objects.create_user(username, email, password) 74 | new_user.is_active = False 75 | new_user.save() 76 | 77 | registration_profile = self.create_profile(new_user) 78 | 79 | if send_email: 80 | registration_profile.send_activation_email(site) 81 | 82 | return new_user 83 | create_inactive_user = transaction.commit_on_success(create_inactive_user) 84 | 85 | def create_profile(self, user): 86 | """ 87 | Create a ``RegistrationProfile`` for a given 88 | ``User``, and return the ``RegistrationProfile``. 89 | 90 | The activation key for the ``RegistrationProfile`` will be a 91 | SHA1 hash, generated from a combination of the ``User``'s 92 | username and a random salt. 93 | 94 | """ 95 | salt = sha_constructor(str(random.random())).hexdigest()[:5] 96 | username = user.username 97 | if isinstance(username, unicode): 98 | username = username.encode('utf-8') 99 | activation_key = sha_constructor(salt+username).hexdigest() 100 | return self.create(user=user, 101 | activation_key=activation_key) 102 | 103 | def delete_expired_users(self): 104 | """ 105 | Remove expired instances of ``RegistrationProfile`` and their 106 | associated ``User``s. 107 | 108 | Accounts to be deleted are identified by searching for 109 | instances of ``RegistrationProfile`` with expired activation 110 | keys, and then checking to see if their associated ``User`` 111 | instances have the field ``is_active`` set to ``False``; any 112 | ``User`` who is both inactive and has an expired activation 113 | key will be deleted. 114 | 115 | It is recommended that this method be executed regularly as 116 | part of your routine site maintenance; this application 117 | provides a custom management command which will call this 118 | method, accessible as ``manage.py cleanupregistration``. 119 | 120 | Regularly clearing out accounts which have never been 121 | activated serves two useful purposes: 122 | 123 | 1. It alleviates the ocasional need to reset a 124 | ``RegistrationProfile`` and/or re-send an activation email 125 | when a user does not receive or does not act upon the 126 | initial activation email; since the account will be 127 | deleted, the user will be able to simply re-register and 128 | receive a new activation key. 129 | 130 | 2. It prevents the possibility of a malicious user registering 131 | one or more accounts and never activating them (thus 132 | denying the use of those usernames to anyone else); since 133 | those accounts will be deleted, the usernames will become 134 | available for use again. 135 | 136 | If you have a troublesome ``User`` and wish to disable their 137 | account while keeping it in the database, simply delete the 138 | associated ``RegistrationProfile``; an inactive ``User`` which 139 | does not have an associated ``RegistrationProfile`` will not 140 | be deleted. 141 | 142 | """ 143 | for profile in self.all(): 144 | if profile.activation_key_expired(): 145 | user = profile.user 146 | if not user.is_active: 147 | user.delete() 148 | 149 | 150 | class RegistrationProfile(models.Model): 151 | """ 152 | A simple profile which stores an activation key for use during 153 | user account registration. 154 | 155 | Generally, you will not want to interact directly with instances 156 | of this model; the provided manager includes methods 157 | for creating and activating new accounts, as well as for cleaning 158 | out accounts which have never been activated. 159 | 160 | While it is possible to use this model as the value of the 161 | ``AUTH_PROFILE_MODULE`` setting, it's not recommended that you do 162 | so. This model's sole purpose is to store data temporarily during 163 | account registration and activation. 164 | 165 | """ 166 | ACTIVATED = u"ALREADY_ACTIVATED" 167 | 168 | user = models.ForeignKey(User, unique=True, verbose_name=_('user')) 169 | activation_key = models.CharField(_('activation key'), max_length=40) 170 | 171 | objects = RegistrationManager() 172 | 173 | class Meta: 174 | verbose_name = _('registration profile') 175 | verbose_name_plural = _('registration profiles') 176 | 177 | def __unicode__(self): 178 | return u"Registration information for %s" % self.user 179 | 180 | def activation_key_expired(self): 181 | """ 182 | Determine whether this ``RegistrationProfile``'s activation 183 | key has expired, returning a boolean -- ``True`` if the key 184 | has expired. 185 | 186 | Key expiration is determined by a two-step process: 187 | 188 | 1. If the user has already activated, the key will have been 189 | reset to the string constant ``ACTIVATED``. Re-activating 190 | is not permitted, and so this method returns ``True`` in 191 | this case. 192 | 193 | 2. Otherwise, the date the user signed up is incremented by 194 | the number of days specified in the setting 195 | ``ACCOUNT_ACTIVATION_DAYS`` (which should be the number of 196 | days after signup during which a user is allowed to 197 | activate their account); if the result is less than or 198 | equal to the current date, the key has expired and this 199 | method returns ``True``. 200 | 201 | """ 202 | expiration_date = datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS) 203 | return self.activation_key == self.ACTIVATED or \ 204 | (self.user.date_joined + expiration_date <= datetime.datetime.now()) 205 | activation_key_expired.boolean = True 206 | 207 | def send_activation_email(self, site): 208 | """ 209 | Send an activation email to the user associated with this 210 | ``RegistrationProfile``. 211 | 212 | The activation email will make use of two templates: 213 | 214 | ``registration/activation_email_subject.txt`` 215 | This template will be used for the subject line of the 216 | email. Because it is used as the subject line of an email, 217 | this template's output **must** be only a single line of 218 | text; output longer than one line will be forcibly joined 219 | into only a single line. 220 | 221 | ``registration/activation_email.txt`` 222 | This template will be used for the body of the email. 223 | 224 | These templates will each receive the following context 225 | variables: 226 | 227 | ``activation_key`` 228 | The activation key for the new account. 229 | 230 | ``expiration_days`` 231 | The number of days remaining during which the account may 232 | be activated. 233 | 234 | ``site`` 235 | An object representing the site on which the user 236 | registered; depending on whether ``django.contrib.sites`` 237 | is installed, this may be an instance of either 238 | ``django.contrib.sites.models.Site`` (if the sites 239 | application is installed) or 240 | ``django.contrib.sites.models.RequestSite`` (if 241 | not). Consult the documentation for the Django sites 242 | framework for details regarding these objects' interfaces. 243 | 244 | """ 245 | ctx_dict = {'activation_key': self.activation_key, 246 | 'expiration_days': settings.ACCOUNT_ACTIVATION_DAYS, 247 | 'site': site} 248 | subject = render_to_string('registration/activation_email_subject.txt', 249 | ctx_dict) 250 | # Email subject *must not* contain newlines 251 | subject = ''.join(subject.splitlines()) 252 | 253 | message = render_to_string('registration/activation_email.txt', 254 | ctx_dict) 255 | 256 | self.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL) 257 | 258 | -------------------------------------------------------------------------------- /registration/signals.py: -------------------------------------------------------------------------------- 1 | from django.dispatch import Signal 2 | 3 | 4 | # A new user has registered. 5 | user_registered = Signal(providing_args=["user", "request"]) 6 | 7 | # A user has activated his or her account. 8 | user_activated = Signal(providing_args=["user", "request"]) 9 | -------------------------------------------------------------------------------- /registration/templates/base.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | {% block title %}{% endblock %} 8 | 9 | 10 |
11 | {% block body %} 12 |
13 | {% block content_title %}{% endblock %} 14 |
15 |
16 | {% block content %}{% endblock %} 17 |
18 | {% endblock %} 19 |
20 | 21 | -------------------------------------------------------------------------------- /registration/templates/registration/activate.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base_registration.html" %} 2 | 3 | 4 | {% block title %}Account activation error{% endblock %} 5 | {% block body_class %}{{ block.super }} registration_activate{% endblock %} 6 | 7 | 8 | {% block content_title %} 9 |

Account activation error

10 | {% endblock %} 11 | 12 | 13 | {% block content %} 14 |

The activation key "{{ activation_key }}" is invalid and cannot be used to activate this account.

15 | {% endblock %} -------------------------------------------------------------------------------- /registration/templates/registration/activation_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base_registration.html" %} 2 | 3 | 4 | {% block title %}Account activation complete{% endblock %} 5 | {% block body_class %}{{ block.super }} registration_activation_complete{% endblock %} 6 | 7 | 8 | {% block content_title %} 9 |

Account activation complete

10 | {% endblock %} 11 | 12 | 13 | {% block content %} 14 |

Congratulations, your account has been activated.

15 | {% endblock %} -------------------------------------------------------------------------------- /registration/templates/registration/activation_email.txt: -------------------------------------------------------------------------------- 1 | Thank you for registering an account at {{ site.domain }}. 2 | To activate your registration, please visit the following page: 3 | 4 | http://{{ site.domain }}{% url registration_activate activation_key %} 5 | 6 | This page will expire in {{ expiration_days }} day{{ expiration_days|pluralize }}. 7 | 8 | *** 9 | 10 | If you didn't register this account you can simply delete this email and we won't bother you again. -------------------------------------------------------------------------------- /registration/templates/registration/activation_email_subject.txt: -------------------------------------------------------------------------------- 1 | {{ site.name }} - activate your account -------------------------------------------------------------------------------- /registration/templates/registration/base_registration.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | 4 | {% block title %}Registration{% endblock %} 5 | {% block body_class %}{{ block.super }} registration{% endblock %} -------------------------------------------------------------------------------- /registration/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base_registration.html" %} 2 | 3 | 4 | {% block title %}Log in{% endblock %} 5 | {% block body_class %}{{ block.super }} login_form{% endblock %} 6 | 7 | 8 | {% block content_title %} 9 |

Log in

10 | {% endblock %} 11 | 12 | 13 | {% block content %} 14 | 19 | {% endblock %} -------------------------------------------------------------------------------- /registration/templates/registration/logout.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base_registration.html" %} 2 | 3 | 4 | {% block title %}Logged out{% endblock %} 5 | {% block body_class %}{{ block.super }} logout{% endblock %} 6 | 7 | 8 | {% block content_title %} 9 |

Logged out

10 |

You have been logged out.

11 | {% endblock %} 12 | 13 | 14 | {% block content %} 15 | 21 | {% endblock %} -------------------------------------------------------------------------------- /registration/templates/registration/registration_closed.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base_registration.html" %} 2 | 3 | 4 | {% block title %}Registration closed{% endblock %} 5 | {% block body_class %}{{ block.super }} registration_closed{% endblock %} 6 | 7 | 8 | {% block content_title %} 9 |

Registration closed

10 | {% endblock %} 11 | 12 | 13 | {% block content %} 14 |

Please try registering again.

15 | {% endblock %} -------------------------------------------------------------------------------- /registration/templates/registration/registration_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base_registration.html" %} 2 | 3 | 4 | {% block title %}Registration complete{% endblock %} 5 | {% block body_class %}{{ block.super }} registration_complete{% endblock %} 6 | 7 | 8 | {% block content_title %} 9 |

Registration complete

10 | {% endblock %} 11 | 12 | 13 | {% block content %} 14 |

Activate your account

15 |

We will be sending you an email with an activation link which you'll need to click to verify this account. If you choose not to activate your account it will eventually become disabled.

16 |

Check your email.

17 | {% endblock %} -------------------------------------------------------------------------------- /registration/templates/registration/registration_form.html: -------------------------------------------------------------------------------- 1 | {% extends "registration/base_registration.html" %} 2 | 3 | 4 | {% block title %}Register for an account{% endblock %} 5 | {% block body_class %}{{ block.super }} registration_form{% endblock %} 6 | 7 | 8 | {% block content_title %} 9 |

Register for an account

10 | {% endblock %} 11 | 12 | 13 | {% block content %} 14 |
{% csrf_token %} 15 | {{ form.as_p }} 16 |

17 |
18 | {% endblock %} -------------------------------------------------------------------------------- /registration/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | import registration 4 | 5 | from registration.tests.backends import * 6 | from registration.tests.forms import * 7 | from registration.tests.models import * 8 | from registration.tests.views import * 9 | 10 | 11 | class RegistrationVersionInfoTests(TestCase): 12 | """ 13 | Test django-registration's internal version-reporting 14 | infrastructure. 15 | 16 | """ 17 | def setUp(self): 18 | self.version = registration.VERSION 19 | 20 | def tearDown(self): 21 | registration.VERSION = self.version 22 | 23 | def test_get_version(self): 24 | """ 25 | Test the version-info reporting. 26 | 27 | """ 28 | versions = [ 29 | {'version': (1, 0, 0, 'alpha', 0), 30 | 'expected': "1.0 pre-alpha"}, 31 | {'version': (1, 0, 1, 'alpha', 1), 32 | 'expected': "1.0.1 alpha 1"}, 33 | {'version': (1, 1, 0, 'beta', 2), 34 | 'expected': "1.1 beta 2"}, 35 | {'version': (1, 2, 1, 'rc', 3), 36 | 'expected': "1.2.1 rc 3"}, 37 | {'version': (1, 3, 0, 'final', 0), 38 | 'expected': "1.3"}, 39 | {'version': (1, 4, 1, 'beta', 0), 40 | 'expected': "1.4.1 beta"}, 41 | ] 42 | 43 | for version_dict in versions: 44 | registration.VERSION = version_dict['version'] 45 | self.assertEqual(registration.get_version(), version_dict['expected']) 46 | -------------------------------------------------------------------------------- /registration/tests/forms.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import User 2 | from django.test import TestCase 3 | 4 | from registration import forms 5 | 6 | 7 | class RegistrationFormTests(TestCase): 8 | """ 9 | Test the default registration forms. 10 | 11 | """ 12 | def test_registration_form(self): 13 | """ 14 | Test that ``RegistrationForm`` enforces username constraints 15 | and matching passwords. 16 | 17 | """ 18 | # Create a user so we can verify that duplicate usernames aren't 19 | # permitted. 20 | User.objects.create_user('alice', 'alice@example.com', 'secret') 21 | 22 | invalid_data_dicts = [ 23 | # Non-alphanumeric username. 24 | {'data': {'username': 'foo/bar', 25 | 'email': 'foo@example.com', 26 | 'password1': 'foo', 27 | 'password2': 'foo'}, 28 | 'error': ('username', [u"This value must contain only letters, numbers and underscores."])}, 29 | # Already-existing username. 30 | {'data': {'username': 'alice', 31 | 'email': 'alice@example.com', 32 | 'password1': 'secret', 33 | 'password2': 'secret'}, 34 | 'error': ('username', [u"A user with that username already exists."])}, 35 | # Mismatched passwords. 36 | {'data': {'username': 'foo', 37 | 'email': 'foo@example.com', 38 | 'password1': 'foo', 39 | 'password2': 'bar'}, 40 | 'error': ('__all__', [u"The two password fields didn't match."])}, 41 | ] 42 | 43 | for invalid_dict in invalid_data_dicts: 44 | form = forms.RegistrationForm(data=invalid_dict['data']) 45 | self.failIf(form.is_valid()) 46 | self.assertEqual(form.errors[invalid_dict['error'][0]], 47 | invalid_dict['error'][1]) 48 | 49 | form = forms.RegistrationForm(data={'username': 'foo', 50 | 'email': 'foo@example.com', 51 | 'password1': 'foo', 52 | 'password2': 'foo'}) 53 | self.failUnless(form.is_valid()) 54 | 55 | def test_registration_form_tos(self): 56 | """ 57 | Test that ``RegistrationFormTermsOfService`` requires 58 | agreement to the terms of service. 59 | 60 | """ 61 | form = forms.RegistrationFormTermsOfService(data={'username': 'foo', 62 | 'email': 'foo@example.com', 63 | 'password1': 'foo', 64 | 'password2': 'foo'}) 65 | self.failIf(form.is_valid()) 66 | self.assertEqual(form.errors['tos'], 67 | [u"You must agree to the terms to register"]) 68 | 69 | form = forms.RegistrationFormTermsOfService(data={'username': 'foo', 70 | 'email': 'foo@example.com', 71 | 'password1': 'foo', 72 | 'password2': 'foo', 73 | 'tos': 'on'}) 74 | self.failUnless(form.is_valid()) 75 | 76 | def test_registration_form_unique_email(self): 77 | """ 78 | Test that ``RegistrationFormUniqueEmail`` validates uniqueness 79 | of email addresses. 80 | 81 | """ 82 | # Create a user so we can verify that duplicate addresses 83 | # aren't permitted. 84 | User.objects.create_user('alice', 'alice@example.com', 'secret') 85 | 86 | form = forms.RegistrationFormUniqueEmail(data={'username': 'foo', 87 | 'email': 'alice@example.com', 88 | 'password1': 'foo', 89 | 'password2': 'foo'}) 90 | self.failIf(form.is_valid()) 91 | self.assertEqual(form.errors['email'], 92 | [u"This email address is already in use. Please supply a different email address."]) 93 | 94 | form = forms.RegistrationFormUniqueEmail(data={'username': 'foo', 95 | 'email': 'foo@example.com', 96 | 'password1': 'foo', 97 | 'password2': 'foo'}) 98 | self.failUnless(form.is_valid()) 99 | 100 | def test_registration_form_no_free_email(self): 101 | """ 102 | Test that ``RegistrationFormNoFreeEmail`` disallows 103 | registration with free email addresses. 104 | 105 | """ 106 | base_data = {'username': 'foo', 107 | 'password1': 'foo', 108 | 'password2': 'foo'} 109 | for domain in forms.RegistrationFormNoFreeEmail.bad_domains: 110 | invalid_data = base_data.copy() 111 | invalid_data['email'] = u"foo@%s" % domain 112 | form = forms.RegistrationFormNoFreeEmail(data=invalid_data) 113 | self.failIf(form.is_valid()) 114 | self.assertEqual(form.errors['email'], 115 | [u"Registration using free email addresses is prohibited. Please supply a different email address."]) 116 | 117 | base_data['email'] = 'foo@example.com' 118 | form = forms.RegistrationFormNoFreeEmail(data=base_data) 119 | self.failUnless(form.is_valid()) 120 | -------------------------------------------------------------------------------- /registration/tests/models.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import re 3 | 4 | from django.conf import settings 5 | from django.contrib.auth.models import User 6 | from django.contrib.sites.models import Site 7 | from django.core import mail 8 | from django.core import management 9 | from django.test import TestCase 10 | from django.utils.hashcompat import sha_constructor 11 | 12 | from registration.models import RegistrationProfile 13 | 14 | 15 | class RegistrationModelTests(TestCase): 16 | """ 17 | Test the model and manager used in the default backend. 18 | 19 | """ 20 | user_info = {'username': 'alice', 21 | 'password': 'swordfish', 22 | 'email': 'alice@example.com'} 23 | 24 | def setUp(self): 25 | self.old_activation = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', None) 26 | settings.ACCOUNT_ACTIVATION_DAYS = 7 27 | 28 | def tearDown(self): 29 | settings.ACCOUNT_ACTIVATION_DAYS = self.old_activation 30 | 31 | def test_profile_creation(self): 32 | """ 33 | Creating a registration profile for a user populates the 34 | profile with the correct user and a SHA1 hash to use as 35 | activation key. 36 | 37 | """ 38 | new_user = User.objects.create_user(**self.user_info) 39 | profile = RegistrationProfile.objects.create_profile(new_user) 40 | 41 | self.assertEqual(RegistrationProfile.objects.count(), 1) 42 | self.assertEqual(profile.user.id, new_user.id) 43 | self.failUnless(re.match('^[a-f0-9]{40}$', profile.activation_key)) 44 | self.assertEqual(unicode(profile), 45 | "Registration information for alice") 46 | 47 | def test_activation_email(self): 48 | """ 49 | ``RegistrationProfile.send_activation_email`` sends an 50 | email. 51 | 52 | """ 53 | new_user = User.objects.create_user(**self.user_info) 54 | profile = RegistrationProfile.objects.create_profile(new_user) 55 | profile.send_activation_email(Site.objects.get_current()) 56 | self.assertEqual(len(mail.outbox), 1) 57 | self.assertEqual(mail.outbox[0].to, [self.user_info['email']]) 58 | 59 | def test_user_creation(self): 60 | """ 61 | Creating a new user populates the correct data, and sets the 62 | user's account inactive. 63 | 64 | """ 65 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 66 | **self.user_info) 67 | self.assertEqual(new_user.username, 'alice') 68 | self.assertEqual(new_user.email, 'alice@example.com') 69 | self.failUnless(new_user.check_password('swordfish')) 70 | self.failIf(new_user.is_active) 71 | 72 | def test_user_creation_email(self): 73 | """ 74 | By default, creating a new user sends an activation email. 75 | 76 | """ 77 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 78 | **self.user_info) 79 | self.assertEqual(len(mail.outbox), 1) 80 | 81 | def test_user_creation_no_email(self): 82 | """ 83 | Passing ``send_email=False`` when creating a new user will not 84 | send an activation email. 85 | 86 | """ 87 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 88 | send_email=False, 89 | **self.user_info) 90 | self.assertEqual(len(mail.outbox), 0) 91 | 92 | def test_unexpired_account(self): 93 | """ 94 | ``RegistrationProfile.activation_key_expired()`` is ``False`` 95 | within the activation window. 96 | 97 | """ 98 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 99 | **self.user_info) 100 | profile = RegistrationProfile.objects.get(user=new_user) 101 | self.failIf(profile.activation_key_expired()) 102 | 103 | def test_expired_account(self): 104 | """ 105 | ``RegistrationProfile.activation_key_expired()`` is ``True`` 106 | outside the activation window. 107 | 108 | """ 109 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 110 | **self.user_info) 111 | new_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1) 112 | new_user.save() 113 | profile = RegistrationProfile.objects.get(user=new_user) 114 | self.failUnless(profile.activation_key_expired()) 115 | 116 | def test_valid_activation(self): 117 | """ 118 | Activating a user within the permitted window makes the 119 | account active, and resets the activation key. 120 | 121 | """ 122 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 123 | **self.user_info) 124 | profile = RegistrationProfile.objects.get(user=new_user) 125 | activated = RegistrationProfile.objects.activate_user(profile.activation_key) 126 | 127 | self.failUnless(isinstance(activated, User)) 128 | self.assertEqual(activated.id, new_user.id) 129 | self.failUnless(activated.is_active) 130 | 131 | profile = RegistrationProfile.objects.get(user=new_user) 132 | self.assertEqual(profile.activation_key, RegistrationProfile.ACTIVATED) 133 | 134 | def test_expired_activation(self): 135 | """ 136 | Attempting to activate outside the permitted window does not 137 | activate the account. 138 | 139 | """ 140 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 141 | **self.user_info) 142 | new_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1) 143 | new_user.save() 144 | 145 | profile = RegistrationProfile.objects.get(user=new_user) 146 | activated = RegistrationProfile.objects.activate_user(profile.activation_key) 147 | 148 | self.failIf(isinstance(activated, User)) 149 | self.failIf(activated) 150 | 151 | new_user = User.objects.get(username='alice') 152 | self.failIf(new_user.is_active) 153 | 154 | profile = RegistrationProfile.objects.get(user=new_user) 155 | self.assertNotEqual(profile.activation_key, RegistrationProfile.ACTIVATED) 156 | 157 | def test_activation_invalid_key(self): 158 | """ 159 | Attempting to activate with a key which is not a SHA1 hash 160 | fails. 161 | 162 | """ 163 | self.failIf(RegistrationProfile.objects.activate_user('foo')) 164 | 165 | def test_activation_already_activated(self): 166 | """ 167 | Attempting to re-activate an already-activated account fails. 168 | 169 | """ 170 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 171 | **self.user_info) 172 | profile = RegistrationProfile.objects.get(user=new_user) 173 | RegistrationProfile.objects.activate_user(profile.activation_key) 174 | 175 | profile = RegistrationProfile.objects.get(user=new_user) 176 | self.failIf(RegistrationProfile.objects.activate_user(profile.activation_key)) 177 | 178 | def test_activation_nonexistent_key(self): 179 | """ 180 | Attempting to activate with a non-existent key (i.e., one not 181 | associated with any account) fails. 182 | 183 | """ 184 | # Due to the way activation keys are constructed during 185 | # registration, this will never be a valid key. 186 | invalid_key = sha_constructor('foo').hexdigest() 187 | self.failIf(RegistrationProfile.objects.activate_user(invalid_key)) 188 | 189 | def test_expired_user_deletion(self): 190 | """ 191 | ``RegistrationProfile.objects.delete_expired_users()`` only 192 | deletes inactive users whose activation window has expired. 193 | 194 | """ 195 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 196 | **self.user_info) 197 | expired_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 198 | username='bob', 199 | password='secret', 200 | email='bob@example.com') 201 | expired_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1) 202 | expired_user.save() 203 | 204 | RegistrationProfile.objects.delete_expired_users() 205 | self.assertEqual(RegistrationProfile.objects.count(), 1) 206 | self.assertRaises(User.DoesNotExist, User.objects.get, username='bob') 207 | 208 | def test_management_command(self): 209 | """ 210 | The ``cleanupregistration`` management command properly 211 | deletes expired accounts. 212 | 213 | """ 214 | new_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 215 | **self.user_info) 216 | expired_user = RegistrationProfile.objects.create_inactive_user(site=Site.objects.get_current(), 217 | username='bob', 218 | password='secret', 219 | email='bob@example.com') 220 | expired_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1) 221 | expired_user.save() 222 | 223 | management.call_command('cleanupregistration') 224 | self.assertEqual(RegistrationProfile.objects.count(), 1) 225 | self.assertRaises(User.DoesNotExist, User.objects.get, username='bob') 226 | -------------------------------------------------------------------------------- /registration/tests/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | URLs used in the unit tests for django-registration. 3 | 4 | You should not attempt to use these URLs in any sort of real or 5 | development environment; instead, use 6 | ``registration/backends/default/urls.py``. This URLconf includes those 7 | URLs, and also adds several additional URLs which serve no purpose 8 | other than to test that optional keyword arguments are properly 9 | handled. 10 | 11 | """ 12 | 13 | from django.conf.urls.defaults import * 14 | from django.views.generic.simple import direct_to_template 15 | 16 | from registration.views import activate 17 | from registration.views import register 18 | 19 | 20 | urlpatterns = patterns('', 21 | # Test the 'activate' view with custom template 22 | # name. 23 | url(r'^activate-with-template-name/(?P\w+)/$', 24 | activate, 25 | {'template_name': 'registration/test_template_name.html', 26 | 'backend': 'registration.backends.default.DefaultBackend'}, 27 | name='registration_test_activate_template_name'), 28 | # Test the 'activate' view with 29 | # extra_context_argument. 30 | url(r'^activate-extra-context/(?P\w+)/$', 31 | activate, 32 | {'extra_context': {'foo': 'bar', 'callable': lambda: 'called'}, 33 | 'backend': 'registration.backends.default.DefaultBackend'}, 34 | name='registration_test_activate_extra_context'), 35 | # Test the 'activate' view with success_url argument. 36 | url(r'^activate-with-success-url/(?P\w+)/$', 37 | activate, 38 | {'success_url': 'registration_test_custom_success_url', 39 | 'backend': 'registration.backends.default.DefaultBackend'}, 40 | name='registration_test_activate_success_url'), 41 | # Test the 'register' view with custom template 42 | # name. 43 | url(r'^register-with-template-name/$', 44 | register, 45 | {'template_name': 'registration/test_template_name.html', 46 | 'backend': 'registration.backends.default.DefaultBackend'}, 47 | name='registration_test_register_template_name'), 48 | # Test the'register' view with extra_context 49 | # argument. 50 | url(r'^register-extra-context/$', 51 | register, 52 | {'extra_context': {'foo': 'bar', 'callable': lambda: 'called'}, 53 | 'backend': 'registration.backends.default.DefaultBackend'}, 54 | name='registration_test_register_extra_context'), 55 | # Test the 'register' view with custom URL for 56 | # closed registration. 57 | url(r'^register-with-disallowed-url/$', 58 | register, 59 | {'disallowed_url': 'registration_test_custom_disallowed', 60 | 'backend': 'registration.backends.default.DefaultBackend'}, 61 | name='registration_test_register_disallowed_url'), 62 | # Set up a pattern which will correspond to the 63 | # custom 'disallowed_url' above. 64 | url(r'^custom-disallowed/$', 65 | direct_to_template, 66 | {'template': 'registration/registration_closed.html'}, 67 | name='registration_test_custom_disallowed'), 68 | # Test the 'register' view with custom redirect 69 | # on successful registration. 70 | url(r'^register-with-success_url/$', 71 | register, 72 | {'success_url': 'registration_test_custom_success_url', 73 | 'backend': 'registration.backends.default.DefaultBackend'}, 74 | name='registration_test_register_success_url' 75 | ), 76 | # Pattern for custom redirect set above. 77 | url(r'^custom-success/$', 78 | direct_to_template, 79 | {'template': 'registration/test_template_name.html'}, 80 | name='registration_test_custom_success_url'), 81 | (r'', include('registration.backends.default.urls')), 82 | ) 83 | -------------------------------------------------------------------------------- /registration/urls.py: -------------------------------------------------------------------------------- 1 | """ 2 | Backwards-compatible URLconf for existing django-registration 3 | installs; this allows the standard ``include('registration.urls')`` to 4 | continue working, but that usage is deprecated and will be removed for 5 | django-registration 1.0. For new installs, use 6 | ``include('registration.backends.default.urls')``. 7 | 8 | """ 9 | 10 | import warnings 11 | 12 | warnings.warn("include('registration.urls') is deprecated; use include('registration.backends.default.urls') instead.", 13 | PendingDeprecationWarning) 14 | 15 | from registration.backends.default.urls import * 16 | -------------------------------------------------------------------------------- /registration/views.py: -------------------------------------------------------------------------------- 1 | """ 2 | Views which allow users to create and activate accounts. 3 | 4 | """ 5 | 6 | 7 | from django.shortcuts import redirect 8 | from django.shortcuts import render_to_response 9 | from django.template import RequestContext 10 | 11 | from registration.backends import get_backend 12 | 13 | 14 | def activate(request, backend, 15 | template_name='registration/activate.html', 16 | success_url=None, extra_context=None, **kwargs): 17 | """ 18 | Activate a user's account. 19 | 20 | The actual activation of the account will be delegated to the 21 | backend specified by the ``backend`` keyword argument (see below); 22 | the backend's ``activate()`` method will be called, passing any 23 | keyword arguments captured from the URL, and will be assumed to 24 | return a ``User`` if activation was successful, or a value which 25 | evaluates to ``False`` in boolean context if not. 26 | 27 | Upon successful activation, the backend's 28 | ``post_activation_redirect()`` method will be called, passing the 29 | ``HttpRequest`` and the activated ``User`` to determine the URL to 30 | redirect the user to. To override this, pass the argument 31 | ``success_url`` (see below). 32 | 33 | On unsuccessful activation, will render the template 34 | ``registration/activate.html`` to display an error message; to 35 | override thise, pass the argument ``template_name`` (see below). 36 | 37 | **Arguments** 38 | 39 | ``backend`` 40 | The dotted Python import path to the backend class to 41 | use. Required. 42 | 43 | ``extra_context`` 44 | A dictionary of variables to add to the template context. Any 45 | callable object in this dictionary will be called to produce 46 | the end result which appears in the context. Optional. 47 | 48 | ``success_url`` 49 | The name of a URL pattern to redirect to on successful 50 | acivation. This is optional; if not specified, this will be 51 | obtained by calling the backend's 52 | ``post_activation_redirect()`` method. 53 | 54 | ``template_name`` 55 | A custom template to use. This is optional; if not specified, 56 | this will default to ``registration/activate.html``. 57 | 58 | ``\*\*kwargs`` 59 | Any keyword arguments captured from the URL, such as an 60 | activation key, which will be passed to the backend's 61 | ``activate()`` method. 62 | 63 | **Context:** 64 | 65 | The context will be populated from the keyword arguments captured 66 | in the URL, and any extra variables supplied in the 67 | ``extra_context`` argument (see above). 68 | 69 | **Template:** 70 | 71 | registration/activate.html or ``template_name`` keyword argument. 72 | 73 | """ 74 | backend = get_backend(backend) 75 | account = backend.activate(request, **kwargs) 76 | 77 | if account: 78 | if success_url is None: 79 | to, args, kwargs = backend.post_activation_redirect(request, account) 80 | return redirect(to, *args, **kwargs) 81 | else: 82 | return redirect(success_url) 83 | 84 | if extra_context is None: 85 | extra_context = {} 86 | context = RequestContext(request) 87 | for key, value in extra_context.items(): 88 | context[key] = callable(value) and value() or value 89 | 90 | return render_to_response(template_name, 91 | kwargs, 92 | context_instance=context) 93 | 94 | 95 | def register(request, backend, success_url=None, form_class=None, 96 | disallowed_url='registration_disallowed', 97 | template_name='registration/registration_form.html', 98 | extra_context=None): 99 | """ 100 | Allow a new user to register an account. 101 | 102 | The actual registration of the account will be delegated to the 103 | backend specified by the ``backend`` keyword argument (see below); 104 | it will be used as follows: 105 | 106 | 1. The backend's ``registration_allowed()`` method will be called, 107 | passing the ``HttpRequest``, to determine whether registration 108 | of an account is to be allowed; if not, a redirect is issued to 109 | the view corresponding to the named URL pattern 110 | ``registration_disallowed``. To override this, see the list of 111 | optional arguments for this view (below). 112 | 113 | 2. The form to use for account registration will be obtained by 114 | calling the backend's ``get_form_class()`` method, passing the 115 | ``HttpRequest``. To override this, see the list of optional 116 | arguments for this view (below). 117 | 118 | 3. If valid, the form's ``cleaned_data`` will be passed (as 119 | keyword arguments, and along with the ``HttpRequest``) to the 120 | backend's ``register()`` method, which should return the new 121 | ``User`` object. 122 | 123 | 4. Upon successful registration, the backend's 124 | ``post_registration_redirect()`` method will be called, passing 125 | the ``HttpRequest`` and the new ``User``, to determine the URL 126 | to redirect the user to. To override this, see the list of 127 | optional arguments for this view (below). 128 | 129 | **Required arguments** 130 | 131 | None. 132 | 133 | **Optional arguments** 134 | 135 | ``backend`` 136 | The dotted Python import path to the backend class to use. 137 | 138 | ``disallowed_url`` 139 | URL to redirect to if registration is not permitted for the 140 | current ``HttpRequest``. Must be a value which can legally be 141 | passed to ``django.shortcuts.redirect``. If not supplied, this 142 | will be whatever URL corresponds to the named URL pattern 143 | ``registration_disallowed``. 144 | 145 | ``form_class`` 146 | The form class to use for registration. If not supplied, this 147 | will be retrieved from the registration backend. 148 | 149 | ``extra_context`` 150 | A dictionary of variables to add to the template context. Any 151 | callable object in this dictionary will be called to produce 152 | the end result which appears in the context. 153 | 154 | ``success_url`` 155 | URL to redirect to after successful registration. Must be a 156 | value which can legally be passed to 157 | ``django.shortcuts.redirect``. If not supplied, this will be 158 | retrieved from the registration backend. 159 | 160 | ``template_name`` 161 | A custom template to use. If not supplied, this will default 162 | to ``registration/registration_form.html``. 163 | 164 | **Context:** 165 | 166 | ``form`` 167 | The registration form. 168 | 169 | Any extra variables supplied in the ``extra_context`` argument 170 | (see above). 171 | 172 | **Template:** 173 | 174 | registration/registration_form.html or ``template_name`` keyword 175 | argument. 176 | 177 | """ 178 | backend = get_backend(backend) 179 | if not backend.registration_allowed(request): 180 | return redirect(disallowed_url) 181 | if form_class is None: 182 | form_class = backend.get_form_class(request) 183 | 184 | if request.method == 'POST': 185 | form = form_class(data=request.POST, files=request.FILES) 186 | if form.is_valid(): 187 | new_user = backend.register(request, **form.cleaned_data) 188 | if success_url is None: 189 | to, args, kwargs = backend.post_registration_redirect(request, new_user) 190 | return redirect(to, *args, **kwargs) 191 | else: 192 | return redirect(success_url) 193 | else: 194 | form = form_class() 195 | 196 | if extra_context is None: 197 | extra_context = {} 198 | context = RequestContext(request) 199 | for key, value in extra_context.items(): 200 | context[key] = callable(value) and value() or value 201 | 202 | return render_to_response(template_name, 203 | {'form': form}, 204 | context_instance=context) 205 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | import os 3 | 4 | from registration import get_version 5 | 6 | 7 | # Compile the list of packages available, because distutils doesn't have 8 | # an easy way to do this. 9 | packages, data_files = [], [] 10 | root_dir = os.path.dirname(__file__) 11 | if root_dir: 12 | os.chdir(root_dir) 13 | 14 | for dirpath, dirnames, filenames in os.walk('registration'): 15 | # Ignore dirnames that start with '.' 16 | for i, dirname in enumerate(dirnames): 17 | if dirname.startswith('.'): del dirnames[i] 18 | if '__init__.py' in filenames: 19 | pkg = dirpath.replace(os.path.sep, '.') 20 | if os.path.altsep: 21 | pkg = pkg.replace(os.path.altsep, '.') 22 | packages.append(pkg) 23 | elif filenames: 24 | prefix = dirpath[13:] # Strip "registration/" or "registration\" 25 | for f in filenames: 26 | data_files.append(os.path.join(prefix, f)) 27 | 28 | 29 | setup(name='django-registration', 30 | version=get_version().replace(' ', '-'), 31 | description='An extensible user-registration application for Django', 32 | author='James Bennett', 33 | author_email='james@b-list.org', 34 | url='http://www.bitbucket.org/ubernostrum/django-registration/wiki/', 35 | download_url='http://www.bitbucket.org/ubernostrum/django-registration/get/v0.7.gz', 36 | package_dir={'registration': 'registration'}, 37 | packages=packages, 38 | package_data={'registration': data_files}, 39 | classifiers=['Development Status :: 4 - Beta', 40 | 'Environment :: Web Environment', 41 | 'Framework :: Django', 42 | 'Intended Audience :: Developers', 43 | 'License :: OSI Approved :: BSD License', 44 | 'Operating System :: OS Independent', 45 | 'Programming Language :: Python', 46 | 'Topic :: Software Development :: Libraries :: Python Modules', 47 | 'Topic :: Utilities'], 48 | ) 49 | --------------------------------------------------------------------------------