Locating lower level templates - python

Hi I am having problems with the template using Bottle
my folder structure is this:
|views
--main.tpl
--|blog
--home.tpl
what I want to do is this:
def home():
return template('blog/home')
but it won't work
I can get it to work just calling the following:
def home():
return template('main')
But I want to be-able to have many different folders
I understand that I will still need to keep unique names because of the caching
and please don't say use a different framework as this is not my choice.

You can try passing the template_lookup argument to the template function. template_lookup overrides the defaults .views path when looking for the template. However I believe this will only work if the name of the tempalte is not in the views folder. So if you had a /views/main.tpl and a /blog/main.tpl it would not work, every template needs a unique name. This is needed because bottle will only lookup search for tempaltes if it hasn't found it before and stores the found ones in a dict with the tempalte name as the key. so if the templates have the same name it would use the first one.
return template("home", template_lookup="full_path_to/views/blog/"

Related

Get all parameters and their values in a request in Django [duplicate]

I am currently defining regular expressions in order to capture parameters in a URL, as described in the tutorial. How do I access parameters from the URL as part the HttpRequest object?
My HttpRequest.GET currently returns an empty QueryDict object.
I'd like to learn how to do this without a library, so I can get to know Django better.
When a URL is like domain/search/?q=haha, you would use request.GET.get('q', '').
q is the parameter you want, and '' is the default value if q isn't found.
However, if you are instead just configuring your URLconf**, then your captures from the regex are passed to the function as arguments (or named arguments).
Such as:
(r'^user/(?P<username>\w{0,50})/$', views.profile_page,),
Then in your views.py you would have
def profile_page(request, username):
# Rest of the method
To clarify camflan's explanation, let's suppose you have
the rule url(regex=r'^user/(?P<username>\w{1,50})/$', view='views.profile_page')
an incoming request for http://domain/user/thaiyoshi/?message=Hi
The URL dispatcher rule will catch parts of the URL path (here "user/thaiyoshi/") and pass them to the view function along with the request object.
The query string (here message=Hi) is parsed and parameters are stored as a QueryDict in request.GET. No further matching or processing for HTTP GET parameters is done.
This view function would use both parts extracted from the URL path and a query parameter:
def profile_page(request, username=None):
user = User.objects.get(username=username)
message = request.GET.get('message')
As a side note, you'll find the request method (in this case "GET", and for submitted forms usually "POST") in request.method. In some cases, it's useful to check that it matches what you're expecting.
Update: When deciding whether to use the URL path or the query parameters for passing information, the following may help:
use the URL path for uniquely identifying resources, e.g. /blog/post/15/ (not /blog/posts/?id=15)
use query parameters for changing the way the resource is displayed, e.g. /blog/post/15/?show_comments=1 or /blog/posts/2008/?sort_by=date&direction=desc
to make human-friendly URLs, avoid using ID numbers and use e.g. dates, categories, and/or slugs: /blog/post/2008/09/30/django-urls/
Using GET
request.GET["id"]
Using POST
request.POST["id"]
Someone would wonder how to set path in file urls.py, such as
domain/search/?q=CA
so that we could invoke query.
The fact is that it is not necessary to set such a route in file urls.py. You need to set just the route in urls.py:
urlpatterns = [
path('domain/search/', views.CityListView.as_view()),
]
And when you input http://servername:port/domain/search/?q=CA. The query part '?q=CA' will be automatically reserved in the hash table which you can reference though
request.GET.get('q', None).
Here is an example (file views.py)
class CityListView(generics.ListAPIView):
serializer_class = CityNameSerializer
def get_queryset(self):
if self.request.method == 'GET':
queryset = City.objects.all()
state_name = self.request.GET.get('q', None)
if state_name is not None:
queryset = queryset.filter(state__name=state_name)
return queryset
In addition, when you write query string in the URL:
http://servername:port/domain/search/?q=CA
Do not wrap query string in quotes. For example,
http://servername:port/domain/search/?q="CA"
def some_view(request, *args, **kwargs):
if kwargs.get('q', None):
# Do something here ..
For situations where you only have the request object you can use request.parser_context['kwargs']['your_param']
You have two common ways to do that in case your URL looks like that:
https://domain/method/?a=x&b=y
Version 1:
If a specific key is mandatory you can use:
key_a = request.GET['a']
This will return a value of a if the key exists and an exception if not.
Version 2:
If your keys are optional:
request.GET.get('a')
You can try that without any argument and this will not crash.
So you can wrap it with try: except: and return HttpResponseBadRequest() in example.
This is a simple way to make your code less complex, without using special exceptions handling.
I would like to share a tip that may save you some time.
If you plan to use something like this in your urls.py file:
url(r'^(?P<username>\w+)/$', views.profile_page,),
Which basically means www.example.com/<username>. Be sure to place it at the end of your URL entries, because otherwise, it is prone to cause conflicts with the URL entries that follow below, i.e. accessing one of them will give you the nice error: User matching query does not exist.
I've just experienced it myself; hope it helps!
These queries are currently done in two ways. If you want to access the query parameters (GET) you can query the following:
http://myserver:port/resource/?status=1
request.query_params.get('status', None) => 1
If you want to access the parameters passed by POST, you need to access this way:
request.data.get('role', None)
Accessing the dictionary (QueryDict) with 'get()', you can set a default value. In the cases above, if 'status' or 'role' are not informed, the values ​​are None.
If you don't know the name of params and want to work with them all, you can use request.GET.keys() or dict(request.GET) functions
This is not exactly what you asked for, but this snippet is helpful for managing query_strings in templates.
If you only have access to the view object, then you can get the parameters defined in the URL path this way:
view.kwargs.get('url_param')
If you only have access to the request object, use the following:
request.resolver_match.kwargs.get('url_param')
Tested on Django 3.
views.py
from rest_framework.response import Response
def update_product(request, pk):
return Response({"pk":pk})
pk means primary_key.
urls.py
from products.views import update_product
from django.urls import path
urlpatterns = [
...,
path('update/products/<int:pk>', update_product)
]
You might as well check request.META dictionary to access many useful things like
PATH_INFO, QUERY_STRING
# for example
request.META['QUERY_STRING']
# or to avoid any exceptions provide a fallback
request.META.get('QUERY_STRING', False)
you said that it returns empty query dict
I think you need to tune your url to accept required or optional args or kwargs
Django got you all the power you need with regrex like:
url(r'^project_config/(?P<product>\w+)/$', views.foo),
more about this at django-optional-url-parameters
This is another alternate solution that can be implemented:
In the URL configuration:
urlpatterns = [path('runreport/<str:queryparams>', views.get)]
In the views:
list2 = queryparams.split("&")
url parameters may be captured by request.query_params
It seems more recommended to use request.query_params. For example,
When a URL is like domain/search/?q=haha, you would use request.query_params.get('q', None)
https://www.django-rest-framework.org/api-guide/requests/
"request.query_params is a more correctly named synonym for request.GET.
For clarity inside your code, we recommend using request.query_params instead of the Django's standard request.GET. Doing so will help keep your codebase more correct and obvious - any HTTP method type may include query parameters, not just GET requests."

Django - Liste index in template

I have a problem with my template.
I know how to use list.index to get a value from a list, but now my index value is list.container.id (=1).
So, I have stupidly try list.container.id and is not working like list.1.
Edit: As pointed out the old answer was wrong,
New Solution:
Create a custom filter tag.
In your app, create a python module called templatetags (create a folder and place an init.py file in it) then create a py file for your custom filter, for ex: my_custom_filter.py
from django import template
register = template.Library()
#register.filter
def index_my_list(my_list, index):
try:
return my_list[index]
except IndexError:
return None
Use in your template as
{{list|index_my_list:container.id}}
All this being said, it is best to keep your logical code in the view, you might want to reconsider your data structures
Wrong Solution:
Assign container.id to a variable then use it
{% with container.id as foo %}
{{list.foo}}

Exposing global data and functions in Pyramid and Jinja 2 templating

I have a base template for when a user is logged in, and on that base template, I need to add user specific options in a drop down menu. This drop down menu with options must be constant across all handlers, i.e., any time the base template is invoked (extended) with a child template.
Other than performing the necessary DB query, assigning the query results to a variable, and passing that variable to every handler (there are many), how can I consolidate this into one query and one variable, which gets passed directly to the base template? I am using jinja2 templates as well.
I would hate to do something so cumbersome in exchange for something far more simple and maintainable.
Any ideas? Thanks.
EDIT
So I still haven't found anything that's exactly what I'm looking for; however, I decided to at least make some headway in the interim. So, I made a custom decorator that takes a view's returned dict() and appends the appropriate data to it. For example:
def get_base_data(func):
def wrapper(request):
d = func(request)
user_id = request.user.id # used in query
contact_group_data = ContactGroups.query.filter(...criteria...).all()
d['contact_group_data'] = contact_group_data
return d
return wrapper
Now, I can at least decorate each method very concisely and simply by putting:
#view_config(...)
#get_base_data
def my_handler(request):
pass # rest of code...
This is one of most inobvious things in Pyramid and took a while to find for me, too.
You can modify the global template context in BeforeRender event.
http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/hooks.html#using-the-before-render-event
Alternatively, you could use class based views, inherit all your views from one base view class which has get_base_data(), then the class instance is passed to the template context to all your views and then you could extract the data with {{ view.get_base_data }}.
http://ruslanspivak.com/2012/03/02/class-based-views-in-pyramid/
I vouch for the latter approach as it is more beautiful, predictable and easier to maintain engineering wise.

How can I get a rewritten render_to_response to get a json in django with the least changes to the whole project

I now receive a task, that is developing a native app on phone based on a web project. So I think the best way to communicate between server and client is using json.
Then I need all the response give me a result of json format. But now in the web project, almost every view use render_to_response like the following:
ctxt = RequestContext(request,*args)
return render_to_response('XXX.html',ctxt)
Then I want rewrite render_to_response like below, so I need not to change every one to a new function:
def render_to_response:
return new HttpResponse(simplejson.dumps(*args), mimetype='text/json'))
Obviously, I can change the source code in django, but it's not a practicable method. Because other project also need use it.
Or I can write a new module with the render_to_response function, and import this after
from django.shortcuts import render_to_response
But I am not sure if this is possible.
If this can work, I also need to add this import into every .py files which is still a huge work.
So I want a best way with the least changes to the whole project.
Try replacing the return you have with this
return HttpResponse(json.dumps(ctxt), content_type="application/json")
On a different note, you do not really need to return the context if the client requesting it doesn't need it. You might be better of return a simple message like "Success"
Another solution is to include django-annoying in your project and use the #ajax_request decorator on all your views which want to respond as json.
#ajax_request
def my_view(request):
news = News.objects.all()
news_titles = [entry.title for entry in news]
return {'news_titles': news_titles}
Refer example here - https://bitbucket.org/offline/django-annoying/wiki/Home

Pyramid: add_static_view with name='directory/subdirectory'

I've just started learning Python recently and am using Pyramid as my web framework.
I'm trying to add a static view at localhost/images/misc:
config.add_static_view('images', 'C:/Project/Images/')
config.add_static_view('images/misc', 'C:/Path/To/Other/Images/')
But I get an error: File does not exist: C:/Project/images/misc
So it seems that the second line adding images/misc as a static view doesn't have any effect.
I've been searching for a while for a way to do this, but I haven't found anything. Is it possible to add a static view where the name contains a subdirectory? If so, how?
Under the hood, pyramid turns the name part of the add_static_view() method into a Pyramid route predicate of the form name/*subpath (where name can contain slashes itself). A dedicated static asset view is attached to that route predicate.
In your configuration that means there would be both images/*subpath and images/misc/*subpath route predicates, in that order. When you then request a URL with the path images/misc/foo.png Pyramid finds the images/*subpath predicate first, and tries to look up the misc path element in the 'C:/Project/Images/' folder, which fails.
Lucky for you, you can reverse the order of the registrations, simply register the images/misc path first:
config.add_static_view('images/misc', 'C:/Path/To/Other/Images/')
config.add_static_view('images', 'C:/Project/Images/')
Now the images/misc/*subpath predicate is registered first, and will match any images/misc/ URLs before the other predicate is tested.

Categories