Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using django user authentication & taggit for multiple apps in a single project

Background: I have 5 independent Django projects which I am attempting to combine in to 1 Django project composed of several apps. In other words: projA has appA, projB has appB & projC has appC, etc. I want 1 masterProj that has appA, appB & appC.

Currently each app connects to it's own independent database (the apps don't share data). Each project uses Django user authentication, Django registration, taggit, profiles, comments and sorl-thumbnail.

I'm using Django 1.4 and setup database routing according to this stackoverflow answer so that, once combined into one project, each app in the newly combined Django project is still able to connect to its own database. That went smoothly, but I started running into trouble with things like user authentication and taggit:

1) As mentioned before, each app connects to a different database and each of those databases has a table named 'auth_user'. However, I've found that all read/write calls to the auth_user table (regardless of which app makes the read/write call) are routed to the default database (in this case appA's database):

# settings.py:
DATABASES['default'] = DATABASES['appA']
DATABASE_ROUTERS = ['appA.db.DBRouter', 'appB.db.DBRouter', 'appC.db.DBRouter']

# appA/dbrouterA.py (appB, appC routers are identical this, replacing 'appA' with 'appB', etc.)
class DBRouter(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'appA':
            return 'appA'
        if model._meta.app_label == 'auth':
            return 'appA'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'appA':
            return 'appA'
        if model._meta.app_label == 'auth':
            return 'appA'
        return None

2) Assuming I get the routing working, if a user logs into appA, I don't want them to be logged into appB. I have seen many people post the reverse question (they want their apps to share user credentials) but has anyone successfully used Django user authentication in several independent apps in the same project? If so, how did you do this?

3) I get the following error from my taggit code, but I haven't been able to figure out how to pass the "related_name" parameter to taggit. I'm using the basic implementation of taggit - not subclassing anything:

# appA/models.py
tags = TaggableManager(blank=True)

# appB/models.py
tags = TaggableManager(blank=True)

Error:

appA.userprofile: Accessor for m2m field 'tagged_items' clashes with related m2m field 'TaggedItem.userprofile_set'. Add a related_name argument to the definition for 'tagged_items'.
appB.userprofile: Accessor for m2m field 'tagged_items' clashes with related m2m field 'TaggedItem.userprofile_set'. Add a related_name argument to the definition for 'tagged_items'.

4) I'm starting to get the feeling that combining all these apps is a slippery slope; that later down the line I might run into problems with sorl-thumbnail or comments that haven't surfaced yet. Has anyone successfully combined apps into a single project? Or am I trying to do something that Django doesn't fundamentally support?

Thanks in advance for the help!

like image 504
jewelia Avatar asked May 24 '12 21:05

jewelia


People also ask

How does Django handle login?

In a nutshell, these four commands create a new Django project named src, enter the project, create a new app, mysite, inside the src project, then create a SQLite database for the project named db. sqlite3. Also be sure to include the mysite app inside src/settings.py. INSTALLED_APPS = [ 'src', 'django.

How do I add login requirements in Django?

Create an app folder in the django project folder. Add template folder in the django folder and provide its path in django_folder > settings.py . Create file named as urls.py in the app folder and provide its path in django_project > urls.py. Add login decorator to the function in app_folder > views.py.

How does Django session authentication work?

After logging in, the server validates the credentials. If valid, it generates a session, stores it, and then sends the session ID back to the browser. The browser stores the session ID as a cookie, which gets sent anytime a request is made to the server. Session-based auth is stateful.


1 Answers

Django's architecture is designed to revolve around a Django project and several Django applications. The project itself is nothing more than your settings and main URL configuration module, while the applications are simple packages that follow a few file conventions.

Now, the applications themselves are never coupled to a particular project (they can be coupled to other applications by referencing them, though). The idea is to allow you to retain the freedom to design how your project's sources are structured and one approach that's common for most Django projects out there is to distribute Django applications under the project's top-level package, like most Python applications. This approach makes it convenient to get a holistic view of all the features a project provides (when you apply meaningful application labeling), to create namespaces and provides the developers a convenient and organized path of access to particular project sources.

This works great both for large projects and when you want to collocate and merge several different projects that reuse similar designs and approaches across. While this is going to affect only how your project is structured, choosing whether or not you'll have a configuration for a single Django project or several Django projects for your fixed set of Django applications has some important ramifications.

When you create a Django project, your basically plugging in Django applications in to the framework's instrumentation and exposing application behavior, as we understand it in Web applications, by configuring and including mapping patterns for URLs and views from your Django applications.

The point is that you can reorganize the sources in any way that works for you. Your packages can be organized like proj.appA, proj.appB, etc. or proj.common1, proj.common2, proj.projA.app1, proj.projA.app2, proj.projB.app1, it's really up to you.

What you should know is that you don't need a single settings and URL module and resort to database routing and managing database connections, you may just as well have a settings and URL module for each project, that reference different applications and expose different behavior. With per project database settings, your already reusing code and keeping the database data and state distinct for each project at the same time.

like image 112
Filip Dupanović Avatar answered Sep 21 '22 21:09

Filip Dupanović