I'm trying to first access the users table via the user foreign key present in userinformations models and later override the RetriveUpdateDestroy API view's destroy method to change the status of the user to inactive instead of deleting them. I can't seem to access the is-active field of the in built User database.
views.py
class UserUpdateApiView(RetrieveUpdateDestroyAPIView):
queryset = UserInformation.objects.all()
serializer_class = UserInformationUpdateSerializer
lookup_field = 'pk'
lookup_url_kwarg = 'id'
def destroy(self, request, *args, **kwargs):
try:
user = User.objects.get(pk=self.kwargs["id"])
deleteStatusVal = False
user.is_active = deleteStatusVal
user.save()
return Response(UserSerializer(user).data)
except:
return Response("Nope")
serializers.py
class UserSerializer(ModelSerializer):
password = serializers.CharField(style={'input_type': 'password'}, write_only=True)
email = serializers.EmailField(validators=[required])
class Meta:
model = User
fields = ['username', 'email', 'password', 'is_active']
extra_kwargs = {'password': {'write_only': True},
'is_active': {'read_only': True}}
def validate(self, data):
email = data.get('email', None)
user = User.objects.filter(email=email).distinct()
if user.exists():
raise ValidationError("That email is already registered!")
return data
class UserInformationUpdateSerializer(ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = UserInformation
fields = ['user', 'first_name', 'middle_name', 'last_name', 'phone', 'date_of_birth']
models.py
class UserInformation(BaseModel):
user = models.OneToOneField(User, related_name='user_id')
first_name = models.CharField(max_length=45)
middle_name = models.CharField(max_length=45, null=True)
last_name = models.CharField(max_length=45)
vendor = models.BooleanField(default=False)
phone = models.CharField(max_length=100, validators=[
RegexValidator(regex=r'^\+?8801?\d{9}$', message="Phone number must be entered in the format: '+8801*********'")
], blank=False, unique=True)
date_of_birth = models.DateField()
confirmation_token = models.CharField(max_length=45, null=True)
confirmation_exp = models.DateTimeField(null=True)
pw_reminder_token = models.CharField(max_length=45, null=True)
pw_reminder_exp = models.DateTimeField(null=True)
profile_pic = models.ImageField(blank=True, null=True, upload_to='profile_images/', default='Images/none/no_images.jpg')
cover_photo = models.ImageField(blank=True, null=True, upload_to='cover_images/', default='Images/none/no_images.jpg')
thumbnail_pic = models.ImageField(blank=True, null=True, upload_to='thumbnail_images/', default='Images/none/no_images.jpg')
phone_verified = models.BooleanField(default=False)
email_verified = models.BooleanField(default=False)
reward_points = models.IntegerField(null=False)
ref_code = models.CharField(null=True, max_length=10)
def __str__(self):
return self.user.username
def delete(self, *args, **kwargs):
self.user.delete()
super(UserInformation, self).delete(*args, **kwargs)
If you want to make User as in active while keeping the UserInformation object and Userobject un-deleted in database, you can do something like this:
def destroy(self, request, *args, **kwargs):
user = self.get_object().user
user.is_active = False
user.save()
return Response(UserInformationUpdateSerializer(self.get_object()).data)
You have 'is_active': {'read_only': True}}.
Also,
# this seems redundant
def delete(self, *args, **kwargs):
self.user.delete()
super(UserInformation, self).delete(*args, **kwargs)
Related
I have two forms (OwnerCreateForm, EmployeesCreateForm) and 3 models (Profile, Company and Owner). when the owner signs up, it creates the company and its own User object. after owner login, you can create employees.
Have the Owner connect to the profile and associate it with the company
I need to associate the owning company to the employees.
That each company manages its users, that they see the same thing
Here are the details I'm using:
MODELS
class Profile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return '{} Profile'.format(self.user)
class Owner(models.Model):
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
def __str__(self):
return '{} Owner'.format(self.profile)
class Tienda(models.Model):
dueƱo = models.ForeignKey(Owner, null=True, on_delete=models.CASCADE)
nombre_tienda = models.CharField(verbose_name='Nombre de la Tienda', max_length=120)
direccion = models.CharField(verbose_name='Su Direccion', max_length=160)
phone = models.CharField(max_length=11, null=True)
businessemail = models.EmailField(unique = True, verbose_name='Su email')
def __str__(self):
return self.nombre_tienda
class Employee(models.Model):
STATUS = (
('Admin', 'Admin'),
('Gerente', 'Gerente'),
('Validador', 'Validador')
)
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
role = models.CharField(choices=STATUS, max_length=16)
tienda = models.ForeignKey(Tienda, null=True, on_delete=models.CASCADE)
def __str__(self):
texto = "{0} ({1}) {2}"
return texto.format(self.tienda, self.role, self.role)
FORMS
class TiendaForm(ModelForm):
class Meta:
model = Tienda
fields = ('nombre_tienda', 'direccion', 'businessemail')
class OwnerCreateForm(UserCreationForm):
class Meta:
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')
model = User
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Display Name'
self.fields['email'].label = "Email Address"
class EmployeesCreateForm(UserCreationForm):
is_admin = forms.BooleanField(required=False)
is_manager = forms.BooleanField(required=False)
is_systemAdmin = forms.BooleanField(required=False)
class Meta:
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')
model = User
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Display Name'
self.fields['email'].label = "Email Address"
VIEWS
def registroOwner(request):
if request.method == "POST":
form = OwnerCreateForm(request.POST)
tienda = TiendaForm(request.POST)
if form.is_valid() and tienda.is_valid():
tienda.save()
form.save()
messages.success(request, f'Tu cuenta ha sido creada!')
return redirect('login')
else:
form = OwnerCreateForm()
tienda = TiendaForm()
context = {
'title': 'Sign up Owner',
'form': form,
'tienda': tienda
}
return render(request, "accounts/signup.html", context)
I have a registration system that works on otp.
I have a custom user model
class User(AbstractUser):
password = models.CharField(max_length=128, blank=True, null=True)
email = models.EmailField(max_length=254, unique=True)
dial_code_id = models.CharField(max_length=100)
mobile_number = models.CharField(max_length=100, blank=True, null=True)
username = models.CharField(max_length=150, unique=True, blank=True, null=True)
is_resource = models.BooleanField(default=False)
is_customer = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
skills = models.ManyToManyField(Skills)
class Meta:
db_table = "my_user"
def __str__(self):
return self.mobile_number
I have created an 'otp' model to save otp.
class Otp(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
otp = models.IntegerField()
created_on = models.DateTimeField(default=django.utils.timezone.now)
class Meta:
db_table = "otp"
My views looks like this
class UserCreateResponseModelViewSet(viewsets.ModelViewSet):
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
serializer.save()
custom_data = {
"status": True,
"message": 'Successfully registered your account.',
"data": serializer.data
}
generate_otp(serializer.data['id'])
return Response(custom_data, status=status.HTTP_201_CREATED)
else:
custom_data = {
"status": False,
"message": serializer.errors,
}
return Response(custom_data, status=status.HTTP_200_OK)
class UserCreateViewSet(UserCreateResponseModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
I have a function to generate and save otp
def generate_otp(user_id):
try:
otp_obj = Otp.objects.get(user_id=user_id)
except Otp.DoesNotExist:
otp_obj = None
if otp_obj is None:
otp = random.randrange(1000, 9999)
otp_obj = Otp(user=user_id, otp=otp)
otp_obj.save()
Serializer looks like
class UserSerializer(serializers.ModelSerializer):
mobile_number = serializers.CharField(
required=True,
validators=[UniqueValidator(queryset=User.objects.all())]
)
class Meta:
model = User
fields = ['id', 'first_name', 'last_name', 'email', 'dial_code_id','mobile_number', 'is_resource', 'is_customer']
The user is being registered successfully, but when it comes to saving otp in 'generate_otp()' I'm getting an error like
raise ValueError(ValueError: Cannot assign "2": "Otp.user" must be a "User" instance.
How can I overcome this?
Is this the right way to do it?
It looks like the problem is here:
otp_obj = Otp(user=user_id, otp=otp)
you're assigning an id (int) to the user field. not the user_id field
i'm trying to create userprofile while creating user. i'm getting this error:
profile_data = validated_data.pop('profile')
KeyError: 'profile'
when i don't pass profile key while user creation but i have mentioned not required userprofileserialzer in customuserSerializers. i just want to save null if i don't pass profile key.
models.py:
class CustomUser(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(_('first name'), max_length=50)
last_name = models.CharField(_("last name"), max_length=50)
email = models.EmailField(_('email address'), unique=True)
mobile_number = PhoneNumberField()
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
user_type = models.IntegerField(_("user_type"))
otp = models.CharField(_("otp"), max_length=10, default="0")
is_varified = models.BooleanField(default=False)
USER_TYPE_CHOICES = (
(1, 'users'),
(2, 'courier'),
(3, 'admin'),
)
user_type = models.PositiveSmallIntegerField(
choices=USER_TYPE_CHOICES, null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserMananager()
def __str__(self):
return self.email
class UserProfile(models.Model):
user = models.OneToOneField(
CustomUser, primary_key=True, related_name='userProfile', on_delete=models.CASCADE,)
gender = models.CharField(max_length=10, blank=True, null=True)
age = models.IntegerField(blank=True, null=True)
image = models.ImageField(
upload_to='api/user_profile/', blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.user.first_name
serializers.py:
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
read_only_fields = ('created_at', 'updated_at',)
exclude = ('user',)
class CustomUserSerializer(serializers.ModelSerializer):
profile = UserProfileSerializer(required=False)
password = serializers.CharField(write_only=True, required=False)
class Meta:
model = CustomUser
fields = ('id', 'first_name', 'last_name', 'email',
'mobile_number', 'password', 'is_active', 'user_type', 'otp', 'profile')
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = CustomUser.objects.create(**validated_data)
UserProfile.objects.create(user=user, **profile_data)
return user
def update(self, instance, validated_data):
profile_data = validated_data.pop('profile')
# update user data
instance.first_name = validated_data.get(
'first_name', instance.first_name)
instance.last_name = validated_data.get(
'last_name', instance.last_name)
instance.email = validated_data.get('email', instance.email)
# update user profile
if not instance.profile:
UserProfile.objects.create(user=instance, **profile_data)
instance.age = profile_data.get('age', instance.profile.age)
instance.gender = profile_data.get('gender', instance.profile.gender)
instance.save()
password = validated_data.get('password', None)
if password:
instance.set_password(password)
instance.save()
update_session_auth_hash(self.context.get('request'), instance)
return instance
views.py:
#api_view(["POST"])
#permission_classes((AllowAny,))
def register(request):
#permission_classes = [(AllowAny, )]
serializer = CustomUserSerializer(data=request.data)
# print(serializer)
if serializer.is_valid():
serializer.is_active = False
# serializer.make_password(request.data.get('password'))
serializer.save()
user_otp = randint(9999, 99999)
otp_code = str(user_otp)
email = request.data.get('email')
send_mail(
'Otp verification',
otp_code,
'chenaj
il.com',
[email],
fail_silently=False,
)
# serializer.save(otp=user_otp)
otp_update = CustomUser.objects.get(email=request.data.get('email'))
otp_update.otp = user_otp
otp_update.save()
user = CustomUser.objects.get(email=email)
token, created = Token.objects.get_or_create(user=user)
current_time = datetime.datetime.now()
return Response({'status_code': status.HTTP_200_OK, 'status': 'true', 'currentTimeStamp': current_time, 'message': 'User registered successfully, OTP sent to your Mail', 'data': {'id': user.id, 'token': token.key, 'user_type': user.user_type}}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#api_view(["POST"])
#permission_classes((IsAuthenticated, AllowAny))
def verifyUserOtp(request):
print("data.......////")
serializers = VerifyUserOtpSerializer(data=request.data)
if serializers.is_valid(raise_exception=True):
token = request.data.get('email')
otp = request.data.get('otp')
if CustomUser.objects.filter(otp=otp).exists():
user = CustomUser.objects.get(otp=otp)
user.is_varified = 1
user.save()
token, created = Token.objects.get_or_create(user=user)
print(user.profile.age)
return Response({'status_code': status.HTTP_200_OK, 'status': 'true', 'currentTimeStamp': datetime.datetime.now(), 'data': {'id': user.id, 'first_name': user.first_name, 'last_name': user.last_name, 'email': user.email, 'token': token.key, 'user_type': user.user_type}}, status=status.HTTP_200_OK)
return Response({'message': 'OTP not matched', 'status': 'false', 'status_code': status.HTTP_401_UNAUTHORIZED, 'currentTimeStamp': datetime.datetime.now()}, status=status.HTTP_400_BAD_REQUEST)
and in this verifyuserotp function i'm not able to access profile objects with user.profile.age.
To avoid having this error, you need to provide a default value for .pop method
like None
and whenever the returned value is None, don't create a Profile record.
def create(self, validated_data):
profile_data = validated_data.pop('profile', None)
user = CustomUser.objects.create(**validated_data)
if profile_data:
UserProfile.objects.create(user=user, **profile_data)
return user
This should solve your issue.
I cannot update using an inline form.
I thought it was possible before, but it wasn't.
I'm trying to solve it, but it doesn't work.
I added.
I will post any other necessary items.
"Id
This field is required.
user
A Profile with this User already exists.
"
I got an error.
#view
class UserEdit(generic.UpdateView):
model = User
form_class = forms.UserUpdateForm
template_name = 'accounts/accounts_edit.html'
success_url = reverse_lazy('person:myaccount')
def get_object(self):
return get_object_or_404(User, pk=self.request.user.user_id)
#model
class User(AbstractBaseUser, PermissionsMixin):
username_validator = UnicodeUsernameValidator()
user_id = models.UUIDField(default=uuid_lib.uuid4,
primary_key=True, editable=False)
username = models.CharField(_('username'), unique=True, max_length=50,validators=[username_validator],error_messages={
'unique': _("A user with that username already exists."),
},)
class profile(models.Model):
image = models.ImageField(upload_to='profile/',default='profile/default.jpg')
first_name = models.CharField(_('first name'), max_length=30, blank=True,null=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True,null=True)
birthday = models.DateField(_('birthday',),null=True)
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,)
#form
class ProfileUpdateForm(BaseModelForm):
class Meta:
model = profile
fields = ('first_name','last_name','birthday',)
ProfileFormSet = inlineformset_factory(User,profile,form=ProfileUpdateForm,extra=0)
class UserUpdateForm(mixins.ModelFormWithFormSetMixin,BaseModelForm):
formset_class = ProfileFormSet
class Meta:
model = User
fields = ('username','email',)
#mixin
class ModelFormWithFormSetMixin:
def __init__(self, *args, **kwargs):
super(ModelFormWithFormSetMixin, self).__init__(*args, **kwargs)
self.formset = self.formset_class(
instance=self.instance,
data=self.data if self.is_bound else None,
)
def is_valid(self):
return super(ModelFormWithFormSetMixin, self).is_valid() and self.formset.is_valid()
def save(self, commit=True):
saved_instance = super(ModelFormWithFormSetMixin, self).save(commit)
self.formset.save(commit)
return saved_instance
Am having two model classes user and accounts linked by together or connected by another table called useraccounts.
What i want is for the useraccounts table to be automatically also be populated with the ids of the user and account table when i submit data to them(user and accounts).
here is my sample models code.
class Account(models.Model):
# fields
id = models.IntegerField(primary_key=True)
t_stamp = models.DateField(default=datetime.datetime.now())
acctno = models.TextField(null=False, unique =True)
acctname = models.TextField(null=False)
status = models.TextField(null=False, choices=STATUS)
accttype = models.TextField(null=False,choices=ACCT_TYPE)
acctclass = models.TextField(null=False, choices=ACCT_CLASS)
min_balance = models.FloatField(default=0)
cur_balance = models.FloatField(default=0)
ava_balance = models.FloatField(default=0)
#fundingsources = models.ManyToManyField(FundingSource)
class Meta:
managed = False
db_table = 'accounts'
def save(self, *args, **kwargs):
super(Account, self).save(*args, **kwargs)
try:
self.useraccount_set.all()[0]
except:
UserAccount.objects.bulk_create([UserAccount(account_id=self,user_id=user) for user in User.objects.all()])
class User(AbstractBaseUser, PermissionsMixin):
id = models.AutoField(primary_key=True)
username = models.TextField(unique=True, null=True)
fullname = models.TextField(null=False)
country = models.TextField(null=True)
email = models.EmailField( unique=True, db_index=True)
phone = models.TextField()
address = models.TextField()
activation_key = models.CharField(max_length=40)
key_expires = models.DateTimeField(null=True)
date_joined = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=True)
#accounts = models.ManyToManyField(Account, through='UserAccount')
class Meta:
db_table = "users"
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
def get_short_name(self):
return self.fullname
def get_username(self):
return self.email
def is_authenticated(self):
return True
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
signals.post_save.connect(create_auth_client, sender=User)
User._meta.get_field_by_name('email')[0]._unique=True
class UserAccount(models.Model):
user_id = models.ForeignKey(User)
account_id = models.ForeignKey(Account)
class Meta:
managed = False
db_table = 'useraccounts'
class UserAccount(models.Model):
user_id = models.ForeignKey(User)
account_id = models.ForeignKey(Account)
class Meta:
managed = False
db_table = 'useraccounts'
You have to do that in model save method:
class Account(models.Model):
id = models.IntegerField(primary_key=True)
def save(self, *args, **kwargs):
super(Account, self).save(*args, **kwargs)
try:
self.useraccount_set.all()[0]
except:
UserAccount.objects.bulk_create([UserAccount(account_id=self,user_id=user) for user in User.objects.all()])
class User(AbstractBaseUser, PermissionsMixin):
id = models.AutoField(primary_key=True)
def save(self, *args, **kwargs):
super(User, self).save(*args, **kwargs)
try:
self.useraccount_set.all()[0]
except:
UserAccount.objects.bulk_create([UserAccount(user_id=self,account_id=account) for account in Account.objects.all()])