Django signals not working on usercreation - python

I created a signals supposed to create a profile for each created users in my signals.py file but it's not working. I've tried to check if there's an error with the command python manage.py check, but that seems not to work as well.
models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_pic = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f"{self.user.username}'s profile "
signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from .models import Profile
#receiver(post_save, sender=User)
def create_profile(sender, created, instance, **kwargs):
if created:
Profle.instance.create(user=instance)
#receiver(post_save, sender=User)
def create_profile(sender, instance, **kwargs):
instance.profile.save()
apps.py
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
What am I doing wrong?

The order of parameters in your signal handler is wrong, change:
def create_profile(sender, created, instance, **kwargs):
to:
def create_profile(sender, instance, created, **kwargs):
Check the post_signal documentation for further details.

The problem is from how i installed the users app in the settings.py file in the main project directory.
i used :
INSTALLED_APPS = [
'users',
]
**instead of **
INSTALLED_APPS = [
'users.apps.UsersConfig',
]

Related

No module named 'signals' in Django Project

I'm practice Django and I'm trying to make function
( Ready ) in the app.py and import
( users.signals ) into this function and I already used
pip install signals to install signals package and didn't solve it yet.
apps.py
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
signals.py
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
No module named 'signals'

Access Django custom user profile field

I added a custom user profile field role with the following models.py.
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
ROLE_CHOICES = (
(792, 'Student'),
(172, 'Teacher'),
(864, 'Supervisor'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
role = models.IntegerField(choices=ROLE_CHOICES, null=True, blank=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
What is the best way to return the int value assigned to the role? For example if the current logged in user is assigned the role of "Teacher", I want to be able to use the 172 value elsewhere like in views.py.
Currently logged in user is request.user, so
request.user.profile.role
will return 172, and
request.user.profile.get_role_display()
will return "Teacher". Note that you should omit parentheses if you are using the latter in a template.

Django signals not working when placed outside models.py

I'm trying to print some text after Django model in an app has been saved.
I have created a signal for that in a signals.py file in the same application.
However, it's not working as expected (i.e., the function is not being called and text is not being printed)
But if I place the receiver function in the models.py file just below the model that I created, it's working fine (i.e., the function is being called and text has been printed)
I have gone through the documentation to check if there is any need to place the signals in a specific file or location. It looks like there isn't any such restriction.
https://docs.djangoproject.com/en/3.0/topics/signals/#django.dispatch.receiver
Why is this behaving differently if there is no such restriction?
signals.py:
from django.db.models.signals import post_save
from django.dispatch import receiver
from aws_envs.models import UserStack
#receiver(post_save, sender=UserStack)
def create_user_stack(sender, **kwargs):
print("creating user stack now")
models.py:
class UserStack(BaseModel):
name = models.CharField(max_length=50)
email = models.EmailField(unique=True, max_length=50, blank=False)
enabled = models.BooleanField(default=True)
def save(self, *args, **kwargs):
print(f"Creating stack with data: {self.name, self.email}")
super(UserStack, self).save(*args, **kwargs)
def __str__(self):
return self.name, self.email
in INSTALLED_APPS you should register like this:
'post.apps.PostConfig'
I.e. in settings.py replace
INSTALLED_APPS = (
'...',
'post,
)
with
INSTALLED_APPS = (
'...',
'post.apps.PostConfig',
)
in apps.py you shoud add these:
from django.apps import AppConfig
class postConfig(AppConfig):
name = 'post'
def ready(self):
# signals are imported, so that they are defined and can be used
import post.signals
created a file in app's folder
# post/signals.py
from django.dispatch import receiver
from django.db.models.signals import post_save
from post.models import Post
def send():
print("send email!")
#receiver(post_save, sender=Post, dispatch_uid='Post_post_save')
def send_email(instance, **kwargs):
send()

Django | How to reference the User's username when using OneToOneField in UserProfile?

Here's my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class Userprofile(models.Model):
user = models.OneToOneField(User, primary_key=True)
username = user.__unicode__()
path = './data/'+username+'/'
file = models.FileField(upload_to=path)
labelfile = models.FileField(upload_to=path, blank=True)
def __unicode__(self):
return u"%s" % self.user.username
def create_user_profile(sender, instance, created, **kwargs):
if created:
Userprofile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
the problem is:
AttributeError: 'OneToOneField' object has no attribute 'model'
I want a file upload function that it can save in a index related to the User's name, but I can't find a good way to do it. And I hope someone can help me. Thanks.

Django adding a custom field to registration

I'm trying to add additional field for user's profile which can be edited only by administrator.
When I try to save a new value of city in an administration module I'm getting an error:
global name 'created' is not defined
This error comes from:
signals.py in create_profile, line 7
I described what I have done till now :)
I started a new app profil
In models.py
from django.db import models
from django.contrib.auth.models import User
from django.utils.encoding import smart_str
class UserProfile(models.Model):
"""Model przechowujący dodatkowe informacje o użytkowniku"""
user = models.ForeignKey(User, unique=True)
city = models.CharField(max_length=255, verbose_name=u'Miasto', blank=True, null=True)
class Meta:
verbose_name = 'Profil użytkownika'
verbose_name_plural = 'Profile użytkowników'
def __unicode__(self):
return u'%s' self.user.username
def __str__(self):
return smart_str('%s' % self.user.username)
import profil.signals
In file: signals.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from profil.models import UserProfile
def create_profile(sender, instance, **kwargs):
if created == True:
UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_profile, sender=User)
forms.py
from django import forms
from profil.models import UserProfile
class UserProfileForm(forms.ModelForm):
'''Formularz modelu UserProfile'''
class Meta:
model = UserProfile
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from profil.forms import UserProfileForm
from profil.models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
fk_name = 'user'
max_num = 1
form = UserProfileForm
class UserProfileAdmin(UserAdmin):
inlines = [UserProfileInline, ]
admin.site.unregister(User)
admin.site.register(User, UserProfileAdmin)
In your signals.py you are using created but is not defined yet.
So, you can get it from kwargs using this kwargs.get('created')
Fianlly, you create_profile function should looks like this.
def create_profile(sender, instance, **kwargs):
if kwargs.get('created',None):
UserProfile.objects.get_or_create(user=instance)
You can use:
def create_profile(sender, instance, **kwargs):
if kwargs.get('created', False) ...
or
def create_profile(sender, instance, created, **kwargs):
if created == True:

Categories