Simple question. I have bunch of django views. Is there a way to tell django that for each view, use foo(view) instead? Example:
Instead of writing
#foo
#bar
#baz
def view(request):
# do something
all the time, I'd like to have
def view(request):
markers = ['some', 'markers']
and hook this into django:
for view in all_the_views_in_my_app:
view = do_something_based_on_the_marker(view)
I'd like to have this done at server startup time. Any thoughts?
Depending on what you want to do (or achieve), you can write a custom middelware and implement the method process_view (and/or any other method that you need):
process_view() is called just before Django calls the view. It should return either None or an HttpResponse object. If it returns None, Django will continue processing this request, executing any other process_view() middleware and, then, the appropriate view. If it returns an HttpResponse object, Django won't bother calling ANY other request, view or exception middleware, or the appropriate view; it'll return that HttpResponse. Response middleware is always called on every response.
I don't know why you want to do this. I don't know either why you don't want to use decorators. But you could use this ugly (and likely error prone) hack as a start:
def view(request):
pass
view.markers = ['some', 'markers']
some other place:
from app import views
[x for x in views.__dict__.values() if hasattr(x,'markers')]
Related
In Django Rest framework, we can verify permissions such as (isAuthenticated, isAdminUser...)
but how can we add our custom permissions and decide what django can do with those permissions?
I really want to understand what happens behind (I didn't find a documentation that explaint this):
#permission_classes([IsAdminUser])
Thank you
Write your own permissions, like this:
def permission_valid_token(func):
# first arg is the viewset, second is the request
def wrapper(*args, **kwargs):
valid_token, user_token = test_token_authorization(args[1].headers) # my function to validate the user
if not valid_token:
return Response(status=status.HTTP_401_UNAUTHORIZED)
return func(*args, **kwargs)
return wrapper
This is a permission that i'm using in app, probably you will have to change the valid_token part
And them you import in your views
from file_that_you_use.permissions import permission_valid_token
And you use as a decorator
class WeatherViewSet(viewsets.ViewSet):
#permission_valid_token
def list(self, request):
This is just a viewset for example, you can use generic viewsets or whatever you want.
If you are using VSCode, hover over #permission_classes([IsAdminUser]), click on Command (on your keyboard).
You can see what happens behind the scenes, play and create your custom Django version (not recommended) or you can overwrite the function.
How to redirect to another domain with python django and pass additional informations?
For example i want to redirect to https://ssl.dotpay.pl/test_payment/ and give additional informations so url will look like this
https://ssl.dotpay.pl/test_payment/?id=123456&amount=123.00&description=Test
but I don't want to generate url in my view, just pass the data in json or something like that.
What is the way to do this?
this is generated url by what i meant 'ssl.dotpay.pl/test_payment/?id=123456&amount={}&description={}'.format(123.00, 'Test')
Be sure to put a protocol before your url (or at least two slashes).
This way, Django will see it as an absolute path.
From your comment it seems you redirect to ssl.dotpay.pl what will be seen as a local path rather than another domain.
This is what I came across. (See question I put on stackoverflow and answer)
So in your case, you can use the following:
class MyView(View):
def get(self, request, *args, **kwargs):
url = 'https://ssl.dotpay.pl/test_payment/'
'?id=123456&amount={}&description={}'.format(123.00, 'Test')
return HttpResponseRedirect(url)
You could also use redirect from django.shortcuts instead of HttpResponseRedirect
Assuming you are using a functional view, you could probably do something like this in your view:
from django.http import HttpResponseRedirect
def theview(request):
# your logic here
return HttpResponseRedirect(<theURL>)
I have a function that gets some base information in my views.py file, and I'm trying to update the context of each page using it by having it return a dictionary. However, using .update() on the context dictionary in the render() function doesn't seem to work.
Here's what I'm doing:
def getBaseInfo():
allPages = list(Page.objects.all())
primaryPages = allPages[:5]
secondaryPages = allPages[5:]
return {'p':primaryPages, 'p2':secondaryPages}
def index(request):
return render(request, 'pages/index.html', {}.update(getBaseInfo()))
However, nothing is sent to my templates. Thanks in advance!
Edit: I'm using Python 2.7.11
Firstly, if you wanted to use a base dictionary and add objects to that you should do so explicitly:
def index(request):
context = getBaseInfo()
context.update({'otherkey': 'othervalue'})
# or
context['otherkey'] = 'othervalue'
return(...)
However, there is no need to do this at all. Django already provides you a way of automatically providing shared context, and that is a context processor.
In fact your getBaseInfo() function is already almost a context processor - it just needs to accept the request parameter - so you just need to add it to the context_processors list in your TEMPLATES setting. Then all your templates will automatically get the values from that function.
You should do something like this:
def index(request):
allPages = list(Page.objects.all())
primaryPages = allPages[:5]
secondaryPages = allPages[5:]
return render(request, 'pages/index.html', {'p':primaryPages, 'p2':secondaryPages})
Other option should be to make getBaseInfo a #property for reusability and DRY purposes, or make the view class based template view and define reusable code as mixin. I prefer the latter, but it's entirely matter of personal choice.
I'm curious about setting urls accept_method directly when defining url like
url(r'some-pattern', 'view_name', name='url_name', accept_method='GET|POST')
I know there're view decorators like require_GET, require_POST etc.
Is there any solutions for Django or any extension to do it?
Thanks.
Yes it can be done using django middleware.
Use Process Request to intercept the requests.
It should return either None or an HttpResponse object. If it returns
None, Django will continue processing this request, executing any
other process_request() middleware, then, process_view() middleware,
and finally, the appropriate view. If it returns an HttpResponse
object, Django won't bother calling any other request, view or
exception middleware, or the appropriate view; it'll apply response
middleware to that HttpResponse, and return the result.
HttpRequest has a path attribute which contains the url. Use that url to lookup the urlconf and check the urlconf params for the accept-method and return None or the same HttpResponse accordingly.
#Pratik Mandrekar thanks for definitive information and documentation.
I've created a small application which does this kind of job https://github.com/imanhodjaev/django-besmart-common
Besides the root url request, which will be sent to a view, I want to have a dispatcher that I will route all the requests to different views which I will chose depending on my custom dispatcher's rules.
How can I create a dispatcher? I have read the docs over and over again yet I can not figure it out.
I want to parse the *remainder of url and then dispatch the request accordingly.
Pyramid will dispatch the request to a view registered via add_view or view_config. If you want to dispatch this again to your own code, just remember that from Pyramid's perspective the renderer/permission defined on the original view will be used... so don't use those. The request effectively enters your Pyramid view, then you have your own mini-framework that will handle it from there.
I suggest thinking about how to dispatch things in the context of Pyramid views, for example the pyramid_rpc package does some cool stuff to dispatch to views based on the content in the body of an RPC request (not just the URL). See the custom predicate within add_jsonrpc_method to know what I'm talking about.
Anyway, assuming you still want to do your own thing, all you have to do is register a view in Pyramid for whatever pattern you want.
config.add_route('my_framework', '/foo/{the_rest:.*}')
#view_config(route_name='my_framework')
def my_framework_view(request):
url = request.matchdict['the_rest']
# do your frameworky stuff here
if url == 'foo/bar':
return some_other_view(request)
return HTTPNotFound()
Anyway, it should be clear that this is a framework on top of a framework and probably a code smell in a lot of cases.
It really depends on the structure or you URLS and your "custom dispatcher rules", but for many cases you can use URL traversal instead of URL dispatch to achieve what you want. Due to the fact that URL traversal uses __getitem__ method of the parent resource, where you can write normal Python code, it may allow you more flexibility.
Example: imagine you have the following URLS:
/food/banana
/food/potato
/food/tomato
/food/apple
and you want to have different views for fruit and vegetables. You can do something like this:
class FoodResource(object):
def __getitem__(self, name):
if name in ["banana", "apple"]:
return FruitResource(self, name)
if name in ["potato", "tomato"]:
return VegetableResource(self, name)
then you can register views for FruitResource and VegetableResource:
#view_config(context=FruitResource):
def view_fruit(context, request):
...
#view_config(context=VegetableResource):
def view_vegetable(context, request):
...
You can have different sets of views registered for Fruits and Vegetables, so /foor/banana/make_jam and /food/apple/make_jam will be vaild URLs for fruits only, and for vegetables you'll have, say, /food/potato/make_soup:
#view_config(context=FruitResource, name="make_jam"):
def view_fruit_make_jam(context, request):
...
#view_config(context=VegetableResource, name="make_soup"):
def view_vegetable_make_soup(context, request):
...
Then your FruitResource and VegetableResource can have their own __getitem__ methods, so you can have potentially different sets of "subitems" - /food/banana/skin, /food/banana/flesh etc, with their own views assigned to them - /food/banana/skin/peel, /food/banana/flesh/eat, where peel and eat are views registered for imaginary FruitSkinResource and FruitFleshResource.
And you can have custom permissions for fruits and vegetables, so accessing /food/apple/make_jam may require one permission and /food/potato/make_soup another.
I think you could use pyramid's event system docs this is looks like hack but I think it is the easiest way.