Cannot properly save to a db with OneToOne relationship - python

The flow of what I want to do is the following:
I have two tables, namely Event and Result. The Event table is connected with ForeignKey with a user and the Result table is connected with OneToOne relationship with Event. In my views.py I have one POST and one GET. In POST, I take some data and save it in the table Event. In GET, I solve an optimization problem and I want to save the solution into Result.
The models.py is as follows:
from django.db import models
from django.contrib.postgres.fields import ArrayField
from django.contrib.auth import get_user_model
CustomUser = get_user_model()
class Event(models.Model):
user_id_event = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True)
dr_notice_period = models.IntegerField(blank=True, null=True)
dr_duration = models.IntegerField(blank=True, null=True)
dr_request = models.FloatField(blank=True, null=True)
class Result(models.Model):
event_id_result = models.OneToOneField(Event, on_delete=models.CASCADE, null=True)
HVAC_flex = ArrayField(models.FloatField(blank=True, null=True))
DHW_flex = ArrayField(models.FloatField(blank=True, null=True))
lights_flex = ArrayField(models.FloatField(blank=True, null=True))
The serializers.py is as follows:
from rest_framework import serializers
from vpp_optimization.models import Event, Result
class EventSerializer(serializers.ModelSerializer):
class Meta:
model = Event
fields = ('__all__')
class ResultSerializer(serializers.ModelSerializer):
HVAC_flex = serializers.ListField(child=serializers.FloatField())
DHW_flex = serializers.ListField(child=serializers.FloatField())
lights_flex = serializers.ListField(child=serializers.FloatField())
class Meta:
model = Result
fields = ('__all__')
The views.py is as follows:
from rest_framework.response import Response
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
from vpp_optimization.importer import DR_event_import_data
from vpp_optimization.utils import optimization_solution, convert_dict_for_serializer
from vpp_optimization.serializers import EventSerializer, ResultSerializer
from vpp_optimization.models import Event, Result
#api_view(['POST'])
#permission_classes([IsAuthenticated,])
def event(request):
serializer = EventSerializer(data=request.data)
if serializer.is_valid():
serializer.save(user_id_event=request.user)
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
else:
return Response({"status": "error", "data": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
#api_view(['GET'])
def optimization(request):
last_event = Event.objects.last()
if not last_event:
return Response({"res": "Object Event does not exists"}, status=status.HTTP_400_BAD_REQUEST)
serializer = EventSerializer(last_event)
response_dict = {}
DR_event_data = DR_event_import_data(serializer.data)
response_dict = optimization_solution(DR_event_data)
response_dict_final = convert_dict_for_serializer(response_dict)
serializer_result = ResultSerializer(data=response_dict_final)
if serializer_result.is_valid():
serializer_result.save(event_id_result=last_event.id)
return Response(serializer_result.data, status=status.HTTP_200_OK)
However, I am getting the following error:
ValueError: Cannot assign "2": "Result.event_id_result" must be a "Event" instance.
The error is due to the way that I am trying to save with the OneToOne relationship, namely in this line of the views.py:
event_id_result=last_event.id
Apparently, this is not the correct way to connect the two databases. Does anyone can help me find the correct way?

Change:
event_id_result=last_event.id
To:
event_id_result=last_event

Related

cannot show the field 'name' in REST API

When I try to retrieve all data from my REST API I get them correctly except from one field, that is the field 'name' from Skill class. Instead of the 'name' I get only its id. Can you help me to resolve this?----------------------------------------------
here is the output
Here is the code:
models.py
from django.db import models
from django.forms import ImageField
from django.utils.text import slugify
class Skill(models.Model):
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class Project(models.Model):
title = models.CharField(max_length=200)
sub_title = models.CharField(max_length=200, null=True, blank=True)
front_page = models.ImageField(null=True, blank=True, upload_to="images", default="broken-image.png")
body = models.TextField(null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
skills = models.ManyToManyField(Skill, null=True)
slug = models.SlugField(null=True, blank=True)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if self.slug == None:
slug = slugify(self.title)
has_slug = Project.objects.filter(slug=slug).exists()
count = 1
while has_slug:
count += 1
slug = slugify(self.title) + '-' + str(count)
has_slug = Project.objects.filter(slug=slug).exists()
self.slug = slug
super().save(*args, **kwargs)
serializers.py
from rest_framework import serializers
from project.models import Project, Skill
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = '__all__'
views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view
from project.models import Project, Skill
from .serializers import ProjectSerializer
from rest_framework import status
from django.shortcuts import get_object_or_404
#api_view(['GET'])
def getData(request):
project = Project.objects.all()
serializer = ProjectSerializer(project, many=True)
return Response(serializer.data)
#api_view(['POST'])
def create(request):
serializer= ProjectSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
#api_view(['POST'])
def update(request, pk):
item = Project.objects.get(pk=pk)
serializer = ProjectSerializer(instance=item, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(status=status.HTTP_404_NOT_FOUND)
#api_view(['DELETE'])
def delete(request, pk):
item = get_object_or_404(Project, pk=pk)
item.delete()
return Response(status=status.HTTP_202_ACCEPTED)
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.getData),
path('create/', views.create),
path('update/<int:pk>/', views.update),
path('<int:pk>/delete/', views.delete),
]
Use a SlugRelatedField [drf-doc] to specify that you want to use the name of the skills, so:
from rest_framework import serializers
from project.models import Project, Skill
class ProjectSerializer(serializers.ModelSerializer):
skills = serializers.SlugRelatedField(
many=True, slug_field='name', queryset=Skill.objects.all()
)
class Meta:
model = Project
fields = '__all__'
The nice thing of such SlugRelatedField is that this can work bidrectional: not only can you serialize data, but you can also use it to specify skills and thus create or update Projects.
You need to provide a SkillSerializer and refer to it in your ProjectSerializer. Also, it is better to specify the fields you want in your serializers explicitly, as __all__ may expose the fields you don't want to expose or cause unwanted database queries.
https://www.django-rest-framework.org/api-guide/relations/#nested-relationships

How to solve in Django REST API the serializing of data from 2 models with ForeignKey

I was wondering what the correct way is to serialize data in Django REST API from 2 models connected with ForeignKey.
The situation is: i have a 1st table called NewUsers with the user registrations, and a 2nd table called Ticker with data saved from an external API.
The goal is: create a 3rd table with parts of the 2 tables interconnected - one part is the user loggedin, and the other part is the selection of one crypto object. This new table will then be displayed via Django REST API serializer.
The problem is: this new 3rd table does not display the complete list of values selected by the user.
I have gone through the documentation here https://books.agiliq.com/projects/django-admin-cookbook/en/latest/override_save.html and here https://www.django-rest-framework.org/tutorial/1-serialization/ but could not find a complete solution. What am i missing?
views.py:
from rest_framework import generics
from .serializers import WatchlistSerializer
from ticker.serializers import TickerSerializer
from watchlist.models import SectionWatchlist
from ticker.models import Ticker
import requests
from rest_framework.views import APIView
from rest_framework.decorators import api_view
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
class CreateSectionWatchlist(generics.CreateAPIView):
queryset = SectionWatchlist.objects.all()
serializer_class = WatchlistSerializer
class ListSectionWatchlist(generics.ListAPIView):
queryset = SectionWatchlist.objects.all()
serializer_class = WatchlistSerializer
def get_queryset(self):
queryset = SectionWatchlist.objects.all()
author = self.request.query_params.get('author')
if author:
queryset = queryset.filter(author=author)
return queryset
class DeleteSectionWatchlist(generics.RetrieveDestroyAPIView):
queryset = SectionWatchlist.objects.all()
serializer_class = WatchlistSerializer
models.py:
from django.db import models
from django.conf import settings
from ticker.models import Ticker
class SectionWatchlist(models.Model):
id = models.AutoField(primary_key=True) # auto increment field
tickerlist = models.ForeignKey(Ticker, related_name="tickerinfo", on_delete=models.CASCADE)
crypto = models.CharField(blank=True, null=True, max_length=40)
c_0 = models.FloatField(null=True, blank=True, default=None)
o_0 = models.FloatField(null=True, blank=True, default=None)
percentage = models.FloatField(null=True, blank=True, default=None)
user_name = models.CharField(blank=True, null=True, max_length=40)
author = models.ForeignKey(
settings.AUTH_USER_MODEL, blank=True, null=True,
on_delete=models.CASCADE,
)
serializers.py:
from rest_framework import serializers
from watchlist.models import SectionWatchlist
from ticker.models import Ticker
from ticker.serializers import TickerSerializer
class WatchlistSerializer(serializers.ModelSerializer):
crypto = TickerSerializer()
class Meta:
model = SectionWatchlist
fields = ('id','tickerlist','author', 'crypto')
the Django REST API incomplete response
{
"id": 88,
"tickerlist": 36,
"author": 6,
"crypto": {
"crypto": null,
"c_0": null,
"o_0": null
}
}
]
admin.py:
from django.contrib import admin
from django import forms
from . import models
from ticker.models import Ticker
#admin.register(models.SectionWatchlist)
class WatchlistAdmin(admin.ModelAdmin):
list_display = (
'id',
# 'percentage',
'tickerlist',
# 'user_name',
'author',
'get_crypto',
'get_c_0',
'get_o_0',
)
#admin.display(ordering='watchlist__tickerlist', description='get_crypto')
def get_crypto(self, obj):
return obj.tickerlist.crypto
#admin.display(ordering='watchlist__tickerlist', description='c_0')
def get_c_0(self, obj):
return obj.tickerlist.c_0
#admin.display(ordering='watchlist__tickerlist', description='o_0')
def get_o_0(self, obj):
return obj.tickerlist.o_0
Actually my admin displays the response correctly with complete values:
.
How can I have the serialized response in Django REST API complete?
I think you need to set the serializer for the foreign key fields.
class WatchlistSerializer(serializers.ModelSerializer):
tickerlist= TickerSerializer()
author = UserSerializer()
class Meta:
model = SectionWatchlist
fields = ('id', 'tickerlist', 'author', 'crypto')

Django rest framework function base view how to get object by string not id

Problem: I trying to path like this --> path('Image/<str>', views.getImage, name='imageCategory'),
to get image filter by category --> http://127.0.0.1:8000/Image/TV
#-->Model.py
from django.db import models
class Post(models.Model):
Topic = models.CharField(max_length=250, default='')
Desc = models.CharField(max_length=750, default='')
Link = models.TextField(default='')
def __str__(self):
return str(self.Topic)
class Category(models.Model):
categoryName = models.CharField(max_length=50, default='')
def __str__(self):
return str(self.categoryName)
class PostImage(models.Model):
post = models.ForeignKey(
Post, on_delete=models.CASCADE, null=True, related_name='post_name')
category = models.ForeignKey(
Category, on_delete=models.CASCADE, null=True, related_name='category_name')
images = models.FileField(upload_to='images/')
def __str__(self):
return str(self.post)
#-->Serializer.py
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import Post, PostImage
class BlogSerializer(ModelSerializer):
class Meta:
model = Post
fields = '__all__'
class ImageSerializer(ModelSerializer):
topic_link = serializers.CharField(source='post.Link', read_only=True)
Category = serializers.CharField(source='category', read_only=True)
class Meta:
model = PostImage
fields = '__all__'
#-->view.py
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Post, PostImage
from .Serializer import BlogSerializer, ImageSerializer
# Create your views here.
#api_view(['GET'])
def getNames(request):
Blog = Post.objects.all()
serializer = BlogSerializer(Blog, many=True)
return Response(serializer.data)
#api_view(['GET'])
def getName(request, pk):
Blog = Post.objects.get(id=pk)
serializer = BlogSerializer(Blog, many=False)
return Response(serializer.data)
#my problem part
#api_view(['GET'])
def getImage(request):
image = PostImage.objects.get(Category=request.Category)
serializer = ImageSerializer(image, many=True)
return Response(serializer.data)
#-->urls.py
from django.urls import path
from . import views
urlpatterns = [
path('blogs/', views.getNames, name='blog'),
path('blogs/<pk>', views.getName, name='blog'),
path('Image/', views.getImage, name='image'),
path('Image/<str>', views.getImage, name='imageCategory'),
]
First, you need to set the parameter name in urls.py.
urlpatterns = [
...
path('Image/', views.getImages, name='image'),
path('Image/<str:category>', views.getImage, name='imageCategory'),
]
Here the category should be the categoryName value of the Category model.
Next, in views.py, you need to pass that parameter to the getImage function.
And also you need to add getImages function for the case of no category.
#api_view(['GET'])
def getImage(request, category):
image = PostImage.objects.filter(category__categoryName=category)
serializer = ImageSerializer(image, many=True)
return Response(serializer.data)
#api_view(['GET'])
def getImages(request):
image = PostImage.objects.all()
serializer = ImageSerializer(image, many=True)
return Response(serializer.data)

Object of type ProductImage is not JSON serializable

I am getting this error Object of type ProductImage is not JSON serializable
I am trying to make model in which I can add multiple images using ManytoManyFeild().and I then I want to serialize it so that I can send it to and show on frontend page.
here is my models:
from django.db import models
class Product(models.Model):
id = models.IntegerField(unique=True,primary_key=True)
title = models.CharField(max_length=200)
description = models.TextField(max_length= 100000 ,null=True, blank=True)
price = models.FloatField()
count = models.IntegerField(default=1)
file_content = models.ManyToManyField("ProductImage", related_name='file_content', blank=True, null=True)
offer= models.BooleanField(default=False)
def __str__(self):
return self.title
class ProductImage(models.Model):
property_id = models.ForeignKey(Product,on_delete=models.CASCADE ,null=True, blank=True)
media = models.FileField(upload_to='pics')
def __str__(self):
return '%s-image' % (self.property_id.title)
and here is my serializer.py:
from rest_framework import serializers
from . models import Product, ProductImage
class ProductImageSerializer(serializers.ModelSerializer):
class Meta:
model = ProductImage
fields = [ 'property_id','media']
class ProductSerializer(serializers.ModelSerializer):
file_content = ProductImageSerializer(many=True)
class Meta:
model = Product
fields = ['id', 'title','description', 'price','count', 'file_content',
'offer']
extra_kwargs = {
"file_content": {
"required": False,
}
}
and here is my Views.py:
from rest_framework.serializers import Serializer
from . models import Product, ProductImage
from rest_framework.response import Response
from . serializer import ProductSerializer
from rest_framework import status
from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.decorators import api_view, permission_classes, parser_classes
from rest_framework.permissions import IsAuthenticated
#api_view(['POST','GET'])
#permission_classes([IsAuthenticated])
#parser_classes([MultiPartParser, FormParser])
def ProductViews(request):
if request.method == 'POST':
files = request.FILES.getlist('file_content')
if files:
request.data.pop('file_content')
serializer = ProductSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
tweet_qs = Product.objects.get(id=serializer.data['id'])
uploaded_files = []
for file in files:
content = ProductImage.objects.create(media=file)
uploaded_files.append(content)
tweet_qs.file_content.add(*uploaded_files)
context = serializer.data
context["file_content"] = [file.id for file in uploaded_files]
return Response(context, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
serializer = ProductSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
context = serializer.data
return Response(context, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'GET':
detail = [{"title": detail.title, "id": detail.id, "count": detail.count, "description": detail.description, "price": detail.price, "offer": detail.offer , "details": detail.file_content.all()}
for detail in Product.objects.all()]
return Response(detail)
I don't what's wrong so I will be very grateful to you if can help. Thanks
Note:If you know any other better way to make a Json that can include a list of images, you can also share it(or its link).
This may help you:
class ProductImage(models.Model):
property_id = models.ForeignKey(Product, on_delete=models.CASCADE ,null=True, blank=True)
media = models.FileField(upload_to='pics')
def __str__(self):
return '%s-image' % (self.property_id.title)
def media_url(self):
return self.media.url
class ProductImageSerializer(serializers.ModelSerializer):
class Meta:
model = ProductImage
fields = [ 'property_id','media','media_url']

error in Django RestFrameWork "NOT NULL constraint failed: qoura_question.author_id "

trying to add a post to DRF which takes the information of USER and TIME automatically, But this is the error which pops up when tried to add a Post.
models.py:
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
class Post(models.Model):
title = models.CharField(max_length = 200)
description = models.CharField(max_length = 2000)
date_posted = models.DateTimeField(default = timezone.now)
author = models.ForeignKey(User , on_delete = models.CASCADE)
def __str__(self):
return self.title
Views.py:
class PostViewSet(ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
authentication_classes = [TokenAuthentication,SessionAuthentication]
def create(self, request):
obj = Post()
obj.title = request.data['title']
obj.description = request.data['description']
obj.date_posted = request.data['date_posted']
obj.user = request.user
obj.save()
return Response(status=status.HTTP_201_CREATED)
serializer.py:
from rest_framework import serializers
from django.contrib.auth.models import User
from . models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('id', 'title','description','date_posted','author')

Categories

Resources