Serializer Relations Doesn't Work in Django Rest Framework - python

I have two models in my application. Here is my code in models.py:
from django.db import models
class TblDivision(models.Model):
strdivisionname = models.CharField(db_column='strDivisionName', max_length=35, blank=True, null=True) # Field name made lowercase.
class Meta:
db_table = 'Tbl_Division'
class TblPosition(models.Model):
strpositionname = models.CharField(db_column='strPositionName', max_length=30, blank=True, null=True) # Field name made lowercase.
class Meta:
db_table = 'Tbl_Position'
class TblEmployee(models.Model):
strname = models.CharField(db_column='strName', max_length=70, blank=True, null=True) # Field name made lowercase.
stremployeeid = models.CharField(db_column='strEmployeeID', max_length=10, blank=True, null=True) # Field name made lowercase.
bitactive = models.BooleanField(db_column='bitActive', blank=True, null=True) # Field name made lowercase.
intdivision = models.ForeignKey(TblDivision, db_column='intDivision',related_name='division', on_delete=models.CASCADE)
intposition = models.ForeignKey(TblPosition, db_column='intPosition',related_name='position', on_delete=models.CASCADE)
class Meta:
db_table = 'Tbl_Employee'
This is my code in serializer.py:
from rest_framework import serializers
from .models import TblEmployee,TblDivision
class DivisionSerializer(serializers.ModelSerializer):
class Meta:
model = TblDivision
fields=['id','strDivisionName']
class EmployeeSerializer(serializers.ModelSerializer):
division = DivisionSerializer(many=True, read_only=True)
class Meta:
model = TblEmployee
fields=['id','strname','stremployeeid','intdivision','division']
And this my views.py:
from .models import TblEmployee
from .serializer import EmployeeSerializer,DivisionSerializer
from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
#api_view(["GET", ])
def api_list_employee_view(request):
try:
employee_list = TblEmployee.objects.all()
except TblEmployee.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == "GET":
serializer = EmployeeSerializer(employee_list, many="true")
dataEmployee = serializer.data
return Response(dataEmployee)
I want to create a simple API that shows data from Employee model and its division name in JSON Format. But the API doesn't show the strDivisionName field. It shows only field from Employee model. Can Anyone explain my problem and its solution? I'm still new in Django Rest Framewrok. Thank you before

Update your serializer with this code:
from rest_framework import serializers
from .models import TblEmployee,TblDivision
class DivisionSerializer(serializers.ModelSerializer):
class Meta:
model = TblDivision
fields=['id','strdivisionname']
In the fields, you showing the wrong field name. It's strdivisionname not strDivisionName.

my friend you made a mistake in your serializer code! you must provide exact same name you entered in your models (in models you wrote : 'strdivisionname' and in serializer : 'strDivisionName')

because you serialize your TblEmployee instance with EmployeeSerializer! and in your EmployeeSerializer there is not any strdivisionname fields! you must make a foreignKey from that in your models, am I right?

Related

serializer.data not showing any data

I'm still getting to know DRF but when I run the command serializer.data it returns an empty set. Here is what I'm working with
models.py
import datetime
from django.db import models
from django.db.models.fields.related import ForeignKey
from django.utils import timezone
from accounts.models import CustomUser
class IndustriaCategoria(models.Model):
name = models.CharField(max_length=20, null=False, blank=False)
def __str__(self):
return self.name
class Post(models.Model):
category = models.ForeignKey(IndustriaCategoria, on_delete=models.CASCADE)
author = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
title = models.CharField(max_length=512, null=False, blank=False)
body = models.TextField()
timestamp = models.DateTimeField(default=timezone.now)
link = models.URLField(max_length=500, null=True)
ups = models.IntegerField(default=0)
score = models.IntegerField(default=0)
hotness = models.IntegerField(default=0)
serializers.py
from django.db.models import fields
from rest_framework import serializers
from .models import IndustriaCategoria, Empresa, Post, Comment
class IndustriaCategoria(serializers.Serializer):
class Meta:
model = IndustriaCategoria
fielst = ('__all__')
class PostSerializer(serializers.Serializer):
class Meta:
model = Post
fields = ('__all__')
I have a management command which creates some data so I can just start throwing commands. Here is where the problem comes up:
>>> from accounts.models import CustomUser
>>> from forum.models import IndustriaCategoria, Post
>>> from forum.serializers import PostSerializer, IndustriaCategoria
>>> u = CustomUser.objects.all().first()
>>> i = IndustriaCategoria.objects.all().first()
>>> post = Post(category=i, author=u, title='hello world', body='this is a test', link='https://helloworld.com')
>>> post.save()
>>> serializer = PostSerializer(post)
>>> serializer.data
{}
Any idea why I got an empty set instead of the serialized data with the proportionated data when created the Post object?
Try to inherit from ModelSerializer instead of Serializer
class IndustriCategoria(serializers.ModelSerializer):
class Meta:
model = IndustriaCategoria
fielst = ('__all__')

'Users' object has no attribute 'values' django rest framework

I'm having a problem with serializing the data with joined tables. Am i doing this right? i'm just a newbie in django.
here's my models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class Agency(models.Model):
agency_id = models.CharField(primary_key=True, max_length=50)
agency_shortname = models.CharField(max_length=20, blank=True, null=True)
agency_longname = models.CharField(max_length=255, blank=True, null=True)
date_created = models.DateTimeField(blank=True, null=True)
class Meta:
managed = False
db_table = 'agency'
class Users(AbstractBaseUser):
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
user_id = models.CharField(primary_key=True, max_length=50)
first_name = models.CharField(max_length=50, blank=True, null=True)
middle_name = models.CharField(max_length=50, blank=True, null=True)
last_name = models.CharField(max_length=50, blank=True, null=True)
username = models.CharField(unique=True, max_length=50, blank=True, null=True)
password = models.CharField(max_length=100, blank=True, null=True)
agency = models.OneToOneField(Agency, models.DO_NOTHING)
date_created = models.DateTimeField(blank=True, null=True)
active = models.CharField(max_length=8)
login_status = models.CharField(max_length=6)
last_login = models.DateTimeField(blank=True, null=True)
class Meta:
managed = False
db_table = 'users'
Then in my serializers.py
from rest_framework import serializers
from .models import Users, Agency
class UserDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = '__all__'
class AgencyDetailSerializer(serializers.ModelSerializer):
agency_id = UserDetailSerializer()
class Meta:
model = Agency
fields = ['agency_id','agency_shortname','agency_longname']
and my views.py
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from .serializers import UserDetailSerializer
from .models import Users, Agency
from rest_framework.permissions import IsAuthenticated
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def userData(request):
username = request.GET.get('username')
r_type = request.GET.get('type')
user = Users.objects.get(username=username).values('user_id','first_name','middle_name','last_name','username','email','agency__agency_id','agency__agency_shortname','agency__agency_longname')
user_serializer = UserDetailSerializer(user, many=False)
return Response(user_serializer.data)
I'm getting an error of 'Users' object has no attribute 'values', what seems be the problem? i'm building api based application with vue.js and django rest framework. Thanks a lot
get queryset does not have values attribute, using filter instead.
user = Users.objects.filter(username=username).values(...)
Regarding your case, using get is enough and custom your Serializer like this:
class UserDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = '__all__'
agency = AgencyDetailSerializer(many=False, read_only=True)
Because values is not an attribute of model object. You can call values on queryset object. something like:
user = Users.objects.filter(username=username).values('user_id','first_name','middle_name','last_name','username','email','agency__agency_id','agency__agency_shortname','agency__agency_longname')
Note: You don't need to call values, just change this line to:
from rest_framework.generics import get_object_or_404
...
user = get_object_or_404(Users, **dict(username=username))
user_serializer = UserDetailSerializer(user)
...
Because serializer itself will handle it for you.

How the updating of m2m fields are working? Django Rest Framework

I have code where Product model has M2M field Comment model. I made methods in views.py for getting Product by id and all objects of Product, but there's problem with updating it. I can't fully understand how to update Product comments field. I already tried a lot of different answers and ideas, but nothing helps me. I'm using PUT method for update.
My main questions:
Where and how target Product id in order to update comments field in it?
After I find Product by it's id how I can update M2M field comments in it?
I tried:
Completely Lost: Many To Many with Serializers and Update in Django Rest Framework
Doesn't work at all, screams for 'collections.OrderedDict' object has no attribute 'id'
Django Rest update many to many by id
It's making PrimaryKeyRelatedField which is not correct for me.
How to update many to many Django REST?
Not enough information in answer, got stuck on it.
I read, but found no usefull information on my problem
products/models.py
from django.db import models
from comments.models import Comment
# Create your models here.
class Product(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=150, blank=True)
description = models.TextField(default="No description")
category = models.CharField(max_length=255, blank=True)
price = models.DecimalField(default=100, max_digits=15, decimal_places=2, blank=True)
photo_one = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
photo_two = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
photo_three = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
photo_four = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True, null=True)
is_popular = models.BooleanField(default=False)
is_hit = models.BooleanField(default=False)
has_sale = models.IntegerField(default=0)
comments = models.ManyToManyField(Comment, blank=True)
def __str__(self):
return self.name
comments/models.py
import uuid
from django.db import models
# Create your models here.
class Comment(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
username = models.CharField(max_length=255, default="default")
text = models.TextField()
rating = models.IntegerField()
def __string__(self):
return self.username
products/serializers.py
class ProductSerializer(serializers.ModelSerializer):
comments = CommentSerializer(many=True)
class Meta:
model = Product
fields = '__all__'
def update(self, instance, validated_data):
submitted_comments = validated_data.get('comments')
if submitted_comments:
for comment in submitted_comments:
comment_instance = Comment.objects.get(id=comment.id)
instance.children.add(comment_instance)
instance.save()
return instance
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ('id', 'username', 'text', 'rating')
products/views.py
import django_filters
from rest_framework import status
from rest_framework.generics import ListAPIView, RetrieveUpdateAPIView
from rest_framework.response import Response
from .models import Product
from .pagination import CustomPagination
from .serializers import ProductSerializer
class GetProductById(RetrieveUpdateAPIView):
serializer_class = ProductSerializer
filter_class = ProductFilter
queryset = Product.objects.all()
def get_product(self, pk):
try:
product = Product.objects.get(pk=pk)
except Product.DoesNotExist:
content = {
'status': 'Not Found'
}
return Response(content, status=status.HTTP_404_NOT_FOUND)
return product
def get(self, request, pk):
product = self.get_product(pk)
serializer = ProductSerializer(product)
return Response(serializer.data, status=status.HTTP_200_OK)
class ProductFilter(django_filters.FilterSet):
product_id = django_filters.UUIDFilter(name='id')
class Meta:
model = Product
fields = ['id']
class GetProducts(ListAPIView):
serializer_class = ProductSerializer
pagination_class = CustomPagination
def get_queryset(self):
products = Product.objects.all()
return products
def get(self, request):
products = self.get_queryset()
paginate_queryset = self.paginate_queryset(products)
serializer = self.serializer_class(paginate_queryset, many=True)
return self.get_paginated_response(serializer.data)
*products/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('api/products/', views.GetProducts.as_view(), name='get_products'),
path('api/product/<pk>/', views.GetProductById.as_view(), name='get_put_product')
]
I expect successful target by Product id and finding product.comments field
I expect successful adding new Comment to Product in it's comments field

How to add string to a ModelSerializer in Django REST

In my database, I store the file name of a particular image for an item. Let's say this is the model in models.py
from django.db import models
class Product(models.Model):
sku = models.CharField(validators=[isalphanumeric], max_length=20, null=False, blank=False)
image = models.CharField(max_length=20, blank=False, null=False)
and then I have a serializer defined like so in serializers.py
from rest_framework import serializers
from app.models import Product
class ProductSerializer(serializer.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
what I want is to be able to add a string to the image of a Product that makes it into a string representing the relative link, something like:
storage_location = '/assets/img'
img_url = f'{storage_location}/{image}'
The reason why I want to do this is because I want to be flexible with the urls rather than having the file name be a "file location" and then having to update the database each time I change how I arrange my images (I'm still not sure how to store them).
How can I do that?
First of all you can use model's ImageField for this:
class Product(models.Model):
sku = models.CharField(validators=[isalphanumeric], max_length=20, null=False, blank=False)
image = models.ImageField(max_length=20, blank=False)
This will automatically add MEDIA_URL setting to the value when you fetch value.
In case you want to use CharField you can do what you need on serializer level using SerializerMethodField:
class ProductSerializer(serializer.ModelSerializer):
image = serializers.SerializerMethodField()
def get_image(self, obj):
storage_location = '/assets/img'
img_url = f'{storage_location}/{obj.image}'
return img_url
class Meta:
model = Product
fields = '__all__'
Try following in your serialiser.py
class ProductSerializer(serializer.ModelSerializer):
img_url = serializers.SerializerMethodField()
class Meta:
model = Product
fields = '__all__'
#fields = ('sku', 'img_url') # This is what i will prefer
def get_img_url(self, obj):
storage_location = '/assets/img'
img_url = f'{storage_location}/{obj.image}'
return img_url
Good Luck!

How do I write a django-rest-framework serializer to save a nested hierarchy containing a generic model?

I am using django 1.6 and django-rest-framework 2.4. I have a generic model that has a foreign key relationship to another model. The generic model can obviously be associated with any other host model. I want to be able to save the host model and the generic model with all its associations in one go.
For example:
models.py:
from django.db import models
from django.contrib.contenttypes.generic import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
class GenericItem(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
details = models.TextField(blank=True)
class GenericSubItem(models.Model):
generic_item = models.ForeignKey(GenericItem, null=True, blank=True, related_name="sub_items")
details = models.TextField(blank=True)
class Host(models.Model):
details = models.TextField(blank=True)
generic_items = GenericRelation(GenericItem, content_type_field='content_type', object_id_field='object_id')
serializers.py:
from rest_framework import serializers
from . import models
class GenericSubItemSerializer(serializers.ModelSerializer):
class Meta:
model = models.GenericSubItem
fields = ('id', 'details', )
class GenericItemSerializer(serializers.ModelSerializer):
sub_items = GenericSubItemSerializer(many=True, required=False, allow_add_remove=True)
class Meta:
model = models.GenericItem
fields = ('id', 'details', 'sub_items', )
class HostSerializer(serializers.ModelSerializer):
generic_items = GenericItemSerializer(many=True, required=False, allow_add_remove=True)
class Meta:
model = models.Host
fields = ('id', 'details', 'generic_items', )
views.py:
from rest_framework import viewsets
from . import serializers, models
class HostView(viewsets.ModelViewSet):
queryset = models.Host.objects.all()
serializer_class = serializers.HostSerializer
The problem here is that the sub_items don't get saved, even though they are posted. Even worse, if you add a sub item through the shell, it will display it fine but when you save, the sub item is deleted.
How should the serializer be written so that saving the host will save everything else?
Thanks,
Paul
Could you please give more details about your views.py? Or you can have a try to override your create(self, validated_data) in your GenericItemSerializer as follow:
class GenericItemSerializer(serializers.ModelSerializer):
sub_items = GenericSubItemSerializer(many=True, required=False, allow_add_remove=True)
class Meta:
model = models.GenericItem
fields = ('id', 'details', 'sub_items', )
def create(self, validate_data):
subitemdata = validate_data.pop('sub_items')
subitemobj = GenericSubItem.objects.create(**subitemdata)
GenericItem.objects.create(sub_items=subitemobj, **validate_data)

Categories

Resources