Using subdomains in django - python

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'),
)

Related

Flask: share sessions between domain.com and username.domain.com

I have a flask running at domain.com
I also have another flask instance on another server running at username.domain.com
Normally user logs in through domain.com
However, for paying users they are suppose to login at username.domain.com
Using flask, how can I make sure that sessions are shared between domain.com and username.domain.com while ensuring that they will only have access to the specifically matching username.domain.com ?
I am concerned about security here.
EDIT:
Later, after reading your full question I noticed the original answer is not what you're looking for.
I've left the original at the bottom of this answer for Googlers, but the revised version is below.
Cookies are automatically sent to subdomains on a domain (in most modern browsers the domain name must contain a period (indicating a TLD) for this behavior to occur). The authentication will need to happen as a pre-processor, and your session will need to be managed from a centralised source. Let's walk through it.
To confirm, I'll proceed assuming (from what you've told me) your setup is as follows:
SERVER 1:
Flask app for domain.com
SERVER 2:
Flask app for user profiles at username.domain.com
A problem that first must be overcome is storing the sessions in a location that is accessible to both servers. Since by default sessions are stored on disk (and both servers obviously don't share the same hard drive), we'll need to do some modifications to both the existing setup and the new Flask app for user profiles.
Step one is to choose where to store your sessions, a database powered by a DBMS such as MySQL, Postgres, etc. is a common choice, but people also often choose to put them somewhere more ephemeral such as Memcachd or Redis for example.
The short version for choosing between these two starkly different systems breaks down to the following:
Database
Databases are readily available
It's likely you already have a database implemented
Developers usually have a pre-existing knowledge of their chosen database
Memory (Redis/Memchachd/etc.)
Considerably faster
Systems often offer basic self-management of data
Doesn't incur extra load on existing database
You can find some examples database sessions in flask here and here.
While Redis would be more difficult to setup depending on each users level of experience, it would be the option I recommend. You can see an example of doing this here.
The rest I think is covered in the original answer, part of which demonstrates the matching of username to database record (the larger code block).
Old solution for a single Flask app
Firstly, you'll have to setup Flask to handle subdomains, this is as easy as specifying a new variable name in your config file. For example, if your domain was example.com you would append the following to your Flask configuration.
SERVER_NAME = "example.com"
You can read more about this option here.
Something quick here to note is that this will be extremely difficult (if not impossible) to test if you're just working off of localhost. As mentioned above, browsers often won't bother to send cookies to subdomains of a domain without dots in the name (a TLD). Localhost also isn't set up to allow subdomains by default in many operating systems. There are ways to do this like defining your own DNS entries that you can look into (/etc/hosts on *UNIX, %system32%/etc/hosts on Windows).
Once you've got your config ready, you'll need to define a Blueprint for a subdomain wildard.
This is done pretty easily:
from flask import Blueprint
from flask.ext.login import current_user
# Create our Blueprint
deep_blue = Blueprint("subdomain_routes", __name__, subdomain="<username>")
# Define our route
#deep_blue.route('/')
def user_index(username):
if not current_user.is_authenticated():
# The user needs to log in
return "Please log in"
elif username != current_user.username:
# This is not the correct user.
return "Unauthorized"
# It's the right user!
return "Welcome back!"
The trick here is to make sure the __repr__ for your user object includes a username key. For eg...
class User(db.Model):
username = db.Column(db.String)
def __repr__(self):
return "<User {self.id}, username={self.username}>".format(self=self)
Something to note though is the problem that arises when a username contains special characters (a space, #, ?, etc.) that don't work in a URL. For this you'll need to either enforce restrictions on the username, or properly escape the name first and unescape it when validating it.
If you've got any questions or requests, please ask. Did this during my coffee break so it was a bit rushed.
You can do this with the builtin Flask sessions, which are cookie-based client-side sessions. To allow users to login to multiple subdomains in '.domain.com', you need only to specify
app.config['SESSION_COOKIE_DOMAIN'] = '.domain.com'
and the client's browser will have a session cookie that allows him to login to every Flask instance that is at 'domain.com'.
This only works if every instance of Flask has the same app.secret_key
For more information, also see
Same Flask login session across two applications

How to find out if an image is loaded?

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

Url rewriting in GAE

Do you know if it's possible to get an url rewrited using GAE and Python in a way that it appears different in also the domain part?
So, for example,
www.aaa.appspot.com to www.bbb.com ??
This is not Url rewriting, it's custom domains which are supported on GAE.
If you want to have requests for .app-id.appspot.com handled differently to .app-id.appspot.com you can use webapp2's DomainRoute. The same would apply to or example.com vs example2.com if you had two custom domains pointing to your app.
See: http://webapp-improved.appspot.com/guide/routing.html#domain-and-subdomain-routing
That way you can have one AppEngine app that handles requests for both example.com and example2.com (or just handles redirects from example1.com to example2.com).

Default application in URL

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.

Django can't find my non-python files!

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.

Categories

Resources