A UserProfile model with Multiple Foreign Keys to 'auth.User' Breaks

627 views
Skip to first unread message

Matt Mansour

unread,
Mar 17, 2016, 10:00:42 PM3/17/16
to Mezzanine Users
Hi All -

Here's the relevant code in UserProfile model

class UserProfile(models.Model):
user = models.OneToOneField('auth.User', blank=True, null=True, related_name='userprofile')
owner = models.ForeignKey('auth.User', blank=True, null=True, related_name='subordinates')

When I makemigrations I get the following error:

'dashboard.UserProfile' has more than one ForeignKey to 'auth.User'.

The issue seems to be stemming from the mezzanine.accounts.admin profile inlines:

If I add :

fk_name = 'user'

to the body of the ProfileLineClass the issue is fixed.

try:
class ProfileInline(admin.StackedInline):
model = get_profile_model()
can_delete = False
template = "admin/profile_inline.html"
extra = 0
UserProfileAdmin.inlines += (ProfileInline,)
except ProfileNotConfigured:
pass

However, I am having a tough time sub classing ProfileInline. I can't seem to get it to work from my project.

Any suggestions on the sub classing approach would be greatly appreciated. Also, if this is an issue that should be posted in github please let me know. Not sure if this is a bug. 

Thanks

Avery Laird

unread,
Mar 18, 2016, 6:49:13 PM3/18/16
to Mezzanine Users
Hi Matt,

It might be useful if you explain what you're trying to do. For example, why do you need the foreign key relationship back to auth.User? I'm having trouble imagining a situation where you'd need both a OneToOne relationship and a ForeignKey relationship to the same model. Maybe you can accomplish your task a different way.

Matt Mansour

unread,
Mar 18, 2016, 8:16:52 PM3/18/16
to mezzani...@googlegroups.com

The additional foreignkey back to user is designated users who have permission to edit the profiles of only their  subordinates. These owners are non staff

On Mar 18, 2016 3:49 PM, "Avery Laird" <laird...@gmail.com> wrote:
Hi Matt,

It might be useful if you explain what you're trying to do. For example, why do you need the foreign key relationship back to auth.User? I'm having trouble imagining a situation where you'd need both a OneToOne relationship and a ForeignKey relationship to the same model. Maybe you can accomplish your task a different way.

--
You received this message because you are subscribed to the Google Groups "Mezzanine Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mezzanine-use...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Matt Mansour

unread,
Mar 18, 2016, 8:18:22 PM3/18/16
to mezzani...@googlegroups.com

Thanks for asking btw!

Avery Laird

unread,
Mar 18, 2016, 8:36:15 PM3/18/16
to Mezzanine Users
No problem! Mezzanine uses Django's permission system, which is probably the best way to go in this situation (if I understand what you're trying to do). See the documentation: "three default permissions – add, change and delete – are created for each Django model defined in one of your installed applications." You have the "subordinate" profile type, and a group of users that can edit the "subordinate" profile type. When creating a new user, Mezzanine displays these three default permissions for all models you have created. For example, I also have a custom User Profile class, so there is a permission displayed "<app label> | User Profile | Can add/change/delete User Profile |." That means, you can create a group which has only the permissions you want.

However, if you want to have the users arranged in a tier of some sort, which any relationship more complicated than what I described above, you may want to look in to creating your own groups/permissions. You can find the documentation here.

Matt Mansour

unread,
Mar 18, 2016, 8:53:38 PM3/18/16
to mezzani...@googlegroups.com

That sounds close but I'm not sure it's granular enough. For example an owner can only edit the profiles that has been assigned to him. E.g Owner A owns - and can only edit objects B, C and D. Owner E owns F G and H.  And yes both those owners can have a superior over them and should be able to edit the grandchildren and the owners. All of which are not staff

Matt Mansour

unread,
Mar 18, 2016, 8:57:22 PM3/18/16
to mezzani...@googlegroups.com

With that it seems like creating a custom permissions would be trivial with with foreign Keys pointing to User for the different ownership relationships

Avery Laird

unread,
Mar 19, 2016, 12:10:39 AM3/19/16
to Mezzanine Users
I see what you're saying, however I still think that groups are the way to go. I think the thing to remember is that, unless the grandchildren actually inherit from your UserProfile, they aren't really "grandchildren" in the sense you mean. They're just instances of the same class, but you want each instance to have different permissions. There is a section of the documentation which references this:

Permissions can be set not only per type of object, but also per specific object instance. By using the has_add_permission(), has_change_permission() and has_delete_permission() methods provided by the ModelAdmin class, it is possible to customize permissions for different object instances of the same type.

It also sounds like what you're really wanting to do is have the creation of one instance of a UserProfile with certain permissions trigger the creation of other instances with difference permissions. This can be achieved by extending the model constructor, with perhaps a method in the UserProfile class to spawn more children? The auth.User model is fairly complicated and, as far as I remember, makemigrations is throwing that ForeignKey error for good reason. However I could be wrong about this, perhaps someone else would be able to clear up things?

In any case, if you can get the ForeignKey method to work, that might very well be the easiest solution. If not, using groups should also work. Unfortunately, I don't know enough about the details of Django's auth backend to give you a definitive answer.
Reply all
Reply to author
Forward
0 new messages