I am trying to create a system in Django by which users will login using a phone number. Used AbstractBaseUser to use the number as user id. Now I am trying to create a foreign key relation of every transaction with the number. While I try to push a transaction, it says "User matching query does not exist". I am getting where I made mistake.
User model:
class User(AbstractBaseUser, PermissionsMixin):
phone_number = models.CharField("Phone number", max_length=100, unique=True, error_messages={
'unique': ("number_existsssss"),
})
name = models.TextField("Name")
time_stamp = models.DateTimeField("Time-Date", auto_now=True)
request_type = models.CharField(max_length=100, default="check"
is_staff = models.BooleanField(verbose_name=('staff status'), default=False)
is_active = models.BooleanField(verbose_name=('active'), default=True)
Transaction Model:
class TransactionModel(models.Model):
trxID = models.CharField(max_length=15, null=True, unique=True)
User = models.ForeignKey(to=User, to_field="phone_number", related_name='transaction', on_delete=models.DO_NOTHING, default=1)
time = models.DateTimeField(auto_now=True, null=True)
amount = models.CharField(max_length=5, null=True)
pay_method = models.CharField(max_length=10, null=True)
amountReceivedFrom = models.CharField(max_length=26, null=True)
transactionStatus = models.CharField(max_length=15, null=True, default='False')
view for add-cash/b-kash request:
class BkashCashinView(APIView):
#transaction.atomic
def post(self, request, *args, **kwargs):
HEADERS = {
"Access-Control-Allow-Origin": "*"
}
if request.method == 'POST':
serializer = BkashCashinSerializer(data = request.data)
# serializer.is_valid()
req = request.data
trx_id = req.get('trxID')
print(trx_id)
phone_number = req.get('phone_number')
recharge_amount = float(req.get('amount'))
number_exists = User.objects.filter(phone_number=phone_number).exists()
user = User.objects.get(phone_number=phone_number)
print(user)
current_user_data = User.objects.select_for_update().get(phone_number=phone_number)
# current_user_data = User.objects.get(phone_number=phone_number)
with transaction.atomic():
current_user_data.current_balance += recharge_amount
current_user_data.save()
print("phone numbe", req.get("amount"))
serializer.is_valid(raise_exception=True)
current_balance = current_user_data.current_balance
context = {
"current_balance": current_balance,
"status": "success"
}
serializer.save()
# print(trx_id)
return Response(context, headers = HEADERS)
I think I made some mistakes with the foreign key relation. The error shows:
raise self.model.DoesNotExist(
user_signup.models.User.DoesNotExist: User matching query does not exist.
[04/Sep/2021 18:44:22] "POST /add-cash/b-kash HTTP/1.1" 500 20728
Related
I have web app which includes authentication. I have form, but when I enter my credentials and click submit I get an error: IntegrityError at /accounts/professor_register/ null value in column "last_name" violates not-null constraint.
view
from .forms import ProfessorSignupForm
class ProfessorSignup(CreateView):
model = User
form_class = ProfessorSignUpForm
template_name = 'authentication/dubai.html'
def form_valid(self, form):
user = form.save()
login(self.request, user)
return redirect('/')
form
class ProfessorSignUpForm(UserCreationForm):
first_name = forms.CharField()
last_name = forms.CharField()
phone = PhoneNumberField()
class Meta(UserCreationForm.Meta):
model = User
#transaction.atomic
def save(self):
user = super().save(commit=False)
user.is_professor = True
user.is_staff = True
user.save()
professor = Professor.objects.create(user=user)
professor.first_name = self.cleaned_data.get('first_name')
professor.last_name = self.cleaned_data.get('last_name')
professor.username = self.cleaned_data.get('username')
professor.email = self.cleaned_data.get('email')
professor.password = self.cleaned_data.get('password')
professor.save()
return user
models
class User(AbstractUser):
is_pupil = models.BooleanField(default=False)
is_instructor = models.BooleanField(default=False)
class Professor(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE, primary_key = True)
first_name = models.CharField(max_length=20, null=False)
last_name = models.CharField(max_length=30, null=True)
username = models.CharField(max_length=30, unique=True, null=True)
email = models.EmailField(unique=True, null=False)
password = models.CharField(max_length=60, null=False)
phone_number = PhoneNumberField(null=False, blank=False, unique=True)
I am using postgresql as database.
I have no idea why this is happening. Every stack answer I tried to replicate gives me another error:(
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
im using uuid token to activate users account , so every client created have their own code in the Client model , but when i create new client it generate always the same Token as others , i have used the uuid 4 , is their anyother ways to generate unique client code to activate their account or some other method then uuid , or just im missing a point on how to generate uuid on models ,
their is my model and client creation codes :
Model.py :
def generateUUID():
return str(uuid4())
class client(models.Model):
name = models.CharField(max_length=45, unique=True)
email = models.EmailField(max_length=85)
date_of_birth = models.DateField(null=True, blank=True)
height = models.IntegerField(null=True, blank=True)
weight = models.IntegerField(null=True , blank=True)
created_at = models.DateTimeField(auto_now_add=True)
picture = models.URLField(null=True ,blank=True)
affiliation = models.ForeignKey(User, on_delete=models.CASCADE, related_name="client_coach")
reference = models.OneToOneField(User, on_delete=models.CASCADE, null=True , blank=True)
is_active = models.BooleanField(default=False)
token = models.CharField( max_length=85, default=generateUUID())
def __str__(self):
return self.name
def getname(self):
return self.coach.name
view.py:
if request.method == 'POST' and request.POST['action'] == 'client':
form = ClientForm(request.POST)
print(form)
name = request.POST.get('name')
email = request.POST.get('email')
#client_code = code.objects.create()
new_client = client.objects.create(name = name, email = email, affiliation = request.user)
new_client.save()
return JsonResponse({'client': model_to_dict(new_client)}, status=200)
You need to create a custom save method and assign this there.
def save(self, *args, **kwargs):
self.token = generateUUID()
super(client, self).save(*args, **kwargs)
I'm currently processing a payment thing for an online subscription service and in order to get the users info to send this stuff, I have a payment form.
But, for some reason the payment form is not saving to the users account. Everything else actually processes and the only error I can trigger is a 'NOT NULL constraint failed: memberships_usermembership.user_id'
Here's what I have in my view -
#login_required()
def payments(request):
user_membership = get_user_membership(request)
selected_membership = get_selected_membership(request)
form = SubscriptionForm()
if request.method == "POST":
form_data = {
'full_name': request.POST['full_name'],
'email': request.POST['email'],
'phone_number': request.POST['phone_number'],
'country': request.POST['country'],
'postcode': request.POST['postcode'],
'town_or_city': request.POST['town_or_city'],
'street_address1': request.POST['street_address1'],
'street_address2': request.POST['street_address2'],
'county': request.POST['county'],
}
token = request.POST['stripeToken']
form = SubscriptionForm(form_data)
if form.is_valid():
customer = stripe.Customer.retrieve(
user_membership.stripe_customer_id)
customer.source = token
customer.save()
subscription = stripe.Subscription.create(
customer=user_membership.stripe_customer_id,
items=[
{"plan": selected_membership.stripe_plan_id},
]
)
user_membership = get_user_membership(request)
selected_membership = get_selected_membership(request)
user_membership.membership = selected_membership
user_membership.save()
form.save(commit=True)
subscription_id = subscription.id
sub, created = Subscription.objects.get_or_create(
user_membership=user_membership)
sub.stripe_subscription_id = subscription_id
sub.active = True
sub.save()
try:
del request.session['selected_membership_type']
except BaseException:
pass
return render(request, 'memberships/update-success.html')
else:
return redirect(reverse('membership_list'))
context = {
'selected_membership': selected_membership,
'form': form,
}
return render(request, 'memberships/payment.html', context)
When the form.save() is the line above the return(render) line, it will process everything as normal, and the form information just wont save into the DB.
It flashes the NOT NULL error when the form.save() line is where it in in the code above.
Any ideas how to get this working?
Thanks!
EDIT: Here's a link to the entire error in Django - http://dpaste.com/140VD8M
& a screenshot of it too!
Here's my models -
class Membership(models.Model):
membership_type = models.CharField(
choices=MEMBERSHIP_CHOICES,
default='Free',
max_length=30)
price = models.IntegerField(default=15)
description = models.TextField(default="DESCRIPTION")
image_url = models.URLField(max_length=1024, null=True, blank=True)
image = models.ImageField(null=True, blank=True)
stripe_plan_id = models.CharField(max_length=40)
def __str__(self):
return self.membership_type
class UserMembership(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
full_name = models.CharField(max_length=50, null=True, blank=True)
email = models.EmailField(max_length=254, null=True, blank=True)
phone_number = models.CharField(max_length=20, null=True, blank=True)
country = CountryField(blank_label='Country', default="Ireland")
postcode = models.CharField(max_length=20, null=True, blank=True)
town_or_city = models.CharField(max_length=40, null=True, blank=True)
street_address1 = models.CharField(max_length=80, null=True, blank=True)
street_address2 = models.CharField(max_length=80, null=True, blank=True)
county = models.CharField(max_length=80, null=True, blank=True)
stripe_customer_id = models.CharField(max_length=40)
membership = models.ForeignKey(
Membership, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.user.username
def post_save_usermembership_create(
sender, instance, created, *args, **kwargs):
user_membership, created = UserMembership.objects.get_or_create(
user=instance)
if user_membership.stripe_customer_id is None or user_membership.stripe_customer_id == '':
new_customer_id = stripe.Customer.create(email=instance.email)
free_membership = Membership.objects.get(membership_type='Free')
user_membership.stripe_customer_id = new_customer_id['id']
user_membership.membership = free_membership
user_membership.save()
post_save.connect(post_save_usermembership_create,
sender=settings.AUTH_USER_MODEL)
class Subscription(models.Model):
user_membership = models.ForeignKey(
UserMembership, on_delete=models.CASCADE)
stripe_subscription_id = models.CharField(max_length=40)
active = models.BooleanField(default=False)
def __str__(self):
return self.user_membership.user.username
& here's my user membership def -
#login_required()
def get_user_membership(request):
user_membership_qs = UserMembership.objects.filter(user=request.user)
if user_membership_qs.exists():
return user_membership_qs.first()
return None
Instead of collecting all the form fields individually, you should be able to just pass the request.POST to the form like so:
form_data = request.POST
token = request.POST['stripeToken']
form = SubscriptionForm(form_data)
Other than that, without seeing the exact error message, there isn't much more to tell. If you update your question I will update my answer.
EDIT:
Without seeing your model and what get_user_membership() returns, it looks like you are missing a User object in a UserMembership class (but I can't tell without seeing more):
user_membership.user = request.user
Or something like that.
I'm trying to override the rest_auth LoginView with my own LoginSerializer.
class LoginSerializer(serializers.ModelSerializer):
"""Login Serialization for first_token"""
first_token = serializers.CharField(write_only=True)
phonenumber = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ['phonenumber', 'first_token']
def _validate_phonenumber(self, phonenumber, first_token):
user = None
if phonenumber and first_token:
user = authenticate(phonenumber=phonenumber, first_token=first_token)
else:
raise exceptions.ValidationError('phonenumber does not exist')
return user
def validate(self, attrs):
first_token = attrs.get('first_token')
phonenumber = attrs.get('phonenumber')
user = self._validate_phonenumber(phonenumber, first_token)
attrs['users'] = user
return attrs
settings.py
REST_AUTH_SERIALIZERS = {
'LOGIN_SERIALIZER': 'blog.serializers.LoginSerializer',
}
when im trying to login errors comes up:
KeyError at /api/login/ 'user'
workspace/test-blog/env/lib/python3.6/site-packages/rest_auth/views.py
in login
self.user = self.serializer.validated_data['user']
my Usermodel is inheriting from AbstractBaseUser:
class User(AbstractBaseUser):
username = models.CharField(max_length=20, blank=True)
email = models.EmailField(verbose_name='email address',blank=True, null=True, max_length=255, unique=True, default=None)
phonenumber = models.CharField(validators=[phone_regex], max_length=17, null=True, unique=True)
first_token = models.ForeignKey(FirstToken, on_delete=models.SET_NULL, null=True, related_name='first_token', blank=True)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'phonenumber'
REQUIRED_FIELDS = []
I'm stuck. I need some help.
attrs[‘users’] = user
The key needs to be user, not users.