'MoneyField' object has no attribute 'serialize' - python-3.x

I have model Product with field MoneyField in /products/models.py
class Product(SeoModel, ModelWithMetadata, PublishableModel):
name = models.CharField(max_length=128)
currency = models.CharField(
max_length=settings.DEFAULT_CURRENCY_CODE_LENGTH,
default=settings.DEFAULT_CURRENCY,
)
price_amount = models.DecimalField(
max_digits=settings.DEFAULT_MAX_DIGITS,
decimal_places=settings.DEFAULT_DECIMAL_PLACES,
)
price = MoneyField(amount_field="price_amount", currency_field="currency")
My views.py is:
from .models import Product
from .serializers import ProductListSerializer
from rest_framework import generics
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductListSerializer
and serializers.py:
from rest_framework import serializers
from .models import Product
class ProductListSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['name', 'id']
and when i go to url i have error:
AttributeError at /ru/products/api/
'MoneyField' object has no attribute 'serialize'
Request Method: GET
Request URL: http://127.0.0.1:8000/ru/products/api/
Django Version: 2.2.6
Exception Type: AttributeError
Exception Value:
'MoneyField' object has no attribute 'serialize'
Can you help me? Thank you!

DRF's ModelSerializer assumes fields that are on the model extend django.db.models.fields.Field, which MoneyField does not. This is a problem when ModelSerializer is collecting fields:
# rest_framework.utils.model_meta._get_fields
def _get_fields(opts):
fields = OrderedDict()
for field in [field for field in opts.fields if field.serialize and not field.remote_field]:
fields[field.name] = field
return fields
You can fix the problem by subclassing MoneyField:
from django_prices.models import MoneyField as BaseMoneyField
class MoneyField(BaseMoneyField):
serialize = True
This will probably lead to your next problem ;)

Related

How can I fetch more than one attribute from a serializer

My models have multiple attributes, all of which are being serialized.
According to the user's request, I want my API to return only limited information
This is my model's code
from django.db import models
class User(models.Model):
name = models.CharField(max_length=50)
age = models.PositiveSmallIntegerField()
description = models.CharField(max_length=200)
def __str__(self) -> str:
return self.name
This is my Serializer's code
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
This is my View's code
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import User
from .serializers import UserSerializer
from rest_framework import serializers
from rest_framework import status
from django.http import JsonResponse
#api_view(['GET'])
def viewUsers(request):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return JsonResponse({'id': serializer.data['id'], 'name': serializer.data['name']})
The code below works if I want to return a single attribute/field
return JsonResponse(serializer.data['id'])
but when I try to fetch more than one attribute by the dictionary method, it throws this error
list indices must be integers or slices, not str
many=True passed to UserSerializer indicates that serializer.data will contain a list of dicts where each particular dict will be a result of serializing User instance to expected dict
Taking into account serializer.data is a list then if you try to execute serializer.data['id'] it raises
list indices must be integers or slices, not str
You may want to update the return statement to
return JsonResponse([{'id': item['id'] for item in serializer.data}])
or specify that you expect only id field to be returned by the serializer
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ("id",)
and then in the view
return JsonResponse(serializer.data)

Providing custom field in serializer using model data

In Problem model I'm storing a list of users who have done it. In Problem serializer when user will request his data I want to show him if he has done certain problem. So I created custom field in serializer class and want to fill it using models data.
this is what I have done.
from rest_framework import serializers
from dsa.models import Problem
class ProblemSerializer(serializers.ModelSerializer):
isDoneByUser = serializers.BooleanField(default=False)
class Meta:
model = Problem
fields = ['id', 'topic', 'title', 'link', 'isDoneByUser']
def perform_create(self, serializer):
user = self.request.user
userlist = serializer.data.get('isDone')
print(userlist)
if user in userlist:
self.isDoneByUser = True
here is the model
from django.db import models
from django.contrib.auth.models import User
class Problem(models.Model):
topic = models.CharField(max_length=100)
title = models.CharField(max_length=100)
link = models.URLField()
isDone = models.ManyToManyField(User)
class Meta:
ordering = ['topic']
But this always setting isDoneByUser = False(default value)
please help!
You cannot set isDoneByUser to True as it does not exist in your model.
You can however get the boolean with a SerializerMethodField:
class ProblemSerializer(serializers.ModelSerializer):
isDoneByUser = serializers.SerializerMethodField()
def get_isDoneByUser(self, instance):
user = self.context['request'].user
return instance.isDone.filter(pk=user.pk).exists()
class Meta:
model = Problem
fields = ['id', 'topic', 'title', 'link', 'isDoneByUser']

Querying users based on time

I want to add a class-based view to return users created from one date to another date. I have tried the following are there other ways to filter the user-created between two dates?
While doing this I get:
TypeError: get() missing 1 required positional argument: 'to_date'
views.py
class RegisteredUserFilter(APIView):
serializer = RegisteredUserFilterSerializer
def get(self, from_date, to_date):
userondate = User.objects.filter(created_at__range=[from_date, to_date]).values()
return Response({"User": userondate})
serializers.py
class RegisteredUserFilterSerializer(serializers.Serializer):
from_date = serializers.DateField()
to_date = serializers.DateField()
model = User
full code at: https://github.com/abinashkarki/rest_framework_authentication/tree/master/authapp
using Django filters
serilaizers.py
add the following
class RegisteredUserFilterSerializer(serializers.Serializer):
class Meta:
model = User
fields = ['username', 'created_at']
make file name it filters.py in same path of views.py
filters.py
from django_filters.rest_framework import FilterSet
import django_filters
from .models import User
from django_filters.widgets import RangeWidget
class UserFilter(FilterSet):
date_range = django_filters.DateFromToRangeFilter(label='Date Range', field_name='created_at',
widget=RangeWidget(attrs={'type': 'date'}))
class Meta:
model = User
fields = ['created_at']
Views.py
from .serializers import RegisteredUserFilterSerializer
from .filters import UserFilter
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.generics import ListAPIView
class RegisteredUserFilter(ListAPIView):
serializer_class = RegisteredUserFilterSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = UserFilter
model = User
urls.py add
from django.urls import path
from .views import RegisteredUserFilter
urlpatterns = [
path('users-filter/', RegisteredUserFilter.as_view(), name="user-filter"),
]
finally do not forget to make
pip install django-filter
and add it to installed app in settings.py
INSTALLED_APPS = [
...
'django_filters',
]
for more information refer to https://django-filter.readthedocs.io/en/stable/guide/rest_framework.html
another approach
you can make this process manually by overriding the get method and getting query parameters manually
and return response after serializing the query set

TypeError: Object of type Asia/Kolkata is not JSON serializable

I am trying to use timezone_field, but it shows it is not serializable and shows error.
Please need your help. I have provided code in below..
Thanks in advance.
Models.py
from django.db import models
from timezone_field import TimeZoneField
# Create your models here.
class Member(models.Model):
tz = TimeZoneField(default='Asia/Kolkata')
def __str__(self):
return self.tz
serializers.py
from . models import Member
from rest_framework.serializers import ModelSerializer
class Member_Serializer(ModelSerializer):
class Meta:
model = Member
fields = '__all__'
views.py
from . models import Member
from . serializers import Member_Serializer
from rest_framework.generics import ListCreateAPIView
# Create your views here.
class MemberListView(ListCreateAPIView):
queryset = Member.objects.all()
serializer_class = Member_Serializer
error:
Object of type Asia/Kolkata is not JSON serializable
Request Method: POST
Request URL: http://localhost:8000/a/
Django Version: 3.1.1
Exception Type: TypeError
Exception Value:
Object of type Asia/Kolkata is not JSON serializable
You need to specify the serialization behaviour for the tz field
from .models import Member
from rest_framework import serializers
class Member_Serializer(serializers.ModelSerializer):
tz = serializers.CharField()
class Meta:
model = Member
fields = '__all__'

Exception Type: AssertionError Exception Value: Class RatingSerializers missing "Meta.model" attribute

hi guys i a newbie and learning django-framework and building rest-api
i'm stuck at this error . Its gives me error at venv\lib\site-packages\rest_framework\serializers.py in get_fields, line 1020. and says Class RatingSerializers missing "Meta.model" attribute.
i did all migration and makemigration
Exception Type: AssertionError
Exception Value:
Class RatingSerializers missing "Meta.model" attribute
urls.py
from django.contrib import admin
from django.urls import path
from rest_framework import routers
from django.conf.urls import include
from .views import MovieViewSet, RatingViewSet
router = routers.DefaultRouter()
router.register('movies', MovieViewSet)
router.register('ratings', RatingViewSet)
urlpatterns = [
path('', include(router.urls)),
]
models.py
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator, MinValueValidator
class Movie(models.Model):
title = models.CharField(max_length=32)
description = models.TextField(max_length=500)
class Rating(models.Model):
movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
stars = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)])
class Meta:
unique_together = (('user', 'movie'),)
index_together = (('user', 'movie'),)
serializer.py
from rest_framework import serializers
from .models import Movie, Rating
class MovieSerializers(serializers.ModelSerializer):
class Meta:
model: Movie
fields = ('id', 'title', 'description')
class RatingSerializers(serializers.ModelSerializer):
class Meta:
model: Rating
fields = ('id', 'stars', 'user', 'movie')
views.py
from django.shortcuts import render
from rest_framework import viewsets
from .models import Movie, Rating
from .serializers import MovieSerializers, RatingSerializers
class MovieViewSet(viewsets.ModelViewSet):
queryset = Movie.objects.all()
serializer_class = MovieSerializers
class RatingViewSet(viewsets.ModelViewSet):
queryset = Rating.objects.all()
serializer_class = RatingSerializers
i have no idea what is wrong with it.
You have to do
model = Rating
instead of
model: Rating
And same for the movies serializer too

Resources