If I create an application and some controller, by default I will access it using:
http:// 127.0.0.1/application/controller/function
I want to change the behaviour of the URLs that I can access any controller by not asking for the application part. Using my example, I want to be able to access all the controllers of my app like this:
http:// 127.0.0.1 /application/controller/function1
http:// 127.0.0.1 /application/controller2/function2
http:// 127.0.0.1 /application/controller2/function3 (and etc.)
What I want to do is remove the need to indicate the application to be able to access all my controllers like this:
http:// 127.0.0.1/controller/function1
http:// 127.0.0.1/controller2/function2
http:// 127.0.0.1/controller2/function3 (and etc.)
Modifying my routes.py:
# routes.py
default_application = 'application'
default_controller = 'controller'
default_function = 'index'
I can access http://127.0.0.1/ and I am redirected to http://127.0.0.1/controller/index
But If I try to access other function I need to indicate the application.
I didn't find a good reference about how routes.py can be configured, and I think that I have to change this file to get what I want.
Anyone can help me?
Thanks!
The web2py URL rewrite functionality is explained in the book. Note, you have a choice between the newer (and simpler) parameter-based system and an alternative pattern-based system (which provides some additional flexibility for more complex cases). In your case, the parameter-based system would be easiest -- just include the following in your routes.py file:
routers = dict(
BASE = dict(
default_application = 'application',
default_controller = 'controller',
),
)
If you need additional help, I would recommend asking on the web2py mailing list.
Related
I am working on a python package which speaks with an API (using HTTP protocol).
In my package I have a python configuration file that contains the API URL (hardcoded) and other settings.
The API URL is saved in a global variable so I could import it and use it in my package modules. For example:
API_URL = "https://api-url.com"
The configuration file is part of the package, that means once that a user installs the package he also gets the configuration file including the hardcoded URL.
The problem is that in some point in the future the API's URL could change, and all the factuality's of the package will break, and the users will have to update (i.g. pip install etc.) the package.
What is the right way to handle hardcoded URLs in a package?
The common pattern here is to not hardcode the URL base, but instead provide a API class that will get instantiate with the corresponding URL. This class can also get additional config/a config file:
class MyAPI:
def __init__(self, config_file: str = DEFAULT_CONFIG, **overrides):
self.config = build_config(config_file, overrides)
self.url = self.config.url
#property
def value(self):
return requests.get(urljoin(self.url, "./value"))
The user would then use it like this:
api = MyAPI()
print(api.value)
or
api = MyAPI(url="NEW_URL")
print(api.value)
This is as example similar to what praw and wikipedia use.
This is an especially good idea if there are different URL that can be used with the same/a very similar Interface. (Often at least the live product + a test sandbox)
You can design your API so that URIs don't change. This might be achieved using versioning, e.g. serving your API at https://api-url.com/v1 instead of https://api-url.com. In this case users
won't have to update or change anything because any changes to the API won't affect them since the changes will exist only in the newer version of you API served at https://api-url.com/v2.
Another option is to force library clients to pass the URL they want to use. This will solve the issue with hardcoding but won't solve the root cause. API usually change because something has changed in the understanding of the domain, which in turn means there are likely more changes than URLs alone (which will break your library anyway).
In case you think you simply might want to change domain name and don't anticipate any other changes that might affect clients you can use redirect from old URL to the new one.
Please tell me whether it is possible (if so, how) to use for pages each user subdomains. For example, now I have a URL of the form: http://hostname.com/user/1 I need to get http://username.hostname.com/
You have a number of options depending on how in-depth you want to go.
One option is to handle the routing at the web server level. Basically you will capture the subdomain part of the URL and rewrite it to a different location within your server.
For example http://username1.local.host/signin will be captured by your webserver and internally routed to a resource such as /username1/signin. The end user will subdomains but your code will handle url parts be none the wiser as to what has happened.
Your urls.py will then handle this like any normal request.
url_pattern = [
...
url(r'(?P<subdomain>[a-z]+)/sigin/$', 'view'),
]
For Nginx you will need to look into "subdomain to subdirectory re-writing".
I would personally use this option for what you have stated in your question. Whilst this method is a little more tricky to setup initially (keep at it until it works). It will be a lot easier to maintain and work with in the long run.
The other option is to handle the subdomains at the django level using a package such as Django Subdomains (I have used this one in the past and found it to be my preferred option (in terms of handling subdomains within django code)).
Without going into too much detail nginx will capture the subdomains and route all of it to django. Django will then handle the subdomains at the middleware level.
Personally I would use option 1 for your usage. Option 2 is if you want different apps on different domains for example: blog.local.host, support.local.host.
Consider using django-hosts
From docs:
# For example, if you own example.com but want to serve
# specific content at api.example.com and beta.example.com,
# add the following to a hosts.py file:
from django_hosts import patterns, host
host_patterns = patterns('path.to',
host(r'api', 'api.urls', name='api'),
host(r'beta', 'beta.urls', name='beta'),
)
I have a django project which is running (for example) on localhost:8000.
I have an image in this address localhost:8000/static/test.jpg . A user may open just this image by going to it's url and not open the containing page.
I want to find out if this image is loaded in a user's browser (by loading the containing page or just entering the image's url) and I want to get the request object of that request.
Can I have a method in my views just for that specific image? I searched through the internet but didn't find anything useful. any idea or solution?
Are you talking about disallowing hotlinking? This can be easier - and more effectively - done with the webserver that runs in front of your Django server.
For some examples for Apache check out https://wiki.apache.org/httpd/DisableImageHotLinking
This can be only by serving your images with your custom views. E.g you should write your own view that will return static resources, and you will not use a standard django static handler
First of all, please note that serving static files in a production environment should not be handled by Django in the first place. From contrib/staticfiles/views.py:
Views and functions for serving static files. These are only to be used during
development, and SHOULD NOT be used in a production setting.
If you do want to use this, then you could write a custom middleware hooking into process_view or process_request to do your stuff in.
I did it finally. for example i have a file in localjost:8000/media/1.jpg and i want to get ip of the user who enters this url to load the 1.jpg.
I added this line in my urls :
url(r'^media/(?P<path>.*)$', 'project.views.serve','document_root': settings.MEDIA_ROOT,}), and i set the MEDIA_ROOT already. then in project.views.serve i called django.views.static.serve and i returned the result of that as a HttpResponse. i have a request argument in my project.views.serve and i did this to get the user's ip from that :
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[-1].strip()
else:
ip = request.META.get('REMOTE_ADDR')
print ip
Your way goes fine but bot for a high traffic. In that case you can use XSendFile library witch works with Apache
I can't, for the life of me, get Django to find my JavaScript files! I am trying to plug in a custom widget to the admin page, like so:
class MarkItUpWidget(forms.Textarea):
class Media:
js = (
'js/jquery.js',
'js/markitup/jquery.markitup.js',
'js/markitup/sets/markdown/set.js',
'js/markitup.init.js',
)
css = {
'screen': (
'js/markitup/skins/simple/style.css',
'js/markitup/sets/markdown/style.css',
)
}
However, when this code is inserted on my admin page, all of the links are broken, I can't get to any of my JavaScript files. My settings file looks like this: http://pastebin.com/qFVqUXyG
Is there something I am doing wrong? I'm somewhat new to Django.
I guess you're using django-admin runserver to test your website. In that case, have a look at "How to serve static files" (but don't ignore the big fat disclaimer).
Once you're ready to deploy, this chapter contains all the information (provided you go the standard route of Apache/mod_wsgi)
I don't know what the "django way" to include js files is, but I just use a simple regular include in the template, its great since you can dynamically generate the location / filename for these.. oh and if you are using django's test server I don't know how to get it to recognize these or if it even can but all you need is to run an apache server on your local machine and then put the files in the localhost directory and you can include them through localhost by including their full path in the template (i.e., http://localhost/myfiledirectory/myfile.js), also something I do is use amazon s3 to host files since you then get a url for them on there (not that you asked about this but its a quick way to host files if you don't have apache running locally)
Basically, my understanding of Django is that it works differently than a PHP framework, for example, as the files for Django don't sit (or don't need to at least) in the web path (i.e. they do not need to be accessible through the host path but can be anywhere on the machine) this is good for providing extra security, etc but it also means, that to give files a url to download them they need to be in the web hosting path, others may know how to make django do this directly but my quick and dirty method of putting them on the localhost path will work if thats all you're after.
I've got a webapp running on CherryPy that needs to access the CherryPy config files before a user creates a request. The docs say to use:
host = cherrypy.request.app.config['database']['host']
But that won't work outside of a user request. You can also use the application object when you start the app like so:
...
application = cherrypy.tree.mount(root, '/', app_conf)
host = application.config['database']['host']
...
But I can see no way of accessing 'application' from other classes outside of a user request.
I ask because our app looks at several databases and we set them up when the app starts rather than on user request. I have a feeling this would be useful in other places too; so is there any way to store a reference to 'application' somewhere or access it through the CherryPy API?
You can access it via the same cherrypy.tree object using the script name (minus the trailing slash):
application = cherrypy.tree.apps['']
host = application.config['database']['host']
However, as alluded to in other answers there are likely better ways to structure your code.
is there any way to store a reference to 'application' somewhere...
Just use normal Python. For a package called 'myapp':
# __init__.py
...
application = cherrypy.tree.mount(root, '/', app_conf)
...
# notarequest.py
import myapp
host = myapp.application.config['database']['host']
However, I would recommend using config to set up your database objects, and then inspect those database objects instead of inspecting the config.