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'
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')