jazzband / django-simple-history

Store model history and view/revert changes from admin site.
https://django-simple-history.readthedocs.org
BSD 3-Clause "New" or "Revised" License
2.21k stars 479 forks source link

Error when requesting User.history.all () #926

Closed ascendantnr closed 1 year ago

ascendantnr commented 2 years ago

I have a model class User (AbstractUser), I would like to keep track of the User history, I have an error while getting User.history.all (),

ERROR: table "core_user" is missing from the FROM clause LINE 1: SELECT "core_user". "Id", "core_user". "Password", "core_user" ...

SELECT "core_user"."id", "core_user"."password", "core_user"."last_login", ' '"core_user"."is_superuser", "core_user"."username", ' '"core_user"."first_name", "core_user"."last_name", "core_user"."email", ' '"core_user"."is_staff", "core_user"."is_active", "core_user"."date_joined", ' '"core_user"."editor_config", "dib_page_historicaluser"."ip_address", ' '"dib_page_historicaluser"."history_id", ' '"dib_page_historicaluser"."history_date", ' '"dib_page_historicaluser"."history_change_reason", ' '"dib_page_historicaluser"."history_type", ' '"dib_page_historicaluser"."history_user_id" FROM "dib_page_historicaluser" ' 'ORDER BY "dib_page_historicaluser"."history_date" DESC, ' '"dib_page_historicaluser"."history_id" DESC LIMIT 21')

core_user table it is my base_model, dib_page_historicaluser table it is history model, whoever knows can tell what the problem is, I'm a beginner

jeking3 commented 2 years ago

All of the fields coming from core_user will be replicated into dib_page_historicaluser on each modification. The query generated by User.history.all() should be using only dib_page_historicaluser. You didn't share your user model code, that may shed some light on the issue.

ascendantnr commented 2 years ago

Все поля, поступающие от core_user, будут реплицироваться в dib_page_historicaluser при каждой модификации. Запрос, сгенерированный User.history.all(), должен использовать только dib_page_historicaluser. Вы не предоставили код своей модели пользователя, что может пролить свет на проблему.

class User(AbstractUser): class Meta: verbosename = ("User") verbose_nameplural = ("Users")

modules = models.ManyToManyField(Module, blank=True, verbose_name=_('Modules'))
editor_config = JSONField(null=True, blank=True, default=dict, verbose_name=_('Editor configuration'))

groups = models.ManyToManyField(
    Group,
    verbose_name=_('groups'),
    blank=True,
    help_text=_(
        'The groups this user belongs to. A user will get all permissions '
        'granted to each of their groups.'
    ),
    related_name="user_set",
    related_query_name="user",
)

read_messages = models.ManyToManyField('documents.ChatHistory', related_name='readers',
                                       verbose_name=_('Read messages'))

analytics = GenericRelation(AnalyticSection)

def has_perm(self, perm, obj=None):
    """
    Return True if the user has the specified permission. Query all
    available auth backends, but return immediately if any backend returns
    True. Thus, a user who has permission from a single auth backend is
    assumed to have permission in general. If an object is provided, check
    permissions for that object.
    """
    # Active superusers have all permissions.
    if self.is_active and self.is_superuser:
        return True
    # Check if user has permission to the module
    if not self.has_module_perms(perm[:perm.index('.')]):
        return False
    # Otherwise we need to check the backends.
    return super(User, self).has_perm(perm, obj)

def has_module_perms(self, app_label):
    """
    Return True if the user has any permissions in the given app label.
    Use simlar logic as has_perm(), above.
    """
    # Active superusers have all permissions.
    if self.is_active and self.is_superuser:
        return True

    for module in self.modules.iterator():
        if module.label == app_label:
            return True
    return False

def get_editor_config(self):
    groups = self.groups.all()
    config = self.editor_config or {}
    for group in groups:
        _conf = group.get_editor_config()
        _tool = _conf.get('toolbar')
        if _tool:
            merged_tools = merge_editor_tools(config.get('toolbar', []), _tool)
            config.update({'toolbar': merged_tools})
            _conf.pop('toolbar')
        config.update(_conf)
    if not config:
        try:
            config = settings.SUMMERNOTE_CONFIG.get('summernote')
        except Exception:
            pass
    tool = config.get('toolbar', [])
    remove_tool(tool, 'print')
    if self.is_superuser:
        return config
    else:
        tool = config.get('toolbar', [])
        remove_tool(tool, 'codeview')
        return config

@property
def pretty_name(self):
    first = ""
    last = ""
    login = ""
    if self.first_name:
        first = self.first_name
    if self.last_name:
        last = self.last_name
    if self.username:
        login = self.username

    return "{} [{} {}]".format(login, first, last)

@property
def person_lastname(self):
    try:
        return self.person.last_name or ''
    except:
        return ''

@property
def person_firstname(self):
    try:
        return self.person.first_name or ''
    except:
        return ''

@property
def person_middlename(self):
    try:
        return self.person.middle_name or ''
    except:
        return ''

@property
def person_lastname_initials(self):
    try:
        first_name_i = self.person_lastname[0] + '.' if self.person_lastname else ''
        middle_name_i = self.person_middlename[0] + '.' if self.person_middlename else ''
        return '{} {} {}'.format(self.person_lastname, first_name_i, middle_name_i)
    except:
        return ''

@property
def person_fullname(self):
    try:
        person_fullname = '{} {} {}'.format(self.person_lastname, self.person_firstname, self.person_middlename)
        return person_fullname
    except:
        return ''
jeking3 commented 2 years ago

I haven't tried making my user table historic before, but it should behave like any other table from this perspective. My guess is you are using an older django-simple-history? I'd recommend you try to upgrade django-simple-history to 3.0 and see if the issue persists; if still there then try master. Don't forget to update migrations when switching versions.

ddabble commented 1 year ago

Closing stale issue.