Action to redirect users to URL - django

Could you tell me how to create an action in the admin site that will redirect users to a certain URL? That is, in the admin site a user chooses this action and finds themselves on Google.
def google(modeladmin, request, queryset):
"""
I myself write some code here to prevent Django from asking users to select an object.
"""
URL = "https://google.com"
... Here goes the code to redirect the user to URL ...
#admin.register(SemanticsCorePhrases)
class SemanticsCorePhrasesAdmin(admin.ModelAdmin):
actions = [google, ]

To redirect a user to a URL in the Django admin site, you can use the redirect function from django.shortcuts.
from django.shortcuts import redirect
def google(modeladmin, request, queryset):
"""I myself write some code here to prevent Django from asking users to select an object.
"""
URL = "https://google.com"
return redirect(URL)
#admin.register(SemanticsCorePhrases)
class SemanticsCorePhrasesAdmin(admin.ModelAdmin):
actions = [google, ]
Please see https://docs.djangoproject.com/en/4.1/topics/http/shortcuts/#:~:text=xhtml%2Bxml%27)-,redirect,-()%C2%B6

Related

In Django, restrict user view using class based views

I have this url pattern:
path("user/<int:pk>", MyAccountView.as_view(), name='my_account'),
And this view:
class MyAccountView(DetailView):
model = CustomUser
When the user is logged Django redirect to that URL.
The problem is that any user can access other users.
For example, if the logged user has pk 25, he can access the view of user with pk 26 by writing in the browser url box:
localhost:8000/user/26
I want that each user can access to his user page only, so if user with pk 25 try to access the url with pk 26, the access should be denied.
Can you point me in some direction of how this is done? The Django documentation is very confusing in this respect.
Thanks.
You need to override the get method of DetailView
from django.core.exceptions import PermissionDenied
from django.contrib.auth.mixins import LoginRequiredMixin
class MyAccountView(LoginRequiredMixin, DetailView):
model = CustomUser
def get(self, request, pk):
if request.user.pk != pk:
raise PermissionDenied()
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
Easy !
First change the view path from user/<int:pk>/ to user/
Link the view to the current user, DetailView won't work because it heavily relies on either pk or slug and we won't be using none of them, so you'll have to write a new view. (Example using FBV because i do not use CBV)
# views.py
from django.contrib.auth.decorators import login_required
# redirects to login page if the user is not authenticated
#login_required(login_url='/example url you want redirect/')
def get_user_profile(request):
context = dict(user=request.user)
return render(request, "template.html", context)
And that's it, any user visiting /user/ will only see their account/profile.

How to add a custom button in a registered model in django admin site

Can anyone guide me in the right direction on how to put a button next to the delete button ? I want to put a confirm and deny button next to it, that when I click it, it will send an email to the user that his/her application is accepted or denied. I've searched online for a solution and also read some similar questions here, but I am not sure whether or not those are right things to go to.
First make buttons for confirm and deny in list_page by writing confirmed() and denied() method , then you append your custom urls in admin urls by overriding get_urls() method and mapped those url to a view method confirmed_application() and denied_application().
After processing your logic then you can redirect same change_list page.
#admin.register(YourModel)
class YourModelAdmin(admin.ModelAdmin):
list_display = ['your_model_fields', 'confirmed', 'denied']
def confirmed(self, obj)
url = reverse('admin:confirm_url', kwargs={'id': obj.id})
return format_html('<a class="button" href="{}">Confirm</a>', url)
def denied(self, obj)
url = reverse('admin:denied_url', kwargs={'id': obj.id})
return format_html('<a class="button" href="{}">Deny</a>', url)
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('confirm/<int:id>', self.confirmed_application, name='confirm_url'),
path('deny/<int:id>', self.denied_application, name='denied_url'),
]
return custom_urls + urls
def confirmed_application(self, request, id):
# you get object_id you can do whatever you want
# you can send a mail
# after processed all logic you can redirect same modeladmin changelist page
redirect_url = "admin:{}_{}_changelist".format(self.opts.app_label, self.opts.model_name)
return redirect(reverse(redirect_url))
def denied_application(self, request, id):
# same as confirmed_application
...

DJANGO ALL AUTHEMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL

I am trying to have two different redirects...one for normal login and another for redirect after email confirmation
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/profile'
LOGIN_REDIRECT_URL = '/'
But when I enable login, AUTHENTICATED REDIRECT goes to LOGIN_REDIRECT but when I disable Login it goes to the EMAIL_CONFIRMATION_REDIRECT route.
When I try printing the adapter settings for email_confirmation redirect url below it shows only the LOGIN_REDIRECT
def get_email_confirmation_redirect_url(self, request):
""" The URL to return to after successful e-mail confirmation. """
if request.user.is_authenticated:
if app_settings.EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL:
return \
app_settings.EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL
else:
return self.get_login_redirect_url(request)
else:
return app_settings.EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL
I tried overriding this get_email_confirmation_redirect_url in the adapter but still wont work. It is not picking the REDIRECT before I login and reverify.
Since ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/profile' was not working if the user is not logged in, I decided to override DefaultAccountAdapter in Django Allauth. My login was that if the time the user joined the app and the time logged in exceeds a certain threshold, then the redirection would be different. So I created an adapter in my users app as below:
class AccountAdapter(DefaultAccountAdapter):
def get_login_redirect_url(self, request):
expiry = 90 #seconds
assert request.user.is_authenticated
if (request.user.last_login - request.user.date_joined).seconds < expiry:
url = 'profile/'
else:
url = settings.LOGIN_REDIRECT_URL
return resolve_url(url)
I then passed this adapter in my settings.py

django allauth redirects to login instead of login on duplicate email

A default behavior of django-allauth is redirect to Singup form when the email retrieved from a social profile matches already existing user's emailid.
Instead, I would like to redirect the user back to the login page with the following message in case of the matching emailid on social login:
An account already exists with this "EMAIL#ADDRESS.COM" e-mail address. Please sign in to that account first, then connect your "PROVIDER" account. You can sign in using "LIST OF LINKED TO THAT EMAIL PROVIDERS".
Has anybody made something similar? Any help is appreciated.
To redirect user before sign-up you need to override allauth.socialaccount.views.SignupView. Simply alter you main urls.py settings:
# urls.py
from users.views import CustomSignupView
urlpatterns = [
# ...
# Your custom SignupView:
url(r'^accounts/social/signup/$', CustomSignupView.as_view(), name='socialaccount_signup'),
url(r'^accounts/', include('allauth.urls')),
# ...
]
CustomSignupView may look like this:
# your_app.views.py
from allauth.socialaccount.views import SignupView
from django.contrib import messages
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.translation import ugettext as _
class CustomSignupView(SignupView):
http_method_names = ['get']
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
social_login_email: str = self.sociallogin.user.email
provider: str = self.sociallogin.account.provider
messages.warning(self.request, _(f"An account already exists with this "
f"\"{social_login_email}\" e-mail address. "
f"Please sign in to that account first, "
f"then connect your \"{provider.capitalize()}\" account."))
return redirect(reverse("account_login"), permanent=False)
This custom view simply forbids all HTTP methods except the GET method (which redirects the user).
This solution works only when SOCIALACCOUNT_AUTO_SIGNUP is set to True (True is set by default, see https://django-allauth.readthedocs.io/en/latest/configuration.html). With this setting, the sign-up form is displayed only when there is e-mail address conflict -> then redirect the user when SignupView is loaded.
Some background: I had a similar problem as mentioned by #horbor in the comment. After the user enters another email (if an email from an external provider is already in use), I get IntegrityError on SignupView. I still do not know if there is a problem with allauth or with my application. However, bypassing signup is the best solution for me.

Django admin login for particular url

i'm using Django admin for admin operation on Movies model like :
urls.py
url(r'^admin/', include(admin.site.urls)),
url(r'^admin/movies/', include('movies.adminurls')),
when request comes like **http://127.0.0.1:8000/admin/** it shows admin-login page
there is Movie model which i can mange from there.
since Movies model have 15 fields , it would be tedious task to fill in data for 100 movies from admin site.
For that i have created a view add_movie in which i'll populate Movies table through json data.
movies.adminurls
url(r'^add/', 'add_movie' , name="admin_add_movie"),
for add_movie admin must be logged in. request is like
http://127.0.0.1:8000/admin/movies/add/
if superuser is not logged in then it should display admin-login form. and when superuser is successfully logged in then it should redirect to add_movie view
So
is it possible to show admin-login for that url?
Redirect to the admin login form if user is not superuser:
def add_movie(request, *args, **kwargs):
if not (request.user.is_authenticated() and request.user.is_superuser):
return HttpResponseRedirect(settings.LOGIN_URL+'?next=/admin/movies/add/')
do_your_stuff(...)
If it is an API, you may want to raise PermissionDenied instead.
After facing your problem I finally find a django decorator with check whether user is admin or logged in and shows your view else returns login form and after login redirects to your page.
from django.contrib.admin.views.decorators import staff_member_required
#staff_member_required
def media_browser(request):
return HttpResponse("You logged in")