I am quite new to Django and I am building a simple referral system where a code is autogenerated for the user and when this code is called, the API should return the user by which this code was referred. However I am experiencing some difficulties to return the username, getting the error TypeError: Object of type User is not JSON serializable. Below I am posting my code (please ignore the unused imports, I was trying many things and I need to clean the code later)
views.py `
from rest_framework.decorators import api_view
from rest_framework.response import Response
import json, requests
from rest_framework.views import APIView
from django.http import JsonResponse, HttpResponse
from django.core import serializers
from django.core.serializers import serialize
import ast
from rest_framework.parsers import JSONParser
class MainView(APIView):
def post(self, request):
code = request.data["ref_code"]
print(str(code))
try:
profile = ReferralSys.objects.get(code=code)
print(profile)
request.session["ref_profile"] = profile.user
username = profile.user.username
print(username)
print(type(username))
# return HttpResponse("user is here", user)
except:
pass
print(request.session.get_expiry_date())
return Response(f"{profile.user.username}")
models.py
from django.db import models
from django.contrib.auth.models import User
from .utils import generate_ref_code
class ReferralSys(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(blank=True)
code = models.CharField(max_length=12, blank=True)
recommented_by = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True, related_name="ref_by"
)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user.username}-{self.code}"
def get_recommended_profiles(self):
pass
def save(self, *args, **kwargs):
if self.code == "":
code = generate_ref_code()
self.code = code
super().save(*args, **kwargs)
utils.py
import uuid
def generate_ref_code():
code = str(uuid.uuid4()).replace("-", "")[:12]
return code
urls.py
from django.contrib import admin
from django.urls import path
from .views import MainView
urlpatterns = [
path("admin/", admin.site.urls),
path("", MainView.as_view()),
path("str:<ref_code>", MainView.as_view()),
]
Thank you in advance for the help.
PS: I am following this tutorial https://www.youtube.com/watch?v=QZfflGvRQrc&t, but instead of using templates I want to use APIView.
CodePudding user response:
What happens is that Django sessions serializes data using JSON. When writing:
request.session["ref_profile"] = profile.user
You are trying to insert a model inside the session, thus the error. One basic and simple way, is to parse the desired data into a JSON:
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import ReferralSys
import json
class MainView(APIView):
def post(self, request, code=None):
if code is None:
code = request.data['code']
try:
profile = ReferralSys.objects.get(code=code)
user = {
'username': profile.user.username,
'email': profile.user.email
}
user_json = json.dumps(user)
request.session["ref_profile"] = user_json
except:
pass
print(request.session.get_expiry_date())
return Response(f"{profile.user.username}")
Of course, there are tradeoffs and I recommend you to read the documentation in order to understand them. There is also another mistake in the form of how you are passing (and retrieving) the extra keyword argument in the URL, the right sintax:
path("<str:code>/", MainView.as_view()),