I’m trying to get the username of the current logged in user using OneToOneField to populate in the admin once the user submits a form.
The username should go in the user column of admin.py.
I’ve tried various methods and still no luck. I’m new to this and this is my first Django application I’m building so I’m not sure what I’m missing.
I’m stuck and have no idea what I’m doing so any help is gladly appreciated.
Can someone please help? What am I missing?
Thanks!
Code Below:
user_profile/models
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import AbstractUser, UserManager
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from users.forms import CustomUserCreationForm, CustomUserChangeForm
from users.models import CustomUser
class Listing (models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
zip_code = models.CharField(max_length=100)
mobile_number = models.CharField(max_length=100)
cc_number = models.CharField(max_length=100)
cc_expiration = models.CharField(max_length=100)
cc_cvv = models.CharField(max_length=100)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = Listing.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
user_profile/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from user_profile.forms import HomeForm
from user_profile.models import Listing
# Register models here.
class UserProfileAdmin(admin.ModelAdmin):
list_display = ['name', 'address', 'zip_code', 'mobile_number', 'created', 'updated', 'user']
list_filter = ['name', 'zip_code', 'created', 'updated', 'user']
admin.site.register(Listing, UserProfileAdmin)
#admin.site.unregister(Listing)
master_application/settings.py
AUTH_USER_MODEL = 'users.CustomUser'
AUTH_PROFILE_MODULE = 'users.UserProfile'
users/models.py
from django.contrib.auth.models import AbstractUser, UserManager
from django.contrib.auth.models import User
from django.db import models
from django.urls import reverse
class CustomUserManager(UserManager):
def get_by_natural_key(self, username):
case_insensitive_username_field = '{}__iexact'.format(self.model.USERNAME_FIELD)
return self.get(**{case_insensitive_username_field: username})
class CustomUser(AbstractUser):
objects = CustomUserManager()`
Your signal is broken; kwargs will never have a user key so the profile will never be created. What you actually want to do is to check that the signal is being called on creation (rather than on update), add then create an instance of Listing:
if kwargs['created']:
user_profile = Listing.objects.create(user=kwargs['instance'])
Note, the AUTH_PROFILE_MODULE setting has not been used for years, you should remove it.
Related
Hello kings and queens!
I'm working on a project and got stuck on a (for me) complicated issue. I have one model (generalpage.models) where all the common info about the users is stored. In a different app (profilesettings), I have an app where all profile page related functions will be coded.
I tried to inherit the model fields from the User class in generalpage.models into profilesettings.models by simply writing UserProfile(User). When I did this, a empty forms was created in the admin panel. So basically, the information that was already stored generalpage.models were not inherited into the profilesettings.models, I created an entire new table in the database.
my questions are:
Is it possible to create an abstract class for a custom user model?
Is there a proper way to handle classes and create a method in profilesettings.models that fills the UserProfile form with the data already stored in database created by the User class?
Can someone please explain how the information can be passed from one application to another without creating a new empty form?
Filestructure:
Admin panel:
generalpage.models:
from random import choices
from secrets import choice
from unittest.util import _MAX_LENGTH
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, User, PermissionsMixin
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from generalpage.managers import CustomUserManager
from django.conf import settings
from generalpage.managers import CustomUserManager
# Create your models here.
sex_choices = ( ("0", "Man"),
("1", "Kvinna"),
("2", "Trans")
)
class User(AbstractBaseUser, PermissionsMixin):
user = models.CharField(settings.AUTH_USER_MODEL, null=True, max_length=50)
username = models.CharField(_("Användarnamn"), max_length=100, null=True, unique=True)
age = models.IntegerField(_("Ålder"),null=True, blank=False)
email = models.EmailField(_("E-mail"), unique=True, null=False)
country = models.CharField(_("Land"),max_length=50, null=True, blank=True)
county = models.CharField(_("Län"),max_length=50, null=True, blank=True)
city = models.CharField(_("Stad"),max_length=50, null=True, blank=True)
sex = models.CharField(_("Kön"), choices=sex_choices, null=True, blank=False, max_length=50)
profile_picture = models.ImageField(_("Profilbild"),null=True, blank=True, default="avatar.svg", upload_to = "static/images/user_profile_pics/")
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'username' # defines the unique identifier for the User model
REQUIRED_FIELDS = ["email"] # A list of the field names that will be prompted for when creating a user via the createsuperuser management command
objects = CustomUserManager()
def __str__(self):
return self.username
profilesettings.models:
from generalpage.models import User, UserInfo, Room, Message, Topic
from django.db import models
class UserProfile(User):
pass
class Settings(UserInfo):
pass
My models after #viktorblindh suggestion are:
for admin.py:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from profilesettings.models import UserProfile
from generalpage.models import User
class UserProfileInline(admin.StackedInline):
model = UserProfile
min_num = 1
class UserProfileAdmin(BaseUserAdmin):
inlines = [UserProfileInline, ]
admin.site.register(User, UserProfileAdmin)
# admin.site.register(UserProfile)
# admin.site.register(Settings)
and for profilesettings.models:
from generalpage.models import User, UserInfo, Room, Message, Topic
from django.db import models
from django.conf import settings
class UserProfile(User):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class Settings(UserInfo):
pass
```
The solution suggested in:
https://stackoverflow.com/questions/42424955/how-to-exchange-data-between-apps-in-django-using-the-database
solved my issue.
Maybe i'm misunderstanding the issue at hand but to me it sounds like you would want to have a OneToOne key on your profilesettings.UserProfile to your generalpage.user. I'm assuming every user have their own unique profilesettings.
from django.conf import settings
class UserProfile(User):
user(models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
Then after that you can use an inlineformset in your generalpage.admin to get all the information displayed in the same form.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from profilesettings.models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
min_num = 1
class UserProfileAdmin(BaseUserAdmin):
inlines = [UserProfileInline, ]
admin.site.register(User, UserProfileAdmin)
I created a Django API to create a new user. However, when I try to create a user I get the error message:
IntegrityError at /api/v1/users/register/ NOT NULL constraint failed: accounts_user.user_id
This is what I have in models.py
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
class User(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100, blank=True)
location = models.CharField(max_length=100, blank=True)
password = models.CharField(max_length=32)
email = models.EmailField(max_length=150)
signup_confirmation = models.BooleanField(default=False)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def update_profile_signal(sender, instance, created, **kwargs):
if created:
User.objects.create(user=instance)
instance.profile.save()
In serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('user_id', 'name', 'location', 'password', 'email', 'signup_confirmation')
and my views.py
from rest_framework import viewsets
from .serializers import UserSerializer
from .models import User
from rest_framework.decorators import action
from .forms import SignUpForm
from .tokens import account_activation_token
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('name')
serializer_class = UserSerializer
#action (detail=True, methods=['post'])
def register(self, request):
print(request)
Any ideas on what I can do to resolve this error
As John wrote in a comment:
Here you have a problem: fields = ('user_id',...).
I also advise you to change your User model. If you don't need separating (I suppose you don't), it is way better to create your User with inheritance directly from AbstractUser instead of creating in fact doubled User models.
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
...
In this way you will already have username, password and email, but you can add anything else in same model, instead of using user.user etc.
I got the following error:
Got AttributeError when attempting to get a value for field Name on
serializer UserSerializer. The serializer field might be named
incorrectly and not match any attribute or key on the User instance.
Original exception text was: 'User' object has no attribute 'Name'.
Why do I get an error?
Here is my code:
views.py
from .serializers import UserSerializer
from rest_framework import viewsets, status
from django.contrib.auth.models import User
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers
from .models import Profile
from rest_framework.authtoken.models import Token
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('id', 'Name', 'secondName', 'user', 'nickName', 'phoneNumber')
"""extra_kwargs = {'password': {'write_only': True, 'required': True}}"""
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
token = Token.objects.create(user=user)
print('Loogg')
return user
models.py
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
"""Define Profile Fields"""
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, default=None)
Name = models.CharField(max_length=32)
secondName = models.CharField(max_length=32)
nickName = models.CharField(max_length=32)
phoneNumber = models.IntegerField(max_length=32)
def __str__(self):
return self.user.username
class Meta:
verbose_name = 'Profile'
verbose_name_plural = 'profiles'
urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from rest_framework import routers
from .views import UserViewSet
router = routers.DefaultRouter()
router.register('users', UserViewSet)
urlpatterns = [
path('', include(router.urls))
]
admin.py
from django.contrib import admin
from .models import Profile
admin.site.register(Profile)
Thanks,
I am quite new to Django so it could be a stupid error.
queryset = Profile.objects.all() instead of queryset = User.objects.all()
– Arakkal Abu
I’m trying to create an instance of Listing so I can have user populate in the admin.
I’m new to Django and thought I had it but looks like I’m wrong somewhere.
How do I create an instance of Listing to populate in admin?
Any help i gladly appreciated, thanks.
Code Below:
user_profile/models
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import AbstractUser, UserManager
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from users.forms import CustomUserCreationForm, CustomUserChangeForm
from users.models import CustomUser
class Listing (models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True)
created = models.DateTimeField(auto_now_add=True, null=True)
updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
zip_code = models.CharField(max_length=100)
mobile_number = models.CharField(max_length=100)
cc_number = models.CharField(max_length=100)
cc_expiration = models.CharField(max_length=100)
cc_cvv = models.CharField(max_length=100)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = Listing.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
user_profile/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from user_profile.forms import HomeForm
from users.forms import CustomUserCreationForm, CustomUserChangeForm
from user_profile.models import Listing
from users.models import CustomUser
# Register models here.
class UserProfileAdmin(admin.ModelAdmin):
list_display = ['name', 'address', 'zip_code', 'mobile_number', 'created', 'updated', 'user']
list_filter = ['name', 'zip_code', 'created', 'updated', 'user']
admin.site.register(Listing, UserProfileAdmin)
I suspect the problem is that you have a custom user model, but your signal is listening to the post_save event from the built-in User. Since you never create instances of that model, the signal never gets triggered.
Change it to:
post_save.connect(create_profile, sender=CustomUser)
I am having an issue passing a field from an extended user model to a template in Django.
I defined the extended user fields in a model in a new app called user_management:
#user_management/models.py
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
class lab_user(models.Model):
user = models.OneToOneField(User)
personal_order_list_url = models.URLField("Personal order list URL", max_length=255, blank=False, unique=True)
abbreviation_code = models.CharField("Abbreviation code", max_length=3, blank=False, unique=True)
def save(self, force_insert=False, force_update=False):
self.personal_order_list_url = self.personal_order_list_url.lower()
self.abbreviation_code = self.abbreviation_code.upper()
super(lab_user, self).save(force_insert, force_update)
I then registered the new fields in admin.py:
#user_management/admin.py
from __future__ import unicode_literals
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
from .models import lab_user
class lab_user_inline(admin.StackedInline):
model = lab_user
can_delete = False
verbose_name_plural = 'Additional Fields'
class UserAdmin(BaseUserAdmin):
inlines = (lab_user_inline, )
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
I can see the new fields in "Authentication and Authorization", which I guess means I've done everything "right".
When I try to call fields in a template using {{ request.user.x }} where x could be first_name, personal_order_list_url or abbreviation_code, I can retrieve the desired value for first_name and personal_order_list_url, but not for abbreviation_code.
If request.user.personal_order_list_url works, request.user.abbreviation_code should work too, shouldn't it?
request.user.lab_user.personal_order_list_url