I' m using django-allauth to authenticate users from different social sites. When a User is created in my db, i' d like to call a function which would create a UserProfile (or would do something) and to achieve this the best would be to use signals.post_save .
I' ve multiple django applications and of course i don' t want to change the core django-allauth, so my question where do i place my post_save code?
Thanks.
You could create an accounts app locally to hold the UserProfile and everything associated with it. The you could have:
# Connecting to AllAuth Signals
from allauth.account.signals import user_signed_up
from django.dispatch import receiver
#receiver(user_signed_up)
def new_user_signup(sender, **kwargs):
p = UserProfile(user = kwargs['user'])
p.save()
Related
I have a OneToOneField between my UserTrust model and django.contrib.auth.models.User that I would like to create whenever a new User registers. I thought on creating the UserTrust instance using the user_signed_up signal.
I have the following code in my AppConfig
def ready(self):
# importing model classes
from .models import UserTrust
#receiver(user_signed_up)
def create_usertrust(sender, **kwargs):
u = kwargs['user']
UserTrust.objects.create(user=u)
... and this is in my pytest test
#pytest.fixture
def test_password():
return 'strong-test-pass'
#pytest.fixture
def create_user(db, django_user_model, test_password):
def make_user(**kwargs):
kwargs['password'] = test_password
if 'username' not in kwargs:
kwargs['username'] = str(uuid.uuid4())
return django_user_model.objects.create_user(**kwargs)
return make_user
#pytest.mark.django_db
def test_my_user(create_user):
user = create_user()
assert user.usertrust.available == 1000
Still, the test fails with
django.contrib.auth.models.User.usertrust.RelatedObjectDoesNotExist: User has no usertrust.
What did I miss?
The problem with you creating the user via the django_user_model is that it doesn't actually pass through the allauth code that actually sends that signal. You've got two options:
Use a client (since I'm assuming you're using pytest-django) and fill out a registration via the allauth provided link for registering new users. That way, a signal is sent, and you can assert attributes and model instances like that.
You can simply ignore the signal and unittest the function itself. That's it. You put your trust in that single registration view not changing at all and put your trust in the package that the API will not change. I can still recommend this option, but you've been warned.
You can send the signal yourself. Not recommended in case allauth's API changes, but you could just import the signal from allauth and send it like this: user_signed_up.send(sender=self.__class__, toppings=toppings, size=size) where user_signed_up is the signal. Ref the docs: https://docs.djangoproject.com/en/dev/topics/signals/#sending-signals
Again, definitely recommend the first one in case of API changes. I can also recommend the second option just because allauth is pretty reputable and you know what going to happen without too huge of an package change, but you never know.
I want to create a new user's login and random/same password using CSV file using the ImportExport module Django. I've tried many examples but for no use. Can you please suggest anything? I've even tried to make password field in the import csv file. Let me know any tutorial/link that you can share to achieve this.
If you're looking to populate the database with dummy data, there is a module called faker in python.
Here is a small code snippet showing how you can use faker:
import os
# Configure settings for project
# Need to run this before calling models from application!
os.environ.setdefault('DJANGO_SETTINGS_MODULE','(YOUR DJANGO PROJECT).settings')
import django
# Import settings
django.setup()
import random
from (YOUR DJANGO APP).models import User
from faker import Faker
fakegen = Faker()
def populate(N=5):
for entry in range(N):
# Create Fake Data for entry
fake_name = fakegen.name().split()
fake_first_name = fake_name[0]
fake_last_name = fake_name[1]
fake_email = fakegen.email()
# Create new User Entry
user = User.objects.get_or_create(first_name=fake_first_name,
last_name=fake_last_name,
email=fake_email)[0]
if __name__ == '__main__':
print("Populating the databases...")
populate(20)
print('Populating Complete')
django-import-export contains several hooks which you can use to manipulate data prior to insertion in the db. This seems like the ideal way to generate a random password for each user.
You can combine this with Django's make_random_password() function. It doesn't seem like a good idea to have passwords in the import spreadsheet, but maybe you need to do that for some reason.
You will need to create your own Resource subclass, and override the before_save_instance(), for example:
class UserResource(resources.ModelResource):
def before_save_instance(self, instance, using_transactions, dry_run):
pw = User.objects.make_random_password()
instance.set_password(pw)
class Meta:
model = User
fields = ('id', 'username', 'password')
import_id_fields = ['id']
I have djoser integrated on my django project, and I need to create a stripe customer_id on account activation, how can I do this?
I've been searching on djoser doc, but there is nothing about customizing activation, or passing a callback method.
Djoser provides user_activated signal. It is usable just like ordinary django signal.
It's undocumented but working.
Example usage
from django.dispatch import receiver
from djoser.signals import user_activated
#receiver(user_activated)
def my_handler(user, request):
# do what you need here
I'm using Allauth module for create accounts and signing in. But I'm also need to create a new directory for every user, who makes an account.
I know that I need to use Signals some how... But cant find a start point for that.
Am I need to create new model, view or whatever? Or what I need to do to complete this task?
You need a post_save signal for the User model.
from django.db.models.signals import post_save
from django.contrib.auth.models import User
def create_folder(sender, instance, created, **kwargs):
if not created: # if it's not a new object return
return
# do your stuff
post_save.connect(create_folder, sender=User)
I have the requirement that whenever there is a model get's added/changed/deleted, it should send a mail notification. The content will be more like the django_admin_log entries. I just need to extend this functionality in my model to send the mail. Any suggestions?
Django_log_admin will only track changes made in the admin interface. If the model is changed anywhere else, it will not update the log. However, if you are OK with just admin changes, then you can use a combination of django_log_admin and the post_save signal to do the trick. Put this in your management.py:
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.admin.models import LogEntry
from django.core.mail import mail_admins
from django.template.loader import render_to_string
#will be triggered every time a LogEntry is saved i.e. every time an action is made.
#receiver(post_save, sender=LogEntry)
def send_notification_email(change, **kwargs):
mail_admins(subject="model %(model) has been changed by %(user)" %
{'model':change.content_type, 'user': change.user},
message = render_to_string('change_email.html', { 'change': change }) )
note to self: wow, django really includes all the batteries :D
You should look at Django's signals. In your case, you'll connect your handlers to the post_save and post_delete signals, for starters. Look through the built-in signal documentation for others you may want to tap. No need to hack into admin.