Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

version 2 stable? #203

Open
specialorange opened this issue Sep 17, 2020 · 11 comments
Open

version 2 stable? #203

specialorange opened this issue Sep 17, 2020 · 11 comments
Labels

Comments

@specialorange
Copy link

I updated all pip packages ( https://stackoverflow.com/questions/2720014/how-to-upgrade-all-python-packages-with-pip [oops] ) which uses this package, and I've run into problems. Everything was working on v 1.1.1, and I am now getting some weird errors:

  • some dealing with having to include empty Meta classes on the Account/Organization/User models
  • some dealing with having to include empty raw_id_fields = () admin models for Account/Organization/User
  • here are some errors that the runserver prevented from running, migrating, or making migrations
<class 'accounts.admin.AccountOwnerAdmin'>: (admin.E002) The value of 'raw_id_fields[0]' refers to 'organization_user', which is not an attribute of 'accounts.AccountOwner'.
<class 'accounts.admin.AccountOwnerAdmin'>: (admin.E002) The value of 'raw_id_fields[1]' refers to 'organization', which is not an attribute of 'accounts.AccountOwner'.
<class 'accounts.admin.AccountOwnerAdmin'>: (admin.E108) The value of 'list_display[0]' refers to 'organization', which is not a callable, an attribute of 'AccountOwnerAdmin', or an attribute or method on 'accounts.AccountOwner'.
<class 'accounts.admin.AccountUserAdmin'>: (admin.E002) The value of 'raw_id_fields[0]' refers to 'user', which is not an attribute of 'accounts.AccountUser'.
<class 'accounts.admin.AccountUserAdmin'>: (admin.E002) The value of 'raw_id_fields[1]' refers to 'organization', which is not an attribute of 'accounts.AccountUser'.
<class 'accounts.admin.AccountUserAdmin'>: (admin.E108) The value of 'list_display[0]' refers to 'user', which is not a callable, an attribute of 'AccountUserAdmin', or an attribute or method on 'accounts.AccountUser'.
<class 'accounts.admin.AccountUserAdmin'>: (admin.E108) The value of 'list_display[1]' refers to 'organization', which is not a callable, an attribute of 'AccountUserAdmin', or an attribute or method on 'accounts.AccountUser'.
accounts.AccountUser: (models.E012) 'unique_together' refers to the nonexistent field 'organization'.
accounts.AccountUser: (models.E012) 'unique_together' refers to the nonexistent field 'user'.
accounts.AccountUser: (models.E015) 'ordering' refers to the nonexistent field, related field, or lookup 'organization'.
accounts.AccountUser: (models.E015) 'ordering' refers to the nonexistent field, related field, or lookup 'user'.

Notes

  • My code is based using the Abstract classes.
  • rolling back to 1.1.1 and everything works
  • up to date Django and Python

From what I can tell, and based on it working in 1.1.1, my models are set up correctly (I'm happy to show you if you'd like to see them). Is 2.0.0 only partially ready for use or is there some upgrade step I might have missed?

@bennylope
Copy link
Owner

Is 2.0.0 only partially ready for use or is there some upgrade step I might have missed?

More likely that it is ready but that I missed something with regard to upgrade.

I think what you've shared here is sufficient (thank you for the detail) to start investigating. I've used a precursor to the final 2.0.0 release for quite a while now, but it was not an upgrade from 1.x.

@bennylope bennylope added the bug label Sep 17, 2020
@bennylope
Copy link
Owner

Actually I'll walk that back a bit @specialorange:

(I'm happy to show you if you'd like to see them).

If you want to share your models here or via email that'd make it easier for me!

@specialorange
Copy link
Author

Yes I would like it a lot. I plan on fixing some of the issues I think I can tackle in the coming weeks. You have helped me in the past, and I think I can finally contribute! :)

Current working v1

# admin.py
from organizations.base_admin import (BaseOwnerInline,
                                      BaseOrganizationAdmin,
                                      BaseOrganizationUserAdmin,
                                      BaseOrganizationOwnerAdmin)

class OwnerInline(BaseOwnerInline):
    model = AccountOwner
    # raw_id_fields = ()
@admin.register(Account)
class AccountAdmin(BaseOrganizationAdmin):
    list_display = ['slug', 'is_active', 'name', 'mgr', 'labor_rate',
                    'number_of_vendors', 'vendors_names', 'number_of_clients',
                    'clients_names', ]
    inlines = [OwnerInline, ServiceInline]
    inlines = [ServiceInline]
    formfield_overrides = {models.ManyToManyField: {'widget': SelectMultiple(attrs={'size': '10'})}, }
@admin.register(AccountUser)
class AccountUserAdmin(BaseOrganizationUserAdmin):
    list_display = ['user', 'organization', 'user_type', ]
    # list_display = ['user_type', ]
    # raw_id_fields = ()
@admin.register(AccountOwner)
class AccountOwnerAdmin(BaseOrganizationOwnerAdmin):
    # raw_id_fields = ("organization_user", "organization")
    list_display = ['organization', ]
    # raw_id_fields = ()

# models.py
from organizations.abstract import (AbstractOrganization,
                                    AbstractOrganizationUser,
                                    AbstractOrganizationOwner)

class AccountUser(AbstractOrganizationUser):
    user_type = models.CharField(max_length=1, default='', blank=True, null=True)
    def __str__(self):
        return str(self.user)
    # class Meta(object):
        # pass
class Account(AbstractOrganization):
    mgr = models.ForeignKey(AccountUser, on_delete=models.DO_NOTHING, blank=True, null=True)
    …
    # Several unrelated methods
    # def number_of_clients(self):
        # return self.vendor_to.filter(vendor=self.pk).count()
class AccountOwner(AbstractOrganizationOwner):
    # acct = models.ForeignKey(Account, on_delete=models.CASCADE, related_name='owner')
    def __str__(self):
        return str(self.organization_user)

    # class Meta(object):
        # pass

The v2 code is most of the commented out lines

@DimasInchidi
Copy link

+1 seems like the module registry thingy here not working properly. On my case the relationship not created.
CustomOrganization doesnt have attribute owner

@iMerica
Copy link

iMerica commented Oct 4, 2020

I'm seeing the following when running makemigrations

3c3732bc1d26:/app$ ./manage.py makemigrations
SystemCheckError: System check identified some issues:

ERRORS:
core.User: (models.E012) 'unique_together' refers to the nonexistent field 'organization'.
core.User: (models.E012) 'unique_together' refers to the nonexistent field 'user'.
core.User: (models.E015) 'ordering' refers to the nonexistent field, related field, or lookup 'organization'.
core.User: (models.E015) 'ordering' refers to the nonexistent field, related field, or lookup 'user'.

@iMerica
Copy link

iMerica commented Oct 4, 2020

Update:
I was able to get around this issue by changing the order of classes in multiple inheritance.

class User(AbstractUser, AbstractOrganizationUser):
 pass

@robd003
Copy link

robd003 commented Oct 20, 2020

@bennylope I was trying to upgrade to django-organizations 2.0 for the openwisp-users project but I'm having the same issue as seen above.

Do you have any suggestions on how to fix this? Errors below:

<class 'openwisp_users.admin.OrganizationOwnerAdmin'>: (admin.E002) The value of 'raw_id_fields[0]' refers to 'organization_user', which is not an attribute of 'openwisp_users.OrganizationOwner'.
<class 'openwisp_users.admin.OrganizationOwnerAdmin'>: (admin.E002) The value of 'raw_id_fields[1]' refers to 'organization', which is not an attribute of 'openwisp_users.OrganizationOwner'.
<class 'openwisp_users.admin.OrganizationOwnerAdmin'>: (admin.E108) The value of 'list_display[1]' refers to 'organization', which is not a callable, an attribute of 'OrganizationOwnerAdmin', or an attribute or method on 'openwisp_users.OrganizationOwner'.
<class 'openwisp_users.admin.OrganizationOwnerInline'>: (admin.E202) 'openwisp_users.OrganizationOwner' has no ForeignKey to 'openwisp_users.Organization'.
<class 'openwisp_users.admin.OrganizationUserAdmin'>: (admin.E002) The value of 'raw_id_fields[0]' refers to 'user', which is not an attribute of 'openwisp_users.OrganizationUser'.
<class 'openwisp_users.admin.OrganizationUserAdmin'>: (admin.E002) The value of 'raw_id_fields[1]' refers to 'organization', which is not an attribute of 'openwisp_users.OrganizationUser'.
<class 'openwisp_users.admin.OrganizationUserAdmin'>: (admin.E108) The value of 'list_display[0]' refers to 'user', which is not a callable, an attribute of 'OrganizationUserAdmin', or an attribute or method on 'openwisp_users.OrganizationUser'.
<class 'openwisp_users.admin.OrganizationUserAdmin'>: (admin.E108) The value of 'list_display[1]' refers to 'organization', which is not a callable, an attribute of 'OrganizationUserAdmin', or an attribute or method on 'openwisp_users.OrganizationUser'.
<class 'openwisp_users.admin.OrganizationUserInline'>: (admin.E202) 'openwisp_users.OrganizationUser' has no ForeignKey to 'openwisp_users.User'.
openwisp_users.OrganizationUser: (models.E012) 'unique_together' refers to the nonexistent field 'organization'.
openwisp_users.OrganizationUser: (models.E012) 'unique_together' refers to the nonexistent field 'user'.
openwisp_users.OrganizationUser: (models.E015) 'ordering' refers to the nonexistent field, related field, or lookup 'organization'.
openwisp_users.OrganizationUser: (models.E015) 'ordering' refers to the nonexistent field, related field, or lookup 'user'.

@bennylope
Copy link
Owner

The short of the issue (or one of the issues) above is that in version 2.0 some of these field names/related names are dynamically named to be relevant to the underlying model. E.g. for a model named AccountUser the field name is going to be account_user now instead of organization_user.

Going to have to think through how to either (a) make this more configurable or (b) create a smooth upgrade path.

@eelkevdbos
Copy link

eelkevdbos commented Nov 4, 2020

@bennylope We experienced the same unique_together warnings although we did not use a custom model name like @specialorange. However, after looking at organizations/models.py we decided to also implement the OrganizationInvitation class and poof! all errors were gone.

This is our working model config, if anyone interested:

class Organization(AbstractOrganization):
    class Meta(AbstractOrganization.Meta):
        abstract = False

class OrganizationUser(AbstractOrganizationUser):
    # only allow one org per user
    user = models.ForeignKey(
        User, related_name="%(app_label)s_%(class)s", on_delete=models.CASCADE, unique=True
    )

    class Meta(AbstractOrganizationUser.Meta):
        abstract = False

class OrganizationOwner(AbstractOrganizationOwner):
    class Meta(AbstractOrganizationOwner.Meta):
        abstract = False

class OrganizationInvitation(AbstractOrganizationInvitation):
    class Meta(AbstractOrganizationInvitation.Meta):
        abstract = False

@n11c
Copy link

n11c commented Nov 11, 2020

Same here, I'm using custom models based on abstract classes and after upgrading to 2.0.0 I started seeing errors mentioning missing foreignkeys on the OrgOwner or OrgUser models.
Adding a concrete model for invitations (based on AbstractOrganizationInvitation) solved it as suggested by @eelkevdbos (thanks!)

@harikvpy
Copy link

harikvpy commented Nov 28, 2020

Encountered the same problem. After a bit of digging into the source, the problem is line 104 in base.py, the one goes if all([cls.module_...]):

            if key:
                cls.module_registry[module][key] = model

        if all([cls.module_registry[module][klass] for klass in base_classes]):
            model.update_org(module)
            model.update_org_users(module)

which requires that all the abstract models to be overridden if model customization is required. That is, AbstractOrganization, AbstractOrganizationUser, AbstractOrganizationOwner & AbstractOrganizationInvitation. Only then would the dynamic field name injection mechanism would work. In my case I was not overriding the AbstractOrganizationInvitation initially.

The sample code in the docs here omits the AbstractOrganizationInvitation model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants