pythondjangodjango-modelsdjango-signalsdjango-activity-stream

'property' object has no attribute '_meta' while using django-activity-stream package


I am using the django-activity-stream package to show activity stream. Everything worked fine, but I couldn't assign user as an actor. This is my signals.py file.

from actstream import action
from django.db.models.signals import post_save
from django.dispatch import receiver
from apps.teams.models import Team
from apps.users.models import User

@receiver(post_save, sender=Team)
def track_team_created(sender, instance, **kwargs):
    action.send(User, verb="create a team", target=instance)
    print("create a team")

In this case, I can create a team. However, when I see the actions I get the below error.

Field 'id' expected a number but got '<property object at 0x7f3804cf8540>'.

Ok. I get that. I need user's id. So, I tried to add User.pk instead just User. Now, I cannot even create a team with below error.

'property' object has no attribute '_meta'

I tried bunch of different ways. Like using User._meta.pk, settings.AUTH_USER_MODEL etc. but I couldn't solve this.

For the reference, User class is using AbstractUser

I am trying to solve this without touching the User Model because I have same issue in the other app, but this was in Model directly, so I could solve it easier.

def save(self, *args, **kwargs):
    super().save(*args, **kwargs)
    action.send(User(self.author).pk, verb="created a note title")

It was in models.py and it has class meta: and I could use self.author in User.

Here is the Traceback.

Environment:


Request Method: POST
Request URL: http://localhost:8000/admin/teams/create/

Django Version: 4.2.1
Python Version: 3.11.3
Installed Applications:
['whitenoise.runserver_nostatic',
 'django_unmigrate',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'admin_interface',
 'colorfield',
 'django.contrib.admin',
 'django.forms',
 'crispy_forms',
 'crispy_tailwind',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'django_celery_beat',
 'rest_framework',
 'rest_framework.authtoken',
 'corsheaders',
 'drf_spectacular',
 'hijack',
 'hijack.contrib.admin',
 'django_otp',
 'django_otp.plugins.otp_totp',
 'django_otp.plugins.otp_static',
 'allauth_2fa',
 'django_htmx',
 'import_export',
 'django_cleanup.apps.CleanupSelectedConfig',
 'column_toggle',
 'actstream',
 'apps.users',
 'apps.core',
 'apps.teams.apps.TeamConfig',
 'apps.markets.apps.MarketsConfig',
 'apps.companies.apps.CompaniesConfig',
 'apps.stock_screener.apps.StockScreenerConfig',
 'apps.custom_admin.apps.CustomAdminConfig',
 'apps.notes.apps.NotesConfig',
 'debug_toolbar',
 'django_extensions']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'whitenoise.middleware.WhiteNoiseMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django_otp.middleware.OTPMiddleware',
 'allauth_2fa.middleware.AllauthTwoFactorMiddleware',
 'apps.teams.middleware.TeamsMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.common.BrokenLinkEmailsMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'hijack.middleware.HijackUserMiddleware',
 'django_htmx.middleware.HtmxMiddleware',
 'apps.core.htmx_message_middleware.HtmxMessageMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware']



Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 486, in thread_handler
    raise exc_info[1]
    ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 486, in thread_handler
    raise exc_info[1]
    ^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
               
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 448, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/asyncio/tasks.py", line 442, in wait_for
    return await fut
           ^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/current_thread_executor.py", line 22, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/asgiref/sync.py", line 490, in thread_handler
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/contextlib.py", line 81, in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/auth/mixins.py", line 135, in dispatch
    return super().dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 143, in dispatch
    return handler(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/edit.py", line 184, in post
    return super().post(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/edit.py", line 153, in post
    return self.form_valid(form)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/messages/views.py", line 12, in form_valid
    response = super().form_valid(form)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/generic/edit.py", line 135, in form_valid
    self.object = form.save()
                  ^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/forms/models.py", line 542, in save
    self.instance.save()
    ^^^^^^^^^^^^^^^^^^^^
  File "/app/apps/teams/models.py", line 61, in save
    super().save(*args, **kwargs)  # Call the "real" save() method.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/model_utils/models.py", line 38, in save
    super().save(*args, **kwargs)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 814, in save
    self.save_base(
    ^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 892, in save_base
    post_save.send(
    ^
  File "/usr/local/lib/python3.11/site-packages/django/dispatch/dispatcher.py", line 176, in send
    return [
           
  File "/usr/local/lib/python3.11/site-packages/django/dispatch/dispatcher.py", line 177, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/apps/custom_admin/signals.py", line 45, in track_team_created
    action.send(User.pk, verb="create a team", target=instance)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/dispatch/dispatcher.py", line 176, in send
    return [
           
  File "/usr/local/lib/python3.11/site-packages/django/dispatch/dispatcher.py", line 177, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/actstream/actions.py", line 118, in action_handler
    actor_content_type=ContentType.objects.get_for_model(actor),
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/contenttypes/models.py", line 41, in get_for_model
    opts = self._get_opts(model, for_concrete_model)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/contenttypes/models.py", line 28, in _get_opts
    model = model._meta.concrete_model
            ^^^^^^^^^^^

Exception Type: AttributeError at /admin/teams/create/
Exception Value: 'property' object has no attribute '_meta'

Solution

  • In your signals.py you write:

    action.send(User.pk, verb='create a team', target=instance)

    Here User is not even a User object, but the User class, so User.pk is a property defined on a class.

    You can work with the .author if I understand the modeling correctly:

    @receiver(post_save, sender=Team)
    def track_team_created(sender, instance, **kwargs):
        action.send(instance.author, verb='create a team', target=instance)
        print('create a team')