Django url based multi database - django

I need to write users into two databases. I decided to send them to different url.
For example: /register/dbone/ and /register/dbsecond/ and then get request.url and separate them.
But in Router two functions db_for_read() and db_for_write() do not know anything about request object and url.
How best to solve this? This is done because of the safe storage of data, so the initial storage of users in the first database is not possible.
P.S. Maybe there is some other way to separate users into two databases, not url but something else?

I can't provide a definitive answer, because I can't see all of your code, but the django docs show that db_for_read() and db_for_write() are actually called like:
db_for_read(model, **hints) and db_for_write(model, **hints) where hints are basically kwargs where, quoting django: hints received by the database router can be used to decide which database should receive a given request.
You are going to need to pass in any data from your request object (or whatever else decides the db) into these hints.

Related

Django app has multiple database and multiple user

I have written one Django cloud based app. This app will have multiple user and for them multiple database, so that their data should be separate and they can save only to same database.
1) How can we implement it
2) How to automatically one user from login page to assign the database to write on it.
I don't have a complete answer, since you do not give a lot of detail. But here are a couple ots that f hinDjango supports custom database router implementations. A database router is a class that helps django decide which database to use for a particular model. Unfortunately I don't think this mechanism is granular enough for your needs. You can also specify the database to use in your code by using using(name) queryset method and save(using=name) form of save() method for instances. Of course this also means that some features of Django are going to be unvailable to you, since you cannot always expect to have a user. Look at the docs here for more info
https://docs.djangoproject.com/en/dev/topics/db/multi-db/

Django - load new objects via ajax

In django app I need to periodically check for if new object of particular model are created.
I want to this by ajax.
I was thinking about something like this:
render current timestamp into template, load current objects.
Then, every x seconds do ajax request and ask for objects which are created later then this timestamp.
What do you think? Is there maybe a better way?
What you want is a way for the client to know whether something has changed in the server. Generally there are three ways to stimulate this subscriber/broadcaster, or pull/push, relationship. The first is Ajax long-polling, which is roughly what you described. The second is implemented via WebSocket, which unfortunately not all browser supports. The third is HTTP streaming, or a long polling at the HTTP level. All three are available in https://github.com/ziyan/django-comet
A newer technology is Webhooks, which allows you to subscribe to server changes via URL (http://en.wikipedia.org/wiki/Webhook). Check it out here for an early Django adaptation: https://github.com/johnboxall/django_webhooks

Django: preventing external query string requests

I've been doing web development for a few months now and keep having this nagging problem. It is typical for pages to request content with a query string which usually contains meaningful data such as an id in the database. An example would be a link such as:
http://www.example.com/posts?id=5
I've been trying to think of a good strategy to prevent users from manually entering a value for the id without having accessed it from a link--I'd only wish to acknowledge requests that were made by links presented on my website. Also, the website may not have an authentication system and allows for anonymous browsing; that being said, the information isn't particularly sensitive but still I don't like the idea of not being able to control access to certain information. One option, I suppose, would be to use HTTP POST requests for these kind of pages -- I don't believe a user can simulate a post request but I may be wrong.
Furthermore, the user could place any arbitrary number for the id and end up requesting a record that doesn't exist in the database. Of course, I could validate the requested id but then I would be wasting resources to accommodate this check.
Any thoughts? I'm working with django but a general strategy for any programming language would be good. Thanks.
First, choosing between GET and POST: A user can simulate any kind of request, so POST will not help you there. When choosing between the two it is best to decide based on the action the user is taking or how they are interacting with your content. Are they getting a page or sending you data (a form is the obvious example)? For your case of retrieving some sort of post, GET is appropriate.
Also worth noting, GET is the correct choice if the content is appropriate for bookmarking. Serving a URL based solely on the referrer -- as you say, "prevent users from manually entering a value for the id without having accessed it from a link" -- is a terrible idea. This will cause you innumerable headaches and it is probably not a nice experience for the user.
As general principle, avoid relying on the primary key of a database record. That key (id=5 in your case) should be treated purely as an auto-increment field to prevent record collisions, i.e. you are guaranteed to always have a unique field for all records in the table. That ID field is a backend utility. Don't expose it to your users and don't rely on it yourself.
If you can't use ID, what do you use? A common idiom is using the date of the record, a slug or both. If you are dealing with posts, use the published/created date. Then add a text field that will hold URL friendly and descriptive words. Call it a slug and read about Django's models.SlugField for more information. Also, see the URL of an article on basically any news site. Your final URL will look something like http://www.example.com/posts/2012/01/19/this-is-cool/
Now your URL is friendly on the eyes, has Google-fu SEO benefits, is bookmark-able and isn't guessable. Because you aren't relying on a back-end database fixed arbitrary ID, you have the freedom to...restore a backup db dump, move databases, change the auto-increment number ID to a UUID hash, whatever. Only your database will care, not you as a programmer and not your users.
Oh and don't over-worry about a user "requesting a record that doesn't exist" or "validating the requested id"...you have to do that anyway. It isn't consuming unnecessary resources. It is how a database-backed website works. You have to connect the request to the data. If the request is incorrect, you 404. Your webserver does it for non-existent URLs and you'll need to do it for non-existent data. Checkout Django's get_object_or_404() for ideas/implementation.
There are two ways I know of to do this effectively, since there is basically no way to stop someone from forging any request.
The first is not to use bare IDs in the query parameters. Instead, generate a large random number, and make the link out of that. You will have to keep a table in your database mapping your random numbers to the actual IDs they represent, and you will have to clean the table eventually. This is fairly simple to implement, but requires some storage space, and some management of the stored data occasionally.
The second method is to sign the data when you make a link. By appending a cryptographic signature to the data, and verifying the signature when a request is made, you ensure that only your web service could possibly have created the link. Even if the request itself is 'forged' -- perhaps bookmarked, written down, copy-and-pasted into another browser -- you know that your site has already authorized that URL.
To do this, you need to create a Message Authentication Code (MAC) with the data that you are signing (say, just the 'id' value, or possibly the id and the time that you signed the data) and with a secret key that you keep only on your server.
In your view, then, you take the id value (or id and timestamp, if that's what you're using) and you construct the MAC again, and see if they match. If there's any difference, you reject the request as having been tampered with.
Look at the python docs for the hmac module, as well as the hashlib module for all of the details.
You could generate a link in python like this:
settings.py:
hmac_secret_key = '12345'
views.py:
import time, hmac, hashlib
from django.conf import settings
def some_view(request):
...
id = 5
time = int(time.time())
mac = hmac.new(
settings.hmac_secret_key,
'%d/%d' % (id, time),
hashlib.sha1)
url = 'http://www.example.com/posts/id=%d&ts=%d&mac=%s' % (
id, time, mac.hexdigest())
# Now return a template with that url in it somewhere
To verify it in another view, you would use code like this: (warning, warning, not robust, lots of error checking still to do)
def posts_view(request):
id = int(request.GET['id'])
ts = int(request.GET['ts'])
mac_from_url = request.GET['mac']
computed_mac = hmac.new(
settings.hmac_secret_key,
'%d/%d' % (id, time),
hashlib.sha1)
if mac_from_url <> computed_mac:
raise SomeSecurityException()
# Now you know that the request is legit.
# You can check the timestamp here, too, if you like.
I don't know if this is the correct way of doing it but maybe you can save the url he is going to be redirected after the GET request into the session, and write a decorator so that if the session has that url take him to that page. else give a 404 error or something.

Django request paths

I've been working through an issue with my django project. The issue is I've got one project, which will retrieve data for users of different clients. I need to know 'from where' a viewer is coming from (request.path [my original solution]). I've been looking at a number of different options which sound close to what I want to do, but I'm not sure what the best option is, not having done this before.
My first option was to add a url in the urls.py with a 'tag' or 'keyword' then look for that tag/keyword in the request.path, which I'd add as a session key. Then go onto get the data.
Something else I started looking at was the sites framework. After reading through the documentation, I'm still confused how sites actually works, so I'm not sure if this is the right option.
Another solution talked about using middleware, this came up in connection with the research into using the sites framework.
And then yet another talked about doing this in apache.
Could some one help point me in the right direction?
Cheers,
T
If you need to know from which URL came your user to your currrent page you should check the REFERER http header, available in request.META.get('HTTP_REFERER').
See http://docs.djangoproject.com/en/1.2/ref/request-response/#ref-request-response for more informations.
Be careful though, the referer meta is not mandatory and could be missing due to private browsing or direct access to the page from the URL bar.
It's not completely clear from your question, but if you're asking for the URL that the user was on before coming to the current page, you probably want request.META['HTTP_REFERRER'].
Edit after comment
That would be a very bad idea. Global variables are not safe given that you potentially have multiple requests being processed at the same time. The referrer is already available from the request, which can be accessed in all views and templates, so I don't know what else a middleware would give you.

How to host 50 domains/sites with common Django code base

I have 50 different websites that use the same layout and code base, but mostly non-overlapping data (regional support sites, not link farm). Is there a way to have a single installation of the code and run all 50 at the same time?
When I have a bug to fix (or deploy new feature), I want to deploy ONE time + 1 restart and be done with it.
Also:
Code needs to know what domain the request is coming to so the appropriate data is displayed.
The Sites framework comes to mind.
Apart from that we have Django running for multiple sites by symlinking Django to various docroots. Works like a charm, too.
I can see two quite distinct ways to do this:
Use one database and the sites framework. Every post/picture/whatever model is connected to a Site and you always filter on Site. This requires a separate settings file for every database.
Use one database for each and every site. This allows different users for every site, but requires duplication of everything that is stored in the database. It also requires a separate settings file pointing to the correct database.
Either way, you do not duplicate any code, only data.
--
If you need to do site-specific, or post-specific changes to ie. a template, you should read up on how Django loads templates. It allows you to specify a list, ie ["story_%d.html", "story_site_%d.html", "story.html"] and django will look for the templates in that order.
I just ran into this and ended up using a custom middleware class that:
Fetch the HTTP_HOST
Clean the HTTP_HOST (remove www, ports, etc.)
Look up domain in a Website table that's tied to each account.
Set the account instance on the HTTPRequest object.
The throughout my view code I do lookups based on the account stored in the HTTPRequest objects.
Hope that helps someone in the future.