On Oct 24, 2017 3:46 AM, "Andréas Kühne" <[email protected]> wrote:

Hi all,

I would love to pick your collective brains for a second. I am working on
an application that will be first and foremost an administration system. As
such there will be very few users in the system. It will have a front end
developed in angular 5 and a Django rest framework backend.

I have got the solution up and running currently and it works as I think it
should. However - now I have another idea that I would like to hear your
opinions on.

Connected to this system we will also have other portals where a user will
be able to login - NOT the same user as the user that logs onto the
administration system - but an entirely different concept (a participant).
These portals will probably be running on another machine (but not
necessarily) and can have their own user concept. This application will
also be more of a traditional Django project with a standard view and
template driven design.

I am thinking about creating the Participant model separate from the User
(they are different concepts) and therefore was wondering if it would be
possible to create the Participant model based on an AbstractUser from
django contrib auth and then in the portal project use that as the user
model?


Short answer is yes, with caveats, but it may not be recommended.

The long answer: There's no technical reason that a model defined in one
project cannot serve as a reference for another project. The common code
just needs to be accessible from both projects. This works the same way as
any other Python library, because after all, Django models are just Python
code.

There are logical and design issues with doing it, though. A change in the
Admin project for the abstract user model will now propagate to the
Participant project, possibly in a negative way. You'll need to execute
tests for both your Admin and Participant projects whenever changes are
made to that model. Adding new features is usually easy, but deprecating
code can be a nightmare, as you now have two code bases that need to be
analyzed rather than one. You've also directly coupled the two projects
together from a semantic versioning standpoint. Even with no changes to the
Participant project, a change to the abstract model in the Admin project
now forces a migration for the Participant project (if a field is
modified), and likely a version bump for the Participant project so that
those running your software pick up the changes, even though there were no
modifications made to the Participant project itself.

I'd ask how important it is that these two models be coupled in such a way?
Granted, adding common fields between the two is handy, but for the reasons
above, it can be dangerous. It's likely that the Admin project only needs a
very small subset of the fields that the Participant project needs, and the
Admin app has no use for any of the authentication/authorization backend
functionality that gets dragged along with AbstractUser.

Has anyone every done anything similar? Is this idea completely wrong? Any
other things that I should think about?


Yes, in the sense that developing a 3rd party app for both projects is
effectively what you are doing. These are the same issues faced by 3rd
party app developers for Django, where a 1-line change in a 3rd party
module requires a migration for anyone that is using the app.

It's not necessarily wrong, there are just a number of issues to consider
with the coupling between the projects that you'll be creating.


My main reason behind this idea is that the applications will share the
database, but be completely different projects and shouldn’t necessarily
share a web app? Is this also a wrong idea or does this sound sane?


When you say 'share the database', are you referring to the same database
server but separate database instances? Or are you expecting both projects
to access the same tables in the same database instance?


All of those issues aside, I wouldn't start with an abstract model
inheriting from AbstractUser. I would create a clean abstract model
inheriting from models.Model, and copy everything from AbstractUser over to
your new abstract user model. Your Admin project would then define a
concrete user model that inherits directly from your new abstract user
model. Over in the Participant project, your concrete model would inherit
from the abstract model created in the Admin project, and also
from AbstractBaseUser and the PermissionsMixin, just like AbstractUser
does. This way, you have a single model controlling what fields are made
available in both applications, but only the Participant project model
contains the extra machinery to use that model to authenticate/authorize
users. The copy/paste operation probably violates DRY for some purists, but
you'll likely be modifying those fields at some point anyway, so I consider
it a necessary evil.

IMO, the number of fields that actually need to be shared between the
projects is quite small (less than a dozen), and likely will not change
often (hopefully), so the headache of having both coupled to the same
abstract class is not worth it for me. Having a note in each user model
reminding me to update the other would likely be sufficient, so I wouldn't
recommend doing this unless you plan on the base abstract model changing
dramatically over time where sync between the two projects may be
problematic.

I'm surprised that Django does not break out the AbstractUser fields like
username, etc. into a separate abstract model that does not inherit all of
the authentication backend functionality, as it forces a code copy for
situations like this. Maybe I should do a PR at some point, since that
wouldn't break any existing functionality.

-James

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/CA%2Be%2BciV9-mXKtrtGb4WXEsis%3D7ccsHmsivoBiLz80472RaZhyg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to