Previously I've been using some older version of django-registration which seems to be deprecated now. Because my server does not allow me to install python plugins I need to use 'registration' as separate django application. Now my question is what do I need to modify in order to get registation running as django-app ? Can I just copy 'registration' to my django project catalog, add it in settings and it should work ? Previously there was no such thing as 'backend' defined, now backend init file with function get_backend, that takes 'path' as argument. I guess this path is sent via url right ?
url(r'^activate/(?P<activation_key>\w+)/$',
activate,
{'backend': 'registration.backends.default.DefaultBackend'},
name='registration_activate'),
Inside this catalog there's also init file with DefaultBackend class, with classes activate and register.
http://paste.pocoo.org/show/225790/
They both use signals. Do I need to bother with those signals in any way ? (I still don't quite get what they're used for).
Last thing. Previously after registration it was redirecting te either given success_url or set template in this way :
return HttpResponseRedirect(success_url or reverse('registration_complete'))
Now code responsible for this looks :
if success_url is None:
to, args, kwargs = backend.post_registration_redirect(request, new_user)
return redirect(to, *args, **kwargs)
else:
return redirect(success_url)
and the post_registration_redirect :
def post_registration_redirect(self, request, user):
"""
Return the name of the URL to redirect to after successful
user registration.
"""
return ('registration_complete', (), {})
So why was this changed in this way if it still simply redirect to 'registration_complete' ? The args and kwargs are empty so why bother ?
The situation is much simpler than you're making it out to be. Django applications (like registration) are just normal Python packages and can be imported as such. What that means is that registration can live anywhere that's in your python path already. Oftentimes the simplest place for that is in your root project directory.
The backend argument there just takes a python import path. The argument was added so that people could extend Django-Registration to use custom backends if they so desire.
If you put the registration directory on your python path the existing string should work just fine.
Quote:
"Because my server does not allow me to install python plugins I need to
use 'registration' as separate django application."
Is this because you don't have root access? Have you tried using virtualenv (Link is to my own blog) to create your own (fully writeable) Python/Django install? Alternatively, creating a writeable directory in a place you do have write access, installing django-registration there and pointing your PYTHON_PATH to that location?
IMO, it seems like you gave up too quickly on the "install django-registration" option and moved to the more complicated "run it on a different server" one.
Related
I'd like to upgrade an existing application to a more recent version of django. In 1.4 they changed the password hashing algorithm such that all my old passwords will no longer match when people try to login. Is there some way to upgrade but not require users to reset their passwords?
according to https://docs.djangoproject.com/en/dev/topics/auth/passwords/#auth-password-storage it will still check everything as usual.
if you are worried about storing everything as SHA1 by default, then put the hasher first in the list (this is not recommended though).
# settings.py
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
...
)
if you need to check for yourself, you can consider using virtualenv with the newer django==1.5 package and create a dummy project/app connected to the same database to try it out. If you have admin privileges and already use the admin interface, you can use that to login there.
I did the same upgrade last month and Django passwords still fully functional. The changes I made are basically in generic views( now all generic views are class based) , The logging in settings.py was changed and I have to put a ALLOWED_HOSTS list. For example: ALLOWED_HOSTS = ['.stackoverflow.com']
Particularly, I changed my urls calls cause I was using named urls without quotes in url tags and it's no longed supported by django. The right way is like this: {% url 'name_of_the_view' arg1 arg2%}
I suggest you to create another environment and try use django 1.5 just making this small changes.
My old worker installed Pinax through PIP and it's installed in site-packages. All the apps lives there. Our own apps are within our Django project structure.
I want to modify Pinax's account app, by switching the create_user's is_active flag to False. Currently, the app makes it True. I also want to add additional functionality to create_user or whatever function I want to do.
from pinax.account import forms
class MyCustomizeForm(forms.SignupForm):
def create_user(....):
super(....)
// additional...
Maybe this?
But doesn't that require me to do at least two commit transactions talking to DB?
Is that preferable? Also, does doing this require me to change anything else in my Django project (how users signup, what views it uses... what forms it uses)?
Currently, I've an app living in my Django project supposes to deal with the extension / customization of account app. I can't commit site-packages to VCS.... I mean.. I am not supposed to make any changes there.
Thanks.
Pinax account/models.py
class Account(models.Model):
...
def its_own_method(...)
# this is in the same indentation level as class Account
def create_account(sender, instance=None, **kwargs):
if instance is None:
return
account, created = Account.objects.get_or_create(user=instance)
post_save.connect(create_account, sender=User)
You can use the django signals for exactly this situation. Signals are meant for apps that need to be distributed generally and won't always know how they will be integrated into a project.
The signal of interest to you here is the pre_save. You can connect a pre_save to the pinax.account model and be notified when a save is about to happen. This will give you a chance to make changes to that model instance. Signals are synchronous, meaning you are making your change serially, right before the pinax.accounts will finish committing the save
a newbie django question
I want to use 3rd party app, but I need to make some mods to it (in this case, the app is django-registration, and I need to change things such as allowing registration without confirmation email)
Initially, I simply installed the app in the general site-packages folder, and changed the code there. Now that I put my code on bitbucket I need a way to be able to keep my mods in the repository in a usable way, and uploading the full python code doesn't sound like a good idea.
I guess the best way would be to keep the 3rd party app in site-packages, and create an app in my project to keep my changes. In my case, I'd create my-django-registration in my project, and then import this when I need it in my code, rather than django-registration.
I also read about virtualenv, but I think that's mostly used for being able to use multiple environments in the same machine (in fact, somewhere it advises against changing the modules installed in the virtualenv), and doesn't help me with keeping my changes in a repository.
Any comments welcome!
Thanks
In general, you should reuse and override the behavior in 3rd party apps and not modify their sources.
What you'll most often encounter is that apps ship models that may not necessarily cover your needs, but do most of the work; you'll have forms that are almost perfect, but need that little something; you'll have views that would be perfect if you can just change one thing; you'll have URLs that are sane, but you need something more from them.
In most cases, that would just require that you create a custom app and rewire everything. Ship your own URLs that map to views that you've extended and overrode methods for custom behavior; supply it with a model form who's Meta is using the new model that you've extended from the original; so forth...
That's just the tip of the iceberg of what you can do, there's more ways when your creative. I can give you an example of how I've used the RegistrationProfile model, but shipped my own URL patterns and a custom class-based view that handled the registration process.
Now, where virtualenv comes into play is that you'll most likely be using pip to specify and supply your required dependencies in the requirements file format. That's when you want to say: "I've extended the django-registration app, but it won't work cleanly with just any version. It has to be of release X", or , "a checkout from the repository of commit Y".
This blog post that adresses this issue is extremely helpful. For convenience I copy-paste it here:
You don’t touch external app code
You are not supposed to edit the code from an external app. Unless you fork it first on github.
So, how to override without forking:
Overriding a template
If you want to override templates/userena/activate_fail.html, then all you have to do is create your own templates/userena directory and make your own activate_fail.html in it.
Overriding a url
Probably the first thing you should check in an external app is its urls.py. Views that are properly coded should support plenty of arguments. For example, userena has a signup view with such a signature (at the time of writing):
def signup(request, signup_form=SignupForm,
template_name='userena/signup_form.html', success_url=None,
extra_context=None):
This means that you can replace the form used by the signup view. To do so, open your urls.py, add what we are going to need at the top:
from userena import views as userena_views
from yourforms import YourSignupForm
Then, find the include the external app’s urls, something like:
url(r'^userena/', include('userena.urls')),
Before that, add your url override:
url(r'^userena/signup/$', userena_views.signup, {'signup_form': YourSignupForm}, name='userena_signup'),
url(r'^userena/', include('userena.urls')),
Now, your custom url definition will be the first to be hit when a visitor hits /userena/signup/. Which means that /userena/signup/ will use YourSignupForm instead of userena’s signup form.
This trick works with any view argument. The ones you should see the most often are:
template_name: lets you change the template name
extra_context: lets you add a dict that will be added to the
context
Almost every view should have these arguments.
Overriding a view
Overriding a view requires to override the url of the view you want to replace. If you want your own signup view to be used, then just override the url:
import yourviews
# ...
url(r'^userena/signup/$', yourviews.yoursignup, name='userena_signup'),
url(r'^userena/', include('userena.urls')),
Decorating a view
Decorating a view is like overriding a view, but reuses the external app’s view. Basically, it’s the same than overriding a view (see above), but your view will look like this
from userena import views as userena_views
def yoursignup(request):
# do stuff before userena signup view is called
# call the original view
response = userena_views.signup(request)
# do stuff after userena signup view is done
# return the response
return response
Forking an app
If you are not familiar with pip and virtualenv first, please read the post about using pip and virtualenv first.
For example:
You installed django-userena as such: pip install django-userena
First you should uninstall it: pip uninstall django-userena
Then go on the app’s github page
Click on the fork button
This will make you a repository with a copy of django-userena
Install it as such: pip install -e
git+git#github.com:your-username/django-userena.git#egg=django-userena
Then you can edit the code in yourenv/src/django-userena
Push your commits
Credits to the post writer!
I think the neatest way to accomplish what you look for would be to fork django-registration, and in your app use the fork instead of the original project.
That being said, you can have a non-email registration in django-registration without changing the code of the app. I've done it by creating a custom registration backend that sets the users as activated upon creation. Here you can see other ways to do the same.
I'm running multiple sites from a single django instance, and expect the framework to eventually serve several hundred sites from one or several installations.
I need to patch some django settings based on the current request. I've written some middleware to monkey patch the settings, but I need these settings to be patched before the middleware gets invoked because other apps aren't taking the monkey-patched changes (i.e. apps get run then middleware gets run so the apps don't use the monkey-patched settings).
I should also add this is mainly for the benefit of third-party apps that I haven't written, so I don't want to go round adding decorators or anything like that because that would mess up my upgrade path.
So:
How can I get access to the current request in an app's init.py file?
Will an app's init.py get called once per request or only once? If it's only once, how else could I do this so I can manipulate the settings once per request?
Is it safe to do this kind of monkey patching? I know it makes code a bit more opaque, but I don't want to use different wsgi files per site because I want to allow users to edit some of these settings and have my monkey patching come from the database.
Is there a better solution that would allow certain settings to be stored in the database?
This module - django-tupperware does what you are asking about: https://bitbucket.org/jiaaro/django-tupperware/
Give it a try.
Never ever ever change settings on the fly. You cannot predict how the application may one day be deployed, and in most of them the project will fail in.. interesting ways.
If you really want to have hundreds of sites which will be dynamically reconfigured all the time, you might try to Djangos django/conf/__init__.py which is used to supply the settings to the rest of the framework. You might be able to alter it in a way it depends on the request and it's Host field. Or you'll get many interesting failures at the very least.
My solution to this problem is to give each request, ALL the settings and update them on the fly with a middleware, how do i do this?
Is rather simple:
This is the middleware that does it all
from django.conf import settings
class DumpObject: pass
class Settings(object):
def process_request(self,request):
request.settings = DumpObject()
for setting in dir(settings):
if not setting.startswith('__'):
setattr(request.settings, setting, getattr(settings,setting))
The DumpObject is just there so i can use the object.property notation, it could have been a dictionary, but i wanted to keep some similarity in the syntax.
This assumes that none of your settings name starts with __ which is a fair assumption.
So if i want to override a particular setting, i don't keep a settings file i do it in this middleware. like this:
class Settings(object):
def process_request(self,request):
request.settings = DumpObject()
for setting in dir(settings):
if not setting.startswith('__'):
setattr(request.settings, setting, getattr(settings,setting))
if 'mydomain' in str(request.host): #this is thanks to django-hosts project
request.settings.GOOGLE_ANALYTICS_ID = '89298393-238'
Of course this doesnt take into account the problem of accessing the settings the old way
from django.conf import settings
settings.GOOGLE_ANALYTICS_ID = 'the value in settings.py'
But it really doesn't matter because you will probably only want to change the settings on the context of having a request object, available.
I want to implement user registration using captcha in Django.
The workflow of django-registration app is a great, but it doesn't have captcha.
What captcha would you recommend to use with it?
Are there some other variants of registration+captcha or useful links on the topic?
This should work with Django-1.1 and don't be too hard to install.
django-registration is pretty extendable. One way to extend it is to provide a custom registration form. I'd recommend to use reCaptcha, e.g. with the widget and form field from here (archived). Then it is as simple as writing a custom form class and registration backend (which is simpler than it sounds):
from registration.backends.default import DefaultBackend
from registration.forms import RegistrationForm
class RecaptchaRegistrationForm(RegistrationForm)
recaptcha = ReCaptchaField(label="I'm a human")
class RecaptchaRegistrationBackend(DefaultBackend):
def get_form_class(self, request):
return RecaptchaRegistrationForm
The last step is to tell django-registration to use your backend. That step is described in the docs (I couldn't find a HTML version of the docs, sorry)
I've just had this problem, but the solution is dead simple.
I'm using django-registration, and I want a reCAPTCHA field for user registration. In just 1 minute:
download django-recaptcha (pip install django-recaptcha)
install it on your project. That is, copy the "captcha" folder to your project, add "captcha" to INSTALLED_APPS and add your RECAPTCHA_PUBLIC_KEY and RECAPTCHA_PRIVATE_KEY keys to settings.py too (as described in the installation instructions)
open registration/forms.py and add this field inside class RegistrationForm(forms.Form):
captcha = ReCaptchaField()
you will also have to import:
from captcha.fields import ReCaptchaField
And that's it. Less than a minute.
For those like me arriving late to the thread, there are a bunch of solutions out there now, which are pretty easy to install:
http://code.google.com/p/django-simple-captcha/
http://code.google.com/p/django-captcha/
https://github.com/inueni/django-captcha-field
https://github.com/justquick/django-math-captcha
https://github.com/marconi/django-mollom which uses the third-party Mollom service (which provides captcha and spam-filtering services).
I've successfully setup Django Mollom and Django Simple Captcha, and the hardest part was yak shaving around installing PIL on my Mac. Implementing the code was as straightforward as the docs for each would suggest.