2

I'm creating a small saas for learning purposes... I know that the best way to go is to have a separate schema for each user... But my saas is a small app and I really don't need separate schemas plus it would complicate stuff (later alterations to the schema)... So I'm going to use the same schema for all users and just append each user's ID to the entry and then display only the user's entries upon login.

Is there a way I can "prepend" user's ID upon login through middleware? Or do I need to adjust all the queries (filter by user's ID)? I already store the user's ID to his entries... so I need this only for select's.

Thank you!

Mission
  • 1,287
  • 3
  • 16
  • 31
  • 1
    I don't know of any way to automatically filter querysets based on request.user. This is because the ORM is not coupled with django.contrib.auth. I did both SaaS designs, one database for all and manual filtering on all querysets (no django.contrib.admin), and one with one database per user which makes it easy to enable django.contrib.admin (also with admindoc and django-dbtemplates). I prefer the later although it's more work concerning system administration. – jpic Jan 05 '12 at 10:11
  • @jpic: Please post your answer as an answer so we can upvote and comment on it. – S.Lott Jan 05 '12 at 10:47

1 Answers1

2

I don't know of any way to automatically filter querysets based on request.user. This is because the ORM is not coupled with django.contrib.auth.

I tried two SaaS designs:

  1. 1 database for all sites, and manual filtering on all querysets. Of course this made django.contrib.admin not possible out of the box. It might be possible to enable django.contrib.admin with a really tight setup of django-authority or maybe even other django per-object permission packages (google cached version because djangopackages.com is down ATM).

  2. 1 database per site, that's just easier, keeps the code cleaner, and enables django.contrib.admin out of the box, which can be really cool if you install a django admin theme. Also I enabled django.contrib.admindoc as well as django-dbtemplates.

(Apparently in your case, 1 site = 1 user, but the concept is the same)

I prefer the second implementation because it's obviously a lot less development work, which is compensated by a little system administration.

jpic
  • 32,891
  • 5
  • 112
  • 113
  • Do you have any recommendation for option #2. I don't really need subdomains... it's a small learning project... So I would need to change schema upon user login... – Mission Jan 05 '12 at 12:21
  • For option #2 short answer: I recommend a server with root access, uWSGI+nginx for deployment because it supports multi-site django apps in a pretty elegant way: all you have to do is configure it once for N clients. It doesn't matter what database server or linux distribution you choose - you can always automate creation of databases. If you want I can open source the app and configuration we have so that you can reproduce it - later today or tomorrow. The only "issue" i ran into is that i didn't find a multi-site background job manager (ie. ztaskd) yet but in most cases you don't need it. – jpic Jan 05 '12 at 15:04
  • You can do things like filtering all query sets based on request.user by overriding the model's manager with one which specifies that filter; thus, `Thingy.objects.all()` would tie you to the current request user. Alternatively, you could give it an extra manager, such that you would use `Thingy.objects_for_user.all()` or similar. – Chris Morgan Jun 06 '13 at 07:22
  • How exactly would you pass request.user to `all()` ? – jpic Jun 06 '13 at 09:24