i have some problems with a web im creating. The paid is made and thats work fine, my problem is with only one line of code XD. Im trying to "save" the names of products purchased (in this case is for courses), in a billing and then pass that course to a user-profile so he can gain access to the course. Im very new in python and django, and i know how to do this.
first a big resume of my organization in the project:
myApp _ apps ______content
| |
| |_____shopping_cart
|
|
|_ paypal
|
|_ user
ok so my model in content is:
class Course(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
thumbnail = models.ImageField(upload_to="courseThumbnails/")
publish_date = models.DateTimeField(auto_now_add=True)
last_update = models.DateTimeField(auto_now=True)
description = models.TextField()
price = models.FloatField()
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
#agregar despues un field de recursos para descargar material nose si aca o en video mejor
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("content_app:course-detail", kwargs={"slug":self.slug})
In shopping_ cart model is:
from django.conf import settings
from django.db.models import Sum
from django.db import models
from apps.content.models import Course
# Create your models here.
class OrderItem(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
def __str__(self):
return self.course.name
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
is_ordered = models.BooleanField(default=False)
items = models.ManyToManyField(OrderItem)
ref_code = models.CharField(max_length=50)
def __str__(self):
return self.user.username
def get_total(self):
return self.items.all().aggregate(order_total=Sum('course__price'))['order_total']
and my model in paypal is:
from django.db import models
from apps.shopping_cart.models import Order
from apps.content.models import Course,
class Compra(models.Model):
id = models.CharField(primary_key= True, max_length=100)
estado = models.CharField(max_length=100)
codigo_estado = models.CharField(max_length=100)
cursos = models.ManyToManyField(to=Order, related_name='comprado')
total_de_la_compra = models.DecimalField(max_digits=5 ,decimal_places= 2)
nombre_cliente = models.CharField(max_length=100)
apellido_cliente = models.CharField(max_length=100)
correo_cliente = models.EmailField(max_length=100)
direccion_cliente = models.CharField(max_length=100)
class Meta:
verbose_name = 'Facturacion'
verbose_name_plural= 'Facturaciones'
def __str__(self):
return str(self.nombre_cliente)
class Payment(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
total_amount = models.FloatField()
date_paid = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.order.user)
last model is for user:
from django.db import models
from django.conf import settings
from django.db.models.signals import post_save
from apps.content.models import Course,
class UserProfile(models.Model):
cursos = models.ManyToManyField(Course, blank=True)
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
def cursos_list(self):
return self.cursos.all()
def post_user_signup_receiver(sender, instance, created, *args, **kwargs):
if created:
UserProfile.objects.get_or_create(user=instance)
post_save.connect(post_user_signup_receiver, sender=settings.AUTH_USER_MODEL)
Okay with thats model and following a lot of tutorials of paypal (because the oficial documentations it wasnt clear enogh for me) i made a view in paypal app, and here is where the problem is:
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, JsonResponse
from paypalcheckoutsdk.core import PayPalHttpClient, SandboxEnvironment
from paypalcheckoutsdk.orders import OrdersGetRequest, OrdersCaptureRequest
from apps.shopping_cart.models import Order
from user.models import UserProfile
from .models import Compra, Payment
import sys, json
def pago(request):
order = get_object_or_404(Order, user=request.user)
payment = Payment()
payment.order = order
payment.total_amount = float(order.get_total())
payment.save()
print('payment:' + str(payment.total_amount))
data = json.loads(request.body)
order_id = data['orderID']
print('order_id: ' + order_id)
detalle = GetOrder().get_order(order_id)
detalle_precio = float(detalle.result.purchase_units[0].amount.value)
if detalle_precio == payment.total_amount:
trx = CaptureOrder().capture_order(order_id, debug=True)
print('transaccion: ' + trx.result.id)
pedido = Compra(
id= trx.result.id,
estado= trx.result.status,
codigo_estado= trx.status_code,
#HERE IS MY PROBLEM
----> **cursos= Order.items.all(),** <----
total_de_la_compra = trx.result.purchase_units[0].payments.captures[0].amount.value,
nombre_cliente= trx.result.payer.name.given_name,
apellido_cliente= trx.result.payer.name.surname,
correo_cliente= trx.result.payer.email_address,
direccion_cliente= trx.result.purchase_units[0].shipping.address.address_line_1)
pedido.save() #guardamos en base de datos la info de la Transaccion
#la funcion json en el html esta pidiendo una respuesta por lo q se le pasa esta variable data:
data = {
"id": f"{trx.result.id}",
"nombre_cliente": f"{trx.result.payer.name.given_name}",
"mensaje": "Ahora ya puedes acceder al contenido! =D"
}
return JsonResponse(data)
else:
data = {
"mensaje": "Error =( "
}
return JsonResponse(data)
if i use the expression in def pago(request): ... cursos = Order.items.all() it prints: TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use cursos.set() instead.
and all other options i dont help me to see in def pago(request) the names of the courses of OrderItems. I want this to made a "bid". And then use it with some sort of for (like this: for curso in cursos: # request.user.UserProfile.cursos.add(curso)) to add it in a UserProfile.
PLEASE HELP ME!!
EDIT: full error in console(have some extras prints()):
System check identified no issues (0 silenced).
October 25, 2020 - 01:10:01
Django version 3.1.2, using settings 'AutismoCDV.settings.local'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[25/Oct/2020 01:10:04] "GET /order-summary/ HTTP/1.1" 200 10001
payment:35.0
order_id: 504320196R962682N
detalle_precio: 35.0
Status Code: 201
Status: COMPLETED
Order ID: 504320196R962682N
Links:
self: https://api.sandbox.paypal.com/v2/checkout/orders/504320196R962682N Call Type: GET
Capture Ids:
9F055159V4840413P
Buyer:
transaccion: 504320196R962682N
Internal Server Error: /pago/
Traceback (most recent call last):
File "/home/yeti/Documentos/PROG/partesONG/10.03agregaraprofile/env/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/yeti/Documentos/PROG/partesONG/10.03agregaraprofile/env/lib/python3.8/site-packages/django/core/handlers/base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/yeti/Documentos/PROG/partesONG/10.03agregaraprofile/AutismoCDV/paypal/views.py", line 45, in pago
pedido = Compra(
File "/home/yeti/Documentos/PROG/partesONG/10.03agregaraprofile/env/lib/python3.8/site-packages/django/db/models/base.py", line 496, in __init__
_setattr(self, prop, kwargs[prop])
File "/home/yeti/Documentos/PROG/partesONG/10.03agregaraprofile/env/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 545, in __set__
raise TypeError(
TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use cursos.set() instead.
[25/Oct/2020 01:10:29] "POST /pago/ HTTP/1.1" 500 78941