I'm using django-ratelimit 2.0 for rate limiting my views. I want to show a different (custom) 403 forbidden page for different views. For example if it is a sign up view, it should give a message try again in 1 minute. If it is a forgot password view then message should be try again after 12 hours. Basically I want different rate limit message for different views.
this will help you
https://django-ratelimit.readthedocs.io/en/stable/usage.html#ratelimit.exceptions.Ratelimited
settings.py
DEBUG = False
ALLOWED_HOSTS = ['*']
views.py
from django.shortcuts import render
from django.http import HttpResponse
from ratelimit.decorators import ratelimit # 进行请求限制
from ratelimit.exceptions import Ratelimited # 进行请求限制,判断403
# Create your views here.
#ratelimit(key='ip', rate='2/m',block=True)
def Hello(request):
return render(request, 'hello.html')
def handler403(request, exception=None):
if isinstance(exception, Ratelimited):
return HttpResponse('Sorry you are blocked', status=429)
return HttpResponse('Forbidden')
urls.py
handler403 = views.handler403
Related
I am looking to redirect my user to login page, if they have not logged in.
I initally looked at the decorator #login_required(login_url='/accounts/login/').
But this is not ideal, for 2 reasons: first I want this to apply to all views. Also the decorator returns an error message when I try to login with allauth.
I am sure this is solvable, but I am looking for a solution that could apply to all views.
I found something using authmiddleware(doc: https://pypi.org/project/django-authmiddleware/). However the code doesn't not seem to be responsive, in the sense nothing is happening and the logs on the console don't seem to pick up anything.
Can someone see what I am doing wrong?
base.py
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'AuthMiddleware.middleware.AuthRequiredMiddleware',
]
AUTH_SETTINGS = {
"LOGIN_URL" : "login_user",
"DEFAULT_REDIRECT_URL" : None,
"REDIRECT_AFTER_LOGIN" : False,
}
views.py
from django.shortcuts import render, redirect, reverse
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth import authenticate, login, logout, get_user_model
from django.urls import reverse
def list_event(request): #ADDED FOLLOWING REQUEST IN COMMENTS
event_list = Event.objects.all
return render(request, 'main/list_event.html',{'event_list':event_list})
class AuthRequiredMiddleware(object):
def process_request(self, request):
if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('login_user'))
return None
Found an alternative solution and thought I would leave it there.
I used a tutorial on youtube (https://www.youtube.com/watch?v=axsaC62UQOc) which, with a few changes (the video is old), works like a charm. Its about 3 videos 30 minutes very well explained.
Here it goes:
settings.py
MIDDLEWARE = [
'[yourappname].middleware.LoginRequiredMiddleware',
]
LOGIN_EXEMPT_URLS =( #<-- I am using allauth, so left some examples here)
r'logout',
r'register_user',
r'accounts/google/login/',
r'accounts/social/signup/',
r'accounts/facebook/login/',
)
middleware.py (this files goes in your main app, by default "mysite")
import re
from django.conf import settings
from django.shortcuts import redirect
EXEMPT_URLS = [re.compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
EXEMPT_URLS += [re.compile(url) for url in settings.LOGIN_EXEMPT_URLS]
class LoginRequiredMiddleware:
pass
def __init__(self, get_response):
self.get_response = get_response
def __call__ (self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
assert hasattr(request,'user')
path = request.path_info.lstrip('/')
print(path)
if not request.user.is_authenticated:
if not any(url.match(path) for url in EXEMPT_URLS):
return redirect(settings.LOGIN_URL)
why not use
return redirect('%s?next=%s' % (settings.login_user, request.path))'
instead of HttpResponse?
I’m trying to integrate stripe custom payments flow into my Django ecom website as PayPal isn’t as good but the docs (https://stripe.com/docs/payments/quickstart?lang=python) for python are in the flask framework. Does anyone have boilerplate code for handling a simple transaction for this in Django (views, template etc.)
In theory, the only thing that needs to change is the flask part of that code and change it into Django view(s).
The rest, html+js+css, should be able to be copied + pasted (especially cause the html is dynamically created by the Stripe JS)
views.py
from django.shortcuts import render
from django.http import HttpResponse
# The GET checkout form
#
# urlpattern:
# path('checkout', views.checkout, name='checkout'),
def checkout(request):
return render(request, 'checkout.html')
# The POST checkout form
#
# urlpattern:
# path('create-payment-intent', views.create_payment, name='create_payment'),
def create_payment(request):
if request.method == 'POST':
import json
try:
data = json.loads(request.POST)
def calculate_order_amount(items):
# Replace this constant with a calculation of the order's amount
# Calculate the order total on the server to prevent
# people from directly manipulating the amount on the client
return 1400
# this api_key could possibly go into settings.py like:
# STRIPE_API_KEY = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
#
# and fetched out with:
# from django.conf import settings
# stripe.api_key = settings.STRIPE_API_KEY
import stripe
stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc'
# Create a PaymentIntent with the order amount and currency
intent = stripe.PaymentIntent.create(
amount=calculate_order_amount(data['items']),
currency='usd',
automatic_payment_methods={
'enabled': True,
},
)
return HttpResponse(
json.dumps({'clientSecret': intent['client_secret']}),
content_type='application/json'
)
except Exception as e:
# Just return the 403 and NO error msg
# Not sure how to raise a 403 AND return the error msg
from django.http import HttpResponseForbidden
return HttpResponseForbidden()
# OR you could return just the error msg
# but the js would need to be changed to handle this
return HttpResponse(
json.dumps({'error': str(e)}),
content_type='application/json'
)
# POST only View, Raise Error
from django.http import Http404
raise Http404
Note: You might also have to change the two urls in the .js to match your django URLS. What they have "/create-payment-intent" + "http://localhost:4242/checkout.html" (not sure why that 2nd one is full url, but remember to get the port correct)
This would just be the barebones that your URL you included shows, you still have to figure out how to get the items into checkout.html, dynamically pass them to the page + eventually to the POST and then redo calculate_order_amount(items)
To understand working with Stripepayement I am sharing my GIT URL in which stripe payment is integrated you may refer
https://github.com/KBherwani/BookManagement/
I am new to Django and created simple api which displays message using GET method
views.py:
#api_view(["GET"])
def message(request):
if request.method == 'GET':
return Response({"Print": "GET request from browser works"}, status=status. HTTP_200_OK)
urls.py:
from django.urls import path,include
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets
from . import views
urlpatterns = [
path('',views.index,name='Home'),
path('message',views.message,name='message'),
]
Output:
Now I want to take 2 inputs from user through url and perform addition on that inputs and return its result using GET and POST methods.
Example: http://127.0.0.1:8000/message/?a=2&b=3 (something like this) and it should return addition results.
Most of tutorials online are on fetching data from database but I want to create api which takes input from user and return its output.
Can anyone show me how to achieve above task?
You can use query_params for this:
#api_view(["GET"])
def message(request):
a = request.query_params.get('a')
b = request.query_params.get('b')
return Response({"Print": "a = {}, b={}".format(a,b), status=status. HTTP_200_OK)
I use Django 1.9.7 & Python 3.5
I implement creating user mechanism and tried to test with POSTMAN(chrome application), but it doesn't work and it shows something like belows:
Forbidden (CSRF cookie not set.): /timeline/user/create/
This is the code :
urls.py
from django.conf.urls import url
From. import views
app_name = 'timeline'
urlpatterns = [
# ex) /
url(r'^$', views.timeline_view, name='timeline_view'),
# ex) /user/create
url(r'^user/(?P<method>create)/$', views.user_view, name='user_view'),
]
views.py
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render, HttpResponse
from timeline.models import *
def timeline_view(request):
return HttpResponse('hello world')
def user_view(request, method):
if method == 'create' and request.method == 'POST':
print("hi")
username = request.POST.get('username')
username = request.POST.get('username')
user = User.objects.create_user(username, password=password)
user.first_name = request.POST.get('name','')
user.save()
profile = UserProfile()
profile.user = user
profile.save()
return HttpResponse('create success')
else:
return HttpResponse('bad request', status=400)
POSTMAN :
I tried Django CSRF Cookie Not Set but I think this post is for past version.
for testing i used the #csrf_exempt decorator.
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def user_view(request, method):
...
now you should be able to call this function without the csrf cookie.
(last time i tried it, i was using django 1.8.7)
source:
https://docs.djangoproject.com/en/1.9/ref/csrf/#edge-cases
You should put CSRFToken in request headers.
After sending request via postman, look at the response Cookies section, take csrftoken value and put in Headers section of request, like this:
key:X-CSRFToken
value: jSdh6c3VAHgLShLEyTjH2N957qCILqmb #your token value
Sometimes Version problem in 'Postman' :
I have face the same problem. While sending the data using the oldest version of postman in POST method.
That time I have received the empty json data in server side.
And I have fix this problem, Once I uninstall the oldest version of postman and installed with latest version.
Use this below statement on top of each and every view function definition (views.py). We don't need to use CRF related statements.
#api_view(["POST", "GET"])
eg:
#api_view(["POST", "GET"])
def GivenInput():
return Response(e.args[0],status.HTTP_400_BAD_REQUEST)
Note*:
But I didn't know that any alternative way to make it global throughout the file.
Hello I am trying to setup stripe payment for an e_commerc django application, and I have a problem whit displaying stripeToken, when I try to pay whit the stripe test credit card.
This is my views.py, where am I defining mine stripe payment:
from django.conf import settings
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
import stripe
# Create your views here.
#login_required
def checkout(request):
if request.method == 'POST':
print request.POST
user = request.user
context = {}
tempalte = 'checkout.html'
return render(request, tempalte, context)
When I use test credit card it will display only this
<QueryDict: {u'csrfmiddlewaretoken': [u'NP0q3qvVZs2C0dB2yEiSzmMuNMBS9jvD']}>, whitout stripeToken.
Can you tell me what am I mistaking here?
Thank you.