How to use different view for django-registration? - python

I have been trying to get django-registration to use the view RegistrationFormUniqueEmail and following the solution from this django-registration question. I have set my urls.py to
from django.conf.urls import patterns, include, url
from registration.forms import RegistrationFormUniqueEmail
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
(r'^users/', include('registration.backends.default.urls')),
url(r'^users/register/$', 'registration.backends.default.views.RegistrationView',
{'form_class': RegistrationFormUniqueEmail,
'backend': 'registration.backends.default.DefaultBackend'},
name='registration_register'),
)
However, I can still create multiple accounts with the same email. What is the problem? Shouldn't django-registration be using the view that I specified? I am currently using django-registration 0.9b1.

The version of Django registration you are using has been rewritten to use class based views. This means a different approach is required in your urls.py.
First, You need to subclass the RegistrationView, and set the custom form class.
from registration.backends.default.views import RegistrationView
from registration.forms import RegistrationFormUniqueEmail
class RegistrationViewUniqueEmail(RegistrationView):
form_class = RegistrationFormUniqueEmail
Then, use your custom RegistrationViewUniqueEmail subclass in your urls. As with other class based views, you must call as_view().
url(r'^user/register/$', RegistrationViewUniqueEmail.as_view(),
name='registration_register'),
Make sure your customised registration_register view comes before you include the default registration urls, otherwise it won't be used.

The version 1.2 of django-registration-redux allows the unique email option with the following urls.py patterns:
url(r'^accounts/register/$', RegistrationView.as_view(form_class=RegistrationFormUniqueEmail), name='registration_register'),
url(r'^accounts/', include('registration.backends.default.urls')),
If you need to do something more, like a specific URL option, you can subclass the RegistrationView in your app views.py and RegistrationForm in your app forms.py

Related

Django 2.2 : Is there any way to remove app name from admin urls?

I am using Django Built-in Admin panel, is there any way to remove app name from urls?
If I want to access User listing, it redirects me to 27.0.0.1:8000/admin/auth/user/ can I make it 27.0.0.1:8000/admin/user/ without the app name auth?
Thanks,
As documented here you can create a custom AdminSite and override the get_urls method. This simple code should to the job:
In your common.admin.py
from django.contrib.admin import AdminSite
class MyAdminSite(AdminSite):
def get_urls(self):
urlpatterns = super().get_urls()
for model, model_admin in self._registry.items():
urlpatterns += [
path('%s/' % (model._meta.model_name), include(model_admin.urls)),
]
return urlpatterns
my_admin = MyAdminSite('My Admin')
my_admin.register(YourModel)
...
Note that you register your models with the new custom AdminSite instance.
Then in your projects urls.py
from common.admin import my_admin as admin
from django.urls import path
urlpatterns = [
path('admin/', admin.urls),
# Your other patterns
]

password_change_done not using custom template in Django

I used Django's auth_views.password_change to allow a user to change their password. It uses a custom template and it works well, but the problem I'm having is that it redirects to Django's password change successful admin template instead of the custom template I declared.
urls.py
from django.conf.urls import url
from django.contrib.auth import views as auth_views
from . import views
app_name = 'users'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^add-user/$', views.CreateUserView.as_view(), name='add-user'),
url(r'^search/$', views.UserSearchView.as_view(), name='search-users'),
url(r'^login/$', views.LoginView.as_view(), name='login'),
url(r'^logout/$', views.LogoutView.as_view(), name='logout'),
url(r'^(?P<pk>\d+)/settings/update$', views.UpdateAccountView.as_view(), name='update-account'),
url(r'^settings/change/$', auth_views.password_change, {'template_name': 'users/forms/change-password.html'},
name='change-password'),
url(r'^settings/change-done/$', auth_views.password_change_done,
{'template_name': 'users/forms/change-password-done.html'}, name='change-password-done'),
url(r'^(?P<pk>\d+)/delete-user/$', views.DeleteUserView.as_view(), name='delete-user'),
Any Ideas what I missed?
In INSTALLED_APPS ensure that your app with the custom templates is specified before admin.
Django searches for the template in order.
You should use:
url(r'^settings/change/$', auth_views.password_change, {'template_name': 'users/forms/change-password.html',post_change_redirect:'change-password-done'},name='change-password'),
Without post_change_redirect default template will be loaded in that case.
Quite long since this question was asked, but the above answers didn't work for me and this did. In urls.py:
Make sure this import is there:
from django.contrib.auth.views import ..., password_change_done, ...
Then remove url(r'^', include('django.contrib.auth.urls')) from the URLs and override the password_change_done view with your custom template. Again, I also had the above suggestions already implemented in my code.

Django registration: Redirect after registering fails because of missing argument

I am currently going through the tango with django tutorial and trying to implement django registration with redirect after it was successful.
I followed both the tutorial and what I found in a linkanother question.
When I register, I get
TypeError at /accounts/register/
get_success_url() missing 1 required positional argument: 'user'
urls.py
from django.conf.urls import include, url, patterns
from django.contrib import admin
from registration.backends.simple.views import RegistrationView
class MyRegistrationView(RegistrationView):
def get_success_url(self, request, user):
return '/student/'
urlpatterns = [
url(r'^student/', include('student.urls')),
url(r'^admin/', admin.site.urls),
# Add in this url pattern to override the default pattern in accounts.
url(r'^accounts/register/$', MyRegistrationView.as_view(), name='registration_register'),
url(r'^accounts/', include('registration.backends.simple.urls')),
url(r'', include('registration.auth_urls')),
]
Anyone an idea what I might be doing wrong?
Thanks!
Things have changed from then, now you supply 'user' as first positional argument. And there is no request argument for get_success_url method. Your code should look like this:
class MyRegistrationView(RegistrationView):
def get_success_url(self, user):
return '/student/'
See: Old RegistrationView and new RegistrationView at github.

Django custom AdminSite and ModelAdmin

I have overridden standard AdminSite with my own one:
project/admin/base.py:
from django.contrib import admin
class MyAdmin(admin.AdminSite):
...
my_admin = MyAdmin()
and registered some application's model with it:
fact/admin.py:
from django.contrib import admin
from project.admin.base import my_admin
from models import Fact
class FactAdmin(admin.ModelAdmin):
fields = ('section', 'description')
my_admin.register(Fact, FactAdmin)
How can I get this model displayed on an index page? I can't use autodiscover as stated here: How to use custom AdminSite class?
The workaround suggested in that question also doesn't work for me and I'd like to make it it a more clean way.
The documentation only states that
There is really no need to use autodiscover when using your own AdminSite instance since you will likely be importing all the per-app admin.py modules in your myproject.admin module.
I don't import per app modules in project.admin module though.
So is there any way to tell custom AdminSite about the registered model and show it on the index?
Edit: I have hooked URLs and I see my_admin, not admin. With standard admin everything works correctly. Here is the code of project/urls.py:
from django.conf.urls import patterns, include, url
from admin.base import my_admin
urlpatterns = patterns('',
...
url(r'^admin/', include(my_admin.urls, app_name='admin')),
)
I think you need to do:
from django.contrib import admin
class MyAdmin(admin.AdminSite):
...
admin.site = MyAdmin()

Python + Django page redirect

How do I accomplish a simple redirect (e.g. cflocation in ColdFusion, or header(location:http://) for PHP) in Django?
It's simple:
from django.http import HttpResponseRedirect
def myview(request):
...
return HttpResponseRedirect("/path/")
More info in the official Django docs
Update: Django 1.0
There is apparently a better way of doing this in Django now using generic views.
Example -
from django.views.generic.simple import redirect_to
urlpatterns = patterns('',
(r'^one/$', redirect_to, {'url': '/another/'}),
#etc...
)
There is more in the generic views documentation.
Credit - Carles Barrobés.
Update #2: Django 1.3+
In Django 1.5 redirect_to no longer exists and has been replaced by RedirectView. Credit to Yonatan
from django.views.generic import RedirectView
urlpatterns = patterns('',
(r'^one/$', RedirectView.as_view(url='/another/')),
)
Depending on what you want (i.e. if you do not want to do any additional pre-processing), it is simpler to just use Django's redirect_to generic view:
from django.views.generic.simple import redirect_to
urlpatterns = patterns('',
(r'^one/$', redirect_to, {'url': '/another/'}),
#etc...
)
See documentation for more advanced examples.
For Django 1.3+ use:
from django.views.generic import RedirectView
urlpatterns = patterns('',
(r'^one/$', RedirectView.as_view(url='/another/')),
)
There's actually a simpler way than having a view for each redirect - you can do it directly in urls.py:
from django.http import HttpResponsePermanentRedirect
urlpatterns = patterns(
'',
# ...normal patterns here...
(r'^bad-old-link\.php',
lambda request: HttpResponsePermanentRedirect('/nice-link')),
)
A target can be a callable as well as a string, which is what I'm using here.
Since Django 1.1, you can also use the simpler redirect shortcut:
from django.shortcuts import redirect
def myview(request):
return redirect('/path')
It also takes an optional permanent=True keyword argument.
If you want to redirect a whole subfolder, the url argument in RedirectView is actually interpolated, so you can do something like this in urls.py:
from django.conf.urls.defaults import url
from django.views.generic import RedirectView
urlpatterns = [
url(r'^old/(?P<path>.*)$', RedirectView.as_view(url='/new_path/%(path)s')),
]
The ?P<path> you capture will be fed into RedirectView. This captured variable will then be replaced in the url argument you gave, giving us /new_path/yay/mypath if your original path was /old/yay/mypath.
You can also do ….as_view(url='…', query_string=True) if you want to copy the query string over as well.
With Django version 1.3, the class based approach is:
from django.conf.urls.defaults import patterns, url
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^some-url/$', RedirectView.as_view(url='/redirect-url/'), name='some_redirect'),
)
This example lives in in urls.py
Beware. I did this on a development server and wanted to change it later.
Firefox 5 'caching' 301 redirects
I had to clear my caches to change it. In order to avoid this head-scratching in the future, I was able to make it temporary like so:
from django.views.generic import RedirectView
url(r'^source$', RedirectView.as_view(permanent=False,
url='/dest/')),
You can do this in the Admin section. It's explained in the documentation.
https://docs.djangoproject.com/en/dev/ref/contrib/redirects/
page_path = define in urls.py
def deletePolls(request):
pollId = deletePool(request.GET['id'])
return HttpResponseRedirect("/page_path/")
This should work in most versions of django, I am using it in 1.6.5:
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
urlpatterns = patterns('',
....
url(r'^(?P<location_id>\d+)/$', lambda x, location_id: HttpResponseRedirect(reverse('dailyreport_location', args=[location_id])), name='location_stats_redirect'),
....
)
You can still use the name of the url pattern instead of a hard coded url with this solution. The location_id parameter from the url is passed down to the lambda function.

Categories