"""I'm unable to access senders and **kwargs and this is my signals.py file and I guess is causing a bug that is when I login as admin its start showing admin details in my profile page too, please help me out as I'm new to Django"""
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)
def save_profile(sender, instance,**kwargs):
instance.profile.save()
[![enter image description here][3]][3]
the below image is of apps.py here is its showing users.signals is not accessed
[3]: https://i.stack.imgur.com/JxE5m.png
I have a view that returns data corresponded to the user, but when I try to find the User I get this error:
Type str has no object method
File views.py
from .models import Question, User
#api_view(['POST'])
#renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def answers_view(request, *args, **kwargs):
userstring = request.data["name"]
try:
user0 = User.objects.get(username=userstring)
except ObjectDoesNotExist:
user0 = "NotFound"
print("USER: ", user0, flush = True)
File models.py
from django.db import models
# Create your models here.
import random
from django.conf import settings
from django.db import models
from django.db.models import Q
User = settings.AUTH_USER_MODEL
The AUTH_USER_MODEL setting is a string, this is often used to refer to the user model, for example in a ForeignKey, the advantage of this is that at that moment, the user model does not have to be loaded (yet).
In order to get a reference to the model, you use the get_user_model() function [Django-doc]:
from .models import Question
from django.contrib.auth import get_user_model
#api_view(['POST'])
#renderer_classes((TemplateHTMLRenderer, JSONRenderer))
def answers_view(request, *args, **kwargs):
userstring = request.data['name']
try:
user0 = get_user_model().objects.get(username=userstring)
except ObjectDoesNotExist:
user0 = 'NotFound'
print('USER: ', user0, flush=True)
I am writing models and i want to access post from username directly in django views. Is it possible? the models.py file is as follows:-
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils import timezone
#this is how profile of a sample user, say MAX looks like
class Profile(models.Model):
Follwers=models.IntegerField(default='0')
user=models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
bio=models.TextField(max_length=120,blank=True)
location=models.CharField(max_length=30,blank=True)
birth_date=models.DateField(null=True,blank=True)
verified=models.BooleanField(default=False)
ProfilePic=models.ImageField(upload_to='UserAvatar',blank=True,null=True)
def __str__(self):
return self.user.username
#receiver(post_save,sender=User)
def update_user_profile(sender,instance,created,**kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
class post(models.Model):
Profile=models.ForeignKey(Profile,on_delete=models.CASCADE)
Picture=models.ImageField(upload_to='PostMedia',blank=True,null=True)
DatePosted=models.DateTimeField(default=timezone.now)
Content=models.TextField(blank=True,null=True)
def __str__(self):
return self.Profile.user.username
You can add this to views,
def get_queryset(self):
return post.objects.filter(Profile__user__username=self.kwargs['username'])
Modify it according to your kwargs, username or pk.
tasks.py
import string
from django.contrib.auth.models import User
from django.utils.crypto import get_random_string
from celery import shared_task
#shared_task
def create_random_user_accounts(total):
for i in range(total):
username = 'user_{}'.format(get_random_string(10, string.ascii_letters))
email = '{}#example.com'.format(username)
password = get_random_string(50)
User.objects.create_user(username=username, email=email, password=password)
return '{} random users created with success!'.format(total)
views.py
from django.contrib.auth.models import User
from .tasks import create_random_user_accounts
from django.http import JsonResponse
def users(request):
obj = list(User.objects.values())
create_random_user_accounts.delay(20)
return JsonResponse(obj,safe=False)
here i am inserting some random datas to User model using celery
And it is working while fetching same data.
But, i want to fetch 'existing data' from database 'without inseting' them on same request.
Please share me some idea how can i do that.
Method #1 do the insert off a POST and then retrieve via a GET:
from django.contrib.auth.models import User
from .tasks import create_random_user_accounts
from django.http import JsonResponse
from django.views.generic import View
class UserView(View):
def get(self, request, *args, **kwargs):
obj = list(User.objects.values())
return JsonResponse(obj,safe=False)
def post(self, request, *args, **kwargs):
create_random_user_accounts.delay(20)
obj = list(User.objects.values())
return JsonResponse(obj,safe=False)
Method #2 is just to remove the call to create_random_user_accounts, since that is what is creating the accounts:
from django.contrib.auth.models import User
from .tasks import create_random_user_accounts
from django.http import JsonResponse
def users(request):
obj = list(User.objects.values())
# create_random_user_accounts.delay(20)
return JsonResponse(obj,safe=False)
I have an extended UserProfile model in django:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
#other things in that profile
And a signals.py:
from registration.signals import user_registered
from models import UserProfile
from django.contrib.auth.models import User
def createUserProfile(sender, instance, **kwargs):
profile = users.models.UserProfile()
profile.setUser(sender)
profile.save()
user_registered.connect(createUserProfile, sender=User)
I make sure the signal gets registered by having this in my __init__.py:
import signals
So that should create me a new UserProfile for every user that registers, right? But it doesn't. I always get "UserProfile matching query does not exist" errors when I try to log in, which means that the database entry isn't there.
I should say that I use django-registration, which provides the user_registered signal.
The structure of the important apps for this is, that I have one application called "users", there I have: models.py, signals.py, urls.py and views.py (and some other things which shouldn't matter here). The UserProfile class is defined in models.py.
Update: I changed the signals.py to:
from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User
def create_profile(sender, **kw):
user = kw["instance"]
if kw["created"]:
profile = UserProfile()
profile.user = user
profile.save()
post_save.connect(create_profile, sender=User)
But now I get a "IntegrityError":
"column user_id is not unique"
Edit 2:
I found it. Looks like somehow I registred the signal twice. The workaround for this is described here: http://code.djangoproject.com/wiki/Signals#Helppost_saveseemstobeemittedtwiceforeachsave
I had to add a dispatch_uid, now my signals.py looks like this and is working:
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from models import UserProfile
from django.db import models
def create_profile(sender, **kw):
user = kw["instance"]
if kw["created"]:
profile = UserProfile(user=user)
profile.save()
post_save.connect(create_profile, sender=User, dispatch_uid="users-profilecreation-signal")
You can implement it using post_save on the user:
from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User
def create_profile(sender, **kwargs):
user = kwargs["instance"]
if kwargs["created"]:
profile = users.models.UserProfile()
profile.setUser(sender)
profile.save()
post_save.connect(create_profile, sender=User)
Edit:
Another possible solution, which is tested and works (I'm using it on my site):
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
def create_profile(sender, **kwargs):
user = kwargs["instance"]
if kwargs["created"]:
up = UserProfile(user=user, stuff=1, thing=2)
up.save()
post_save.connect(create_profile, sender=User)
You can get the extended profile to be created when first accessed for each user instead:
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
additional_info_field = models.CharField(max_length=50)
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
then use
from django.contrib.auth.models import User
user = User.objects.get(pk=1)
user.profile.additional_info_field
ref: http://www.codekoala.com/blog/2009/quick-django-tip-user-profiles/
This helped me: primary_key=True
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True, primary_key=True, related_name="user")
phone = models.CharField(('phone'),max_length=30, blank=False, null=True)
user_building = models.ManyToManyField(Building, blank=True)
added_by = models.ForeignKey(User, blank=True, null=True, related_name="added")
When you call profile.setUser(), I think you want to pass instance rather than sender as the parameter.
From the documentation of the user_registered signal, sender refers to the User class; instance is the actual user object that was registered.
According to my latest research, creating a separate file, e.g., singals.py, does not work.
You'd better connect 'create_profile' to 'post_save' in your models.py directly, otherwise this piece of code won't be executed since it's in a separate file and no one imports it.
My final code for your reference:
# models.py
# Here goes the definition of class UserProfile.
class UserProfile(models.Model):
...
# Use signal to automatically create user profile on user creation.
# Another implementation:
# def create_user_profile(sender, **kwargs):
# user = kwargs["instance"]
# if kwargs["created"]:
# ...
def create_user_profile(sender, instance, created, **kwargs):
"""
:param sender: Class User.
:param instance: The user instance.
"""
if created:
# Seems the following also works:
# UserProfile.objects.create(user=instance)
# TODO: Which is correct or better?
profile = UserProfile(user=instance)
profile.save()
post_save.connect(create_user_profile,
sender=User,
dispatch_uid="users-profilecreation-signal")
Update for 2018:
This question has collected a lot of views, maybe it is time for an update.
This is the latest version for latest Django.
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.conf import settings
from models import UserProfile
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance=None, created=False, **kwargs):
if created:
UserProfile.objects.create(user=instance)