I have created a Django model with a foreign key from user, I want that all created user before be created in that table with a default value:
Models.py
from django.contrib.auth.models import User
class UserProfiles(models.Model):
myuser = models.OneToOneField(User, on_delete=models.CASCADE)
userstatus = models.CharField(default='active', max_length=20)
Can you help me that I can migrate this table and be created to all users who are registered before?
Try something like this:
post_save
from django.contrib.auth.models import User
from django.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=UserProfiles)
def create_user_profile(sender, instance, created, **kwargs):
if created is True:
UserProfiles(instance)
I recommend creating this function in your app folder under signals.py
I hope this is what you are looking for
Related
I am able to register users to my custom table in the Postgres database. I would like to know how can I use the credentials from my Postgres table to authenticate login from my django web app. I know I have to create a custom backend but I don't know how we can import the credentials from Postgres to authenticate against the credentials that user entered.
My model:
from django.conf import settings
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractBaseUser
# Create your models here.
# Database model Users has one to one relationship with Django User table
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(AbstractBaseUser):
first_name = models.TextField()
last_name = models.TextField()
user = models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
user_name = models.TextField(unique=True)
email = models.TextField()
password1 = models.TextField()
password2 = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'user_name'
REQUIRED_FIELDS = []
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def update_profile_signal(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
I have my django project pointing towards my custom user model too.
I just don't know how to create a custom backend for authentication. If I could be guided towards it, I would really appreciate.
If you set the password for each user when creating a new user, the default authentication backend for Django will work just fine for you.
When saving a new Profile you should just do a instance.set_password(password) after validating if password and password2 are the same.
Also I would recommend not using receiver but rather maintaining a CustomManager for your table.
For now this should do the trick for you:
#receiver(post_save, sender=User)
def update_profile_signal(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
if password == password2:
instance.set_password(password)
instance.profile.save()
Then you can limit access to Views using the #login_required decorator. Some other ways are mentioned here
I am using the standard django.contrib.auth.models User model and have extended it to create a Profile model with a one to one relationship with User to hold the profile picture. The signal for this is working fine. I since added another model, Roles, which needs a regular foreign key to User as a user can have multiple roles. The latter gives consistent errors no matter how I try to configure it including giving the fields different related_name in case it was confused which was which as well as having the Role model with a relationship to Profile rather than User but no matter how I seem to tackle it, I can't get the signal to work.
relevant models.py file code is as follows:
models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
...
class Role(TimeStampedModel):
user = models.ForeignKey(User, on_delete=models.CASCADE)
role = models.IntegerField('Roles',choices=Roles.choices, default=0)
...
signals.py:
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from core.models import Profile, Role
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
Role.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
instance.role.save()
The debug error I am getting is as follows:
AttributeError at /login/
'User' object has no attribute 'role'
Request Method: POST
Request URL: http://127.0.0.1:8000/login/
Django Version: 3.0.8
Exception Type: AttributeError
Exception Value:
'User' object has no attribute 'role'
Exception Location: C:\project\path\core\signals.py in save_profile, line 15
I expect it's something to do with setting up a separate signal rather than having them in the same def but haven't been able to crack it after trying numerous ways. Likely just a silly thing I'm missing and will be grateful for a nudge in the right direction.
Thanks for taking a look.
Simon
user have not role but roles, is the default related name in foreignkey
you can change this by foreignkey(... , related_name="your_name")
so you can't do this for 2 reason
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
instance.role.save()
instance not have role but roles
instance.roles is not object but a queryset/list of role models
I am trying to create userprofile after user has been registered in django app.
User creation is working fine but it is not profile models in admin page.
It is not showing any errors.
So far I have done this.
users/signals.py
from django.db.models.signals import post_save
from django.contrib.auth.models import User
#reciever
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()
users/app.py
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
users/models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pic')
def __str__(self):
return f'{self.user.username} Profile'
Add this line of code to your app's __init__.py file as #Mohit Harshan mentioned
default_app_config = 'my_app.apps.MyAppConfig'
Why RelatedObjectDoesNotExist error?
Some of your User object has no active relation with Profile instance.So run the following code in your Django shell
users_without_profile = User.objects.filter(profile__isnull=True)
for user in users_without_profile:
Profile.objects.create(user=user)
In your settings.py you should change installed apps
if your settings like this
INSTALLED_APPS = ['users']
you should change it below like this.
INSTALLED_APPS = ['users.apps.UsersConfig']
I use the built-in User model in django, but i want use some custom fields, i was create new model
class Profile(models.Model):
user = models.OneToOneField(User)
profile_img = models.ImageField(null=True)
def __str__(self):
return self.user.username
this is my custom model.
But when i create new user it doesn't display in admin(in profile table), i need to add user from admin panel, after adding it works fine. what i should to do to display Profile info of all users?
p.s. When i was create table profile and was try to select info from joined tabels, sql query wasn't return anything, but after adding existed user to Profile table sql query return all what i want
To create a new Profile object when a new user is created, you can use a pre_save receiver:
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(
user=instance
)
The created parameter is to check if the object has been created ( created=True ) or updated ( created=False )
I am not sure to understand what you want... If you want to manage profile in admin app you have to register it.
from django.contrib import admin
from myproject.myapp.models import Profile
class ProfileAdmin(admin.ModelAdmin):
pass
admin.site.register(Profile, ProfileAdmin)
Edit: you can use a signal to automatically create a profile when creating a user.
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from myproject.myapp.models import Profile
#receiver(post_save, sender=User)
def create_profile(sender, instance **kwargs):
Profile.objects.create(user=instance)
Note that sometime using signals may be hard to maintain. You can also use AbstractBaseUser. This is a classical issue, which is widely covered in a lot of posts.
One I particularly like: https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html
I am trying to create profile system where my users django username will be their username on the site, and also allow them to create a bio. However when I try to migrate, I get this error:
AttributeError: 'OneToOneField' object has no attribute 'model'
Here is my models.py files:
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True)
bio = models.TextField(null=True)
slug = models.SlugField(default=user)
def __unicode__(self):
return "%s's profile" % self.user
def create_profile(sender, instance, created, **kwargs):
if created:
profile, created = UserProfile.objects.get_or_create(user=instance)
# Signal while saving user
from django.db.models.signals import post_save
post_save.connect(create_profile, sender=User)
And here is my admin.py:
from django.contrib import admin
from profiles.models import UserProfile
class UserProfileAdmin(admin.ModelAdmin):
list_display = ["user"]
admin.site.register(UserProfile, UserProfileAdmin)
Anyone know what the problem is? Thanks.
Try without importing the User model from django.contrib.auth.
Remove (or comment out) the User import line, the signal binding, and switch to string based model specification of relation in OneToOneField. The example of string based relation specification can be found in the docs.
This looks like a circular dependency thing.
If you'd still get an error, try to remove stuff you don't need from INSTALLED_APPS.