unable to show success page after completion of payment - python

i am using razorpay payment gateway web integration for my learning eccomerce project everyhing work fine payment can be done all i want is to store some information after payment done in my order model using test mode
my views.py for checkout
class Checkout_Pre(View):
def post (self, request,):
user = request.user
address = Address.objects.filter(default=True, user=request.user)
cart = request.session.get('cart')
items = Item.get_items_by_id(list(cart.keys()))
prefer = request.POST.get('payment')
total_price = request.POST.get('paying_price')
total_item_price = json.loads(total_price)
with transaction.atomic():
order = Order.objects.create(
user=user,
total_price=total_item_price,
address=address.first(),
method = prefer,
)
for item in items:
item_order = OrderItem.objects.create(
order=order,
item=item,
size=cart.get(str(item.id)),
price=item.price,
)
request.session['cart'] = {}
order_currency = 'INR'
callback_url = 'http://'+ str(get_current_site(request))+"/handlerequest/"
print(callback_url)
notes = {'order-type': "Basic order from the coolbuy website", 'key':'value'}
razorpay_order = razorpay_client.order.create(dict(amount=total_item_price*100, currency=order_currency, notes = notes, receipt=order.order_id, payment_capture='0'))
print(razorpay_order['id'])
order.razorpay_order_id = razorpay_order['id']
order.save()
return render(request, 'payment/razorpaypaymentsummary.html', {'order':order, 'order_id': razorpay_order['id'], 'orderId':order.order_id, 'final_price':total_item_price, 'razorpay_merchant_id':settings.razorpay_id, 'callback_url':callback_url,})
so what the error is after payment completion i want to show html page and change sttus in db but after payment completion the handlerequest throwinh me http 505 error
#csrf_exempt
def handlerequest(request):
if request.method == "POST":
try:
payment_id = request.POST.get('razorpay_payment_id', '')
order_id = request.POST.get('razorpay_order_id','')
signature = request.POST.get('razorpay_signature','')
params_dict = {
'razorpay_order_id': order_id,
'razorpay_payment_id': payment_id,
'razorpay_signature': signature
}
try:
order_db = Order.objects.get(razorpay_order_id=order_id)
except:
return HttpResponse("505 Not Found")
order_db.razorpay_payment_id = payment_id
order_db.razorpay_signature = signature
order_db.save()
result = razorpay_client.utility.verify_payment_signature(params_dict)
if result==None:
amount = order_db.total_amount * 100 #we have to pass in paisa
try:
razorpay_client.payment.capture(payment_id, amount)
order_db.payment_status = 1
order_db.save()
return render(request, 'firstapp/payment/paymentsuccess.html',{'id':order_db.id})
except:
order_db.payment_status = 2
order_db.save()
return render(request, 'firstapp/payment/paymentfailed.html')
else:
order_db.payment_status = 2
order_db.save()
return render(request, 'firstapp/payment/paymentfailed.html')
except:
return HttpResponse("505 not found")
any idea what i am doing wrong here in my handlre request view
order model
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,)
address = models.ForeignKey(Address, default= True, on_delete=models.CASCADE)
status = models.IntegerField(choices = status_choices, default=1)
method = models.CharField(max_length=50, blank=False,)
total_price = models.FloatField(blank=False, default=0)
payment_status = models.IntegerField(choices = payment_status_choices, default=3)
order_id = models.CharField(unique=True, max_length=200, null=True, default=None)
datetime_of_payment = models.DateTimeField(default=timezone.now)
created_at = models.TimeField(auto_now=True, editable=False)
razorpay_order_id = models.CharField(max_length=1000, null=True, blank=True)
razorpay_payment_id = models.CharField(max_length=1000, null=True, blank=True)
razorpay_signature = models.CharField(max_length=1000, null=True, blank=True)
def __str__(self):
return self.user.username + " " + str(self.order_id)
def save(self, *args, **kwargs):
if self.order_id is None and self.datetime_of_payment:
self.order_id = self.datetime_of_payment.strftime('ORDER%Y%m%dODR')
return super(Order,self).save(*args, **kwargs)

The problem is not with your view but with the save method of your model.
in the else part you are doing nothing. You should call the super generally.
Please modify the save function as below and then try :
def save(self, *args, **kwargs):
if self.order_id is None and self.datetime_of_payment:
self.order_id = self.datetime_of_payment.strftime('ORDER%Y%m%dODR')
return super(Order,self).save(*args, **kwargs)

In your post method, after you assign
order.razorpay_order_id = razorpay_order['id']
you need to save it. Looks like that's missing.

In your checkout view
def get(self, request, *args, **kwargs):
order = Order.objects.get(pk = self.kwargs['order'])
settings = SiteSettings.objects.all().first()
# Razorpay client auth
client = razorpay.Client(auth = (settings.razorpay_client_id, settings.razorpay_secret))
if order.razorpay_order_id is None:
order_amount = order.total*100
order_currency = settings.currency
order_receipt = 'Reciept'
notes = {'id': order.id, 'email': order.email_id, 'date':str(datetime.now()), 'amount': order.total, 'is_ios': order.is_ios, 'is_android': order.is_android} # OPTIONAL
data = {"amount":order_amount, "currency":order_currency, "receipt":order_receipt, "notes":notes, "payment_capture":'0'}
razorpay_order = client.order.create(data = data)
# Razorpay order inserted into database order
order.razorpay_order_id = razorpay_order["id"]
order.save()
else:
razorpay_order = client.order.fetch(order.razorpay_order_id)
return render(request, self.template_name, {'settings':settings, 'order':order, 'razorpay_order': razorpay_order})
def post(self, request, *args, **kwargs):
o = self.kwargs['order']+ ' POST'
settings = SiteSettings.objects.all().first()
return render(request, self.template_name, {'settings':settings, 'order':o})
In your handler
settings = SiteSettings.objects.all().first()
order = Order.objects.get(id=request.POST.get('order_id'))
#Razorpay authentication
client = razorpay.Client(auth = (settings.razorpay_client_id, settings.razorpay_secret))
#Razorpay transaction details
razorpay_transaction_details = {
'razorpay_order_id': request.POST.get('razorpay_order_id'),
'razorpay_payment_id': request.POST.get('razorpay_payment_id'),
'razorpay_signature': request.POST.get('razorpay_signature')
}
#Razorpay payment verification
client.utility.verify_payment_signature(razorpay_transaction_details)
#Razorpay capture payment Make sure you change this accordingly.
payment_transaction_details = client.payment.capture(razorpay_transaction_details['razorpay_payment_id'], order.total*100, {"currency":"payment_currency"})
order.order_description = payment_transaction_details
order.status = 'paid'
order.save()
context = {'request': request.POST, 'order': order, 'settings':settings, 'UserData':UserData, 'Password': Password}
return render(request, 'web/rpay-success.html', context)
You can wrap a try except block in it to render failure.

Related

creating post on a review model

I need help leaving a review to a another model as a user, ive been having errrors and tried a lot of solutions.
error
FieldError at /reviews/1
Cannot resolve keyword 'user' into field. Choices are: id, pet_owner, pet_owner_id, rating, review, sitter, sitter_id
This is my view function:
def post(self, request, pk):
user = Review(pet_owner = request.user)
sitter = get_object_or_404(Sitter, pk=pk)
data = request.data
review = Review.objects.create(
pet_owner_id = user,
sitter= sitter,
rating=data['rating'],
review=data['review']
)
return Response('Review Added', status=status.HTTP_400_BAD_REQUEST)
and these are the models:
class Review(models.Model):
review = models.CharField(max_length=500)
rating = models.DecimalField(max_digits=7, decimal_places=2)
sitter = models.ForeignKey(Sitter,on_delete=models.CASCADE,null=True)
pet_owner = models.ForeignKey(get_user_model(),on_delete=models.CASCADE,null=True)
class Sitter(models.Model):
first_name = models.CharField(max_length=255, default='Jane')
last_name = models.CharField(max_length=255, default='Doe')
zipcode = models.CharField(max_length = 5, default='12345')
supersitter = models.BooleanField(null=True, blank=True)
price = models.DecimalField(max_digits=7, decimal_places=2)
numReviews = models.IntegerField(null=True, blank=True, default=0)
rating = models.DecimalField(max_digits=7, decimal_places=2, default=0)
this is my review model and sitter model
def post(self, request):
"""Create request"""
print(request.data)
# Add user to request data object
# Serialize/create review
review_user = request.user
review_data = Review(pet_owner = review_user)
review = ReviewSerializer(review_data, data=request.data)
# If the review data is valid according to our serializer...
if review.is_valid():
# Save the created review & send a response
r = review.save()
return Response({ 'review': review.data }, status=status.HTTP_201_CREATED)
# # If the data is not valid, return a response with the errors
return Response(review.data, status=status.HTTP_400_BAD_REQUEST)
we also tried this
user should be a simple User object, so:
def post(self, request, pk):
sitter = get_object_or_404(Sitter, pk=pk)
data = request.data
review = Review.objects.create(
pet_owner=request.user,
sitter=sitter,
rating=data['rating'],
review=data['review']
)
return Response('Review Added', status=status.HTTP_400_BAD_REQUEST)
You can slightly optimize the method by using the pk immediately:
def post(self, request, pk):
review = Review.objects.create(
pet_owner=request.user,
sitter_id=pk,
rating=data['rating'],
review=data['review']
)
return Response('Review Added', status=status.HTTP_400_BAD_REQUEST)
but it might be better to work with a serializer to properly validate and clean the request data.

TypeError returning Model entry

I'm creating an ebay style website that auctions off items. I have a form that takes in the values for the listing required by the model. The form renders well but when I submit the form I get the error:
<class 'TypeError'> views.py 80 ("l = Listing(title=title, description=description, url=url, user=user_id, category=category)")
forms.py
class NewListingForm(forms.Form):
title = forms.CharField(max_length=200)
description = forms.CharField(max_length=500)
url = forms.URLField()
bid = forms.DecimalField(decimal_places=2, max_digits=10)
category = forms.ModelChoiceField(queryset=Category.objects.all())
views.py
** added around line that's throwing the error
def newListing(request):
try:
if request.method == "POST":
newListingForm = NewListingForm(request.POST)
if newListingForm.is_valid():
title = newListingForm.cleaned_data['title']
description = newListingForm.cleaned_data['description']
url = newListingForm.cleaned_data['url']
bid = newListingForm.cleaned_data['bid']
category = newListingForm.cleaned_data['category']
current_user = request.user
user_id = current_user.id
**l = Listing(title=title, description=description, url=url, user=user_id, category=category)**
l.save()
b = Bid(price=bid, bid_count=0)
b.listing.add(l)
b.save()
return HttpResponseRedirect(reverse("index"))
else:
newListingForm = NewListingForm()
return render(request, "auctions/newListing.html", {
'form': newListingForm
})
except Exception as exc:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
newListingForm = NewListingForm()
return render(request, 'auctions/newListing.html', {
'form': newListingForm
})
models.py
class Listing(models.Model):
title = models.CharField(max_length=200)
description = models.CharField(max_length=500)
url = models.URLField()
user = models.ForeignKey('User', on_delete=models.CASCADE, name='author')
category = models.ForeignKey('Category', on_delete=models.CASCADE, name='category', default="")
def __str__(self):
return f'{self.id}: {self.title}'
class Bid(models.Model):
price = models.DecimalField(decimal_places=2, max_digits=10)
bid_count = models.IntegerField()
listing = models.ForeignKey('Listing', on_delete=models.CASCADE, name='listing', default="")
def __str__(self):
return f'{self.slug} ({self.price})'
User is a keyword, so I was getting an error from that.

How to change status of the model in Django

I'm building a small to-do list project using Django, the to-do list has tasks
divided into to-do, in-progress and done, I want to move to-do tasks from todo list to in-
progress list by changing its status, so I gave the to-do model 3 status, and below in views.py I specified a method to change the status, but it seems not work, I'm not sure how to set the status. Any
help would be appreciated.
models.py
'''
class Todo(models.Model):
status_option = (
('to_do', 'to_do'),
('in_progress', 'in_progress'),
('done', 'done'),
)
status = models.CharField(max_length=20, choices=status_option, default='to_do')
project = models.ForeignKey(Project, on_delete=models.CASCADE)
name = models.CharField(max_length=20)
create_date = models.DateTimeField(auto_now_add=True)
start_date = models.DateTimeField(default=datetime.datetime.now)
due_date = models.DateTimeField(default=datetime.datetime.now)
details = models.TextField()
def __str__(self):
return self.status
'''
views.py
'''
def add_to_progress(request, todo_id, project_id):
todo = Todo.objects.get(id=todo_id)
project = Project.objects.get(id=project_id)
if request.method != 'POST':
form = dragTodoForm()
else:
form = dragTodoForm(request.POST)
Todo.objects.filter(id=todo_id).update(status='in_progress')
context = {'form', form, 'todo', todo, 'project', project}
return render(request, 'todo_lists/new_progress.html', context)
def add_to_done(request, todo_id, project_id):
todo = Todo.objects.get(id=todo_id)
project = Project.objects.get(id=project_id)
if request.method != 'POST':
form = dragTodoForm()
else:
form = dragTodoForm(request.POST)
Todo.objects.filter(id=todo_id).update(status='done')
context = {'form', form, 'todo', todo, 'project', project}
return render(request, 'todo_lists/new_done.html', context)
'''
views.py
'''
def drag(request, project_id):
project = Project.objects.get(id=project_id)
todo = Todo.objects.filter(status='to_do')
progress = Todo.objects.filter(status='in_progress')
done = Todo.objects.filter(status='done')
context = {'todo', todo, 'progress', progress, 'done', done, 'project',
project}
return render(request, 'todo_lists/project.html', context)
'''
I solved the problem using below strategy:
models.py
'''
class Todo(models.Model):
status_option = (
('to_do', 'to_do'),
('in_progress', 'in_progress'),
('done', 'done'),
)
status = models.CharField(max_length=20, choices=status_option, default='to_do')
# todo_list's content
team = models.ForeignKey('Team', on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
name = models.CharField(max_length=20)
create_date = models.DateTimeField(auto_now_add=True)
start_date = models.DateTimeField(default=datetime.datetime.now)
due_date = models.DateTimeField(default=datetime.datetime.now)
project_code = models.CharField(max_length=20)
details = models.TextField()
def __str__(self):
return self.status
# return self.team['team'].queryset
def update_status(self):
if self.status == 'to_do':
self.status = 'in_progress'
elif self.status == 'in_progress':
self.status = 'done'
self.save()
'''
views.py
'''
def progress(request, pk):
to = get_object_or_404(Todo, pk=pk)
to.update_status()
return redirect(reverse('todo_lists:project', kwargs={'project_id':
to.project.pk}))
'''

MultipleObjectsReturned at /checkout/ get() returned more than one Order -- it returned 2

Hi I'm trying to develop an e-commerce website using Django. I have two models and views on separate folders, one is an order model and view, another is the checkout model and view. The order view creates a new order everytime an item is added to the cart. And the checkout view creates a new billing address. I want to associate the billing address that is created to the order when the checkout form is submitted. But for some reason, it's not happening. It throws an error:
MultipleObjectsReturned at /checkout/
get() returned more than one Order -- it returned 2!
What is the problem?
My orders.models.py:
from django.db import models
from shopping_cart.models import Cart
from django.contrib.auth import get_user_model
from accounts2.models import BillingAddress
STATUS_CHOICES = (
("Started", "Started"),
("Abandoned", "Abandoned"),
("Finished", "Finished"),
)
User = get_user_model()
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
order_id = models.CharField(max_length=120, default='ABC', unique=True)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
status = models.CharField(max_length=120, choices=STATUS_CHOICES, default="Started")
sub_total = models.DecimalField(default=10.99, max_digits=1000, decimal_places=2)
tax_total = models.DecimalField(default=0.00, max_digits=1000, decimal_places=2)
final_total = models.DecimalField(default=10.99, max_digits=1000, decimal_places=2)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
billing_address = models.ForeignKey(BillingAddress, on_delete=models.SET_NULL, blank= True, null=True)
My orders.views.py:
#login_required
def order(request):
try:
the_id = request.session['cart_id']
cart = Cart.objects.get(id=the_id)
except:
the_id = None
return redirect(reverse("myshop-home"))
try:
new_order = Order.objects.get(cart=cart)
except Order.DoesNotExist:
new_order = Order(cart=cart)
new_order.cart = cart
new_order.user = request.user
new_order.order_id = id_generator()
new_order.save()
except:
return redirect(reverse("cart"))
if new_order.status == "Finished":
#cart.delete()
del request.session['cart_id']
del request.session['items_total']
return redirect(reverse("cart"))
context = {"address_form": address_form, "cart": cart}
template = "orders/checkout.html"
return render(request, template, context)
My accounts.models.py:
class BillingAddress(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
street_address = models.CharField(max_length=100)
apartment_address = models.CharField(max_length=100)
country = CountryField(multiple=False)
zip = models.CharField(max_length=100)
class Meta:
verbose_name_plural = "Billing Addresses"
My accounts.views.py:
class CheckoutView(LoginRequiredMixin, View):
def get(self, *args, **kwargs):
the_id = self.request.session['cart_id']
cart = Cart.objects.get(id=the_id)
form = CheckoutForm()
context = {"form": form, "cart": cart}
return render(self.request, "orders/checkout.html", context)
def post(self, *args, **kwargs):
form = CheckoutForm(self.request.POST or None)
try:
order = Order.objects.get(user = self.request.user)
if form.is_valid():
street_address = form.cleaned_data.get('street_address')
apartment_address = form.cleaned_data.get('apartment_address')
country = form.cleaned_data.get('country')
zip = form.cleaned_data.get('zip')
# same_shipping_address = form.cleaned_data.get('same_billing_address')
# save_info = form.cleaned_data.get('save_info')
payment_option = form.cleaned_data.get('payment_option')
billing_address = BillingAddress(
user = self.request.user,
street_address = street_address,
apartment_address = apartment_address,
country = country,
zip = zip
)
billing_address.save()
order.billing_address = billing_address
order.save()
return redirect('checkout')
messages.warning(self.request, "Failed checkout")
return redirect('checkout')
except ObjectDoesNotExist:
messages.warning(self.request, "You do not have an active order")
return redirect('/')
Use Order.objects.filter(user=user).last() to get the newest row or try to remember order's id when creating an order and filter with Order.objects.get(id=id)

Django filter with ForeignKey not working

I am building ecommerce and having trouble creating dashboard for sellers. No matter how I try to get filter processed orders so I can show sold products to sellers I couldn't make it happen. Some help will be a great relief. Following is my Seller Mixin I am trying to create:
mixins.py
class SellerAccountMixin(LoginRequiredMixin, object):
account = None
products = []
transactions = []
orders = []
def get_account(self):
user = self.request.user
accounts = SellerAccount.objects.filter(user=user)
if accounts.exists() and accounts.count() == 1:
self.account = accounts.first()
return accounts.first()
return None
def get_products(self):
account = self.get_account()
products = Product.objects.filter(seller=account)
self.products = products
return products
def get_all_products(self):
account = self.get_account()
products = Product.objects.all()
self.products = products
return products
def get_sold_products(self):
orders = UserCheckout.objects.get(user_user=self.user)
return orders
seller/views.py:
class SellerDashboard(SellerAccountMixin, FormMixin, View):
form_class = NewSellerForm
success_url = "/seller/"
def post(self, request, *args, **kwargs):
user = self.user
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def get(self, request, *args, **kwargs):
apply_form = self.get_form() #NewSellerForm()
account = self.get_account()
exists = account
active = None
context = {}
if exists:
active = account.active
if not exists and not active:
context["title"] = "Apply for Account"
context["apply_form"] = apply_form
elif exists and not active:
context["title"] = "Account Pending"
elif exists and active:
context["title"] = "Dashboard"
#products = Product.objects.filter(seller=account)
context["products"] = self.get_products()
context["today_sales"] = self.get_today_sales()
context["sold_products"] = self.get_sold_products()
#context["total_profit"] = self.get_total_profit()
else:
pass
return render(request, "sellers/dashboard.html", context)
Above is my seller app and I am bringing the products model with simple features. The problem is that its not letting me get processed orders with UserCheckout model in Orders app. Following is a snapshot of Orders app.
Orders/models.
class UserCheckout(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, null=True, blank=True)
email = models.EmailField(unique=True)
def __unicode__(self):
return self.email
ADDRESS_TYPE = (
('billing', 'Billing'),
('shipping', 'Shipping'),
)
class UserAddress(models.Model):
user = models.ForeignKey(UserCheckout)
type = models.CharField(max_length=120, choices=ADDRESS_TYPE)
street = models.CharField(max_length=120)
city = models.CharField(max_length=120)
state = models.CharField(max_length=120)
zipcode = models.CharField(max_length=120)
def __unicode__(self):
return self.street
def get_address(self):
return "%s, %s, %s, %s" %(self.street, self.city, self.state, self.zipcode)
CHOICES = (
('CreditCard', "CreditCard"),
('Cash On Delivery', 'Cash On Delivery'),
('PayPal', 'PayPal'),
)
ORDER_STATUS_CHOICES={
('created','Created'),
('paid','Paid'),
}
class Order(models.Model):
status = models.CharField(max_length=120, choices=ORDER_STATUS_CHOICES, default='created')
cart = models.ForeignKey(Cart)
user = models.ForeignKey(UserCheckout, null=True)
billing_address = models.ForeignKey(UserAddress, related_name='billing_address', null=True)
shipping_address = models.ForeignKey(UserAddress, related_name='shipping_address', null=True)
shipping_total_price = models.DecimalField(max_digits=50, decimal_places=2, default=5.99)
user_seller = models.ForeignKey(settings.AUTH_USER_MODEL)
order_total = models.DecimalField(max_digits=50, decimal_places=2, )
order_id = models.CharField(max_length=20, null=True, blank=True)
paymethod = models.CharField(max_length=120, choices=CHOICES, default='CreditCard')
seller = models.ForeignKey(SellerAccount, null=True)
def __unicode__(self):
return str(self.cart.id)
I can get multiple products but I need to filter products by seller and orders by seller. After trying multiple times I always get stuck with error:
user has to be a UserCheckout instance:
User "Admin": Must be a "User" instance.
and
'SellerDashboard' object has no attribute 'user'
I need to filter products by seller.
I need filter orders with paid status by the seller.
Seller Account Model:
class SellerAccount(models.Model):
user = models.ForeignKey(User)
managers = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="manager_sellers", blank=True)
#orders = models.ManyToManyField(Order)
active = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
def __unicode__(self):
return str(self.user.username)
def get_absolute_url(self):
return reverse("products:vendor_detail", kwargs={"vendor_name": self.user.username})
I am stuck so bad that I don't have courage to continue with django anymore. Please help.

Categories

Resources