I have a function that is run every view to correct slugs.
For example if the slug is /12-post-about-stuff and a user enters /12-post-abot_stof they will be redirected correctly. The problem is that the different views have different url patterns for example:
/posts/post_slug/
...
/posts/post_slug/comments/new
how to I write a function that redirects by fixing the slug name based on the current url?
Edit: I am applying a decorator to every view with a board_name and pk argument. What I don't know is how to dynamically return the new url because the url format is different for each view.
def correct_board_url_name(func):
def wrapper(request, board_slug):
try:
pk = int(board_slug.split('-')[0])
board = Board.objects.get(pk=pk)
if (board.slug != board_slug):
# This does not always work depending on what is entered
return redirect(request.get_full_path().replace(board_slug, board.slug, 1))
else:
return func(request, board_slug)
except:
raise Http404('')
return wrapper
A middleware is a good choice if you want to process requests in many different views.
class RedirectMiddleware(object):
def process_request(self, request):
if request.resolver_match.app_name == 'posts' \
and 'post_slug' in request.resolver_match.kwargs:
new_path = None
# your logic here
if new_path:
return redirect(new_path, permanent=True)
return
In settings:
MIDDLEWARE = [
# another middlewares here ...
'path.to.RedirectMiddleware',
]
Related
I am currently try to redirect from one view to another view. However, nothing happens, the token gets printed and that's it.
class SocialLoginInvUserAPIView(APIView):
permission_classes = [AllowAny]
#staticmethod
def post(request):
print(request.data["token"])
return redirect("login/")
Here is the login url:
url(r'login/$',
LoginInvUserAPIView.as_view(),
name='auth_user_login'),
redirect("url_name")
This is how redirect works. Don't give url but give its name. Here,
you must write:
....
return redirect('auth_user_login')
....
I am using Django-registration and I have subclassed the BaseRegistrationView to customised a backend.
However, the HttpResponseRedirect fail to redirect to a new page when the condition is met.
The code is listed below:
class CustomRegistrationView(BaseRegistrationView):
def register(self, request, **cleaned_data):
captchaMatch = False
#check captcha
captchaValue = request.session.get('captcha')
captchaValueSubmitted = cleaned_data['captcha'] + "123"
if captchaValue != captchaValueSubmitted:
return HttpResponseRedirect(reverse('InvitationRequired'))
else:
self.captchaMatch = True
username, email, password = cleaned_data['username'], cleaned_data['email'], cleaned_data['password1']
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
new_user = RegistrationProfile.objects.create_inactive_user(username, email,
password, site)
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=request)
return new_user
def registration_allowed(self, request):
"""
Indicate whether account registration is currently permitted,
based on the value of the setting ``REGISTRATION_OPEN``. This
is determined as follows:
* If ``REGISTRATION_OPEN`` is not specified in settings, or is
set to ``True``, registration is permitted.
* If ``REGISTRATION_OPEN`` is both specified and set to
``False``, registration is not permitted.
"""
return getattr(settings, 'REGISTRATION_OPEN', True)
def get_success_url(self, request, user):
"""
Return the name of the URL to redirect to after successful
user registration.
"""
print "get successful url"
if self.captchaMatch:
return ('registration_complete', (), {})
else:
return HttpResponseRedirect(reverse('InvitationRequired'))
Can anyone help explain why the redirection is executed inside the function register ?
I guess the register method is supposed to return a user or None. Not an HttpRedirect object. Since I'm not familiar with this specific app, try to see how they handle failure on the original method and follow that policy (e.b. return None or raise an Exception).
Also, based on the comments on the get_success_url() method, I would expect the code to be like this:
def get_success_url(self, request, user):
"""
Return the name of the URL to redirect to after successful
user registration.
"""
if self.captchaMatch:
return ('registration_complete', (), {})
else:
return ('InvitationRequired', (), {})
I guess you should not return a HttpResponse instance, as the method is used to get the URL to be redirect to (not the redirection itself).
Suppose I have view
def foo(request)
I'm also using custom user model as follow:
class MyUser(AbstractUser):
field = models.BooleanField()
I'd like to combine 2 django decorators: login_required and user_passed_test, so that anonymous user should be redirected to a login page and user who is not allowed to see the view (user.field == False) should see a proper message (say, something like 'you're not allowed to see this').
So I tried:
my_decor = user_passes_test(lambda user: user.field == True,
login_url='/bar')
def custom_decor(view_func):
decorated_view_func = login_required(my_decor(view_func), login_url='/login')
return decorated_view_func
And I also have to define view:
def bar(request):
return HttpResponse('you are not allowed to see this context.')
and hardcode it in my urls.
The question is: can I do this without creating an additional view and adding it to urls? Is there a way to make 'user_passed_test' decorator raising an 404 error instead of redirecting to a login view?
There is probably a very simple solution and surely I'm just missing it.
I dont remember very well the decorators syntax, but you can do:
def custom_decor(view_func):
def decorator(request, *args, **kwargs)
if request.user.field is True:
return view_func(request, *arg, **kwargs)
raise Http404
return decorator
so...
#login_required(login_url='/login')
#custom_decor
def foo(request)
# ...
I am using Django, and require certain 'trial' users only to activate a certain part of the website-any ideas on an efficient way to do this?
I was thinking about giving a paying customer a certain ID and linking this to the URL of the sites for permission.
Thanks,
Tom
I'd use a view decorator like this:
def paying_only(view):
def _decorated(request, *args, **kwargs):
if not is_paying(request.user):
redirect('page_explaining_that_this_is_for_paying_users_only')
return view(request, *args, **kwargs)
return _decorated
#paying_only
def some_view(request):
...
I decided to post my solution, I might even get some feedback. I have a middleware blocking request/responses on certain paths defined in settings, first the middleware:
import re
from django.conf import settings
from django.shortcuts import redirect
class InvitationRequired(object):
def process_response(self, request, response):
if not settings.CLOSED_BETA_ACTIVE:
return response
if (hasattr(request, 'user')
and hasattr(request.user, 'is_authenticated')
and request.user.is_authenticated()):
return response
elif (request.path in
settings.CLOSED_BETA_INVITATION_MIDDLEWARE_EXCEPTED_URIS):
return response
elif response.status_code < 200 or response.status_code >= 300:
return response
else:
for regex in \
settings.CLOSED_BETA_INVITATION_MIDDLEWARE_EXCEPTED_PATTERNS:
if re.compile(regex).match(request.path):
return response
return redirect(settings.CLOSED_BETA_INVITATION_MIDDLEWARE_REDIRECT)
In settings.py I have something like this:
CLOSED_BETA_ACTIVE = True
CLOSED_BETA_INVITATION_URL = '/invitation/'
CLOSED_BETA_INVITATION_MIDDLEWARE_REDIRECT = CLOSED_BETA_INVITATION_URL
CLOSED_BETA_INVITATION_MIDDLEWARE_EXCEPTED_PATTERNS = (
r'^/api/v1/',
r'^/static/',
r'^/media/',
r'^/admin/',
r'^/registration/',
r'^/',
)
Hope it's clear, at least it can give you a a different approach.
This is a very wide-ranging question. One solution would be to store a trial flag on each user. On an authenticated request, check for User.trial in your controller (and probably view) and selectively allow/deny access to the endpoint or selectively render parts of the page.
If you wish to use built-in capabilities of Django, you could view 'trial' as a permission, or a user group.
So I'm still a newbie in Django and I would like to have your advices regarding this point :
I have a User system in my application which extend from userena:
class FindUrGeekUserProfile(UserenaBaseProfile):
user = models.OneToOneField( User, unique = True, verbose_name ='userData', related_name='myProfile',db_index = True)
type = models.CharField(max_length = 2, choices = USER_TYPE, blank = True, null = True, db_index = True)
def __unicode__(self):
return 'Name: ' + self.user.username + ' Type: ' + self.type
When a User registers in my website he completes login, password and email fields.
The first time a user will connect though my website, he will see a page asking him what's his usertype : Type1 or Type2...
I want to verify in each login_registered view that the user has defined his type. Until now, i created a function I use in every registered view:
def checkUserType(user):
if(user.type != None)
return True
else:
retur False
#login_registered
def myView(request):
if (checkUserType(request.user)):
Continue....
else:
return redirect('setUserType') # Page where the user will set his type
Is there a better way to that in Django? Using some built in function ?
Thanky ou for your help
There's at least a better way:
#login_registered
def myView(request):
if not checkUserType(request.user):
return redirect('setUserType') # Page where the user will set his type
# user has the type, continue
Also, you could write a custom middleware, and do the check/redirect in process_request(). It could look like:
from django import http
from django.core.urlresolvers import reverse
class SetUserTypeMiddleware(object):
urls = ['/some/path/that/requires/user/type/',]
def process_request(self, request):
if not request.user.is_authenticated():
return
for url in urls: # customize url matching to your taste
if url in request.path_info:
return http.HttpResponseRedirect(reverse('setUserType'))
Middleware is a cool feature, it's simple and powerful. Just don't forget to register them in settings.MIDDLEWARE_CLASSES.