BooleanField in ModelSerializer - django

I want to display the content of Trader class through an API call. But I don't know where am I wrong.
models.py
class Trader(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="trader")
bot_status = models.BooleanField(blank=False, default=False)
active_group = models.ManyToManyField(Entry, blank=True, related_name="active_group")
def __str__(self):
return f'{self.user.username}'
def __repr__(self):
return f'Trader=(bot_status={self.bot_status}, active_group={self.active_group})'
serializers.py
class BotStatusSerializer(serializers.ModelSerializer):
user = serializers.ReadOnlyField(source = 'user.username')
class Meta:
model = Trader
read_only_fields = ('bot_status', )
views.py
class BotStatusView(viewsets.ModelViewSet):
serializer_class = BotStatusSerializer
def get_queryset(self):
return self.request.user.trader.bot_status
When I make the request I get the following Error.
Error:
return [
TypeError: 'bool' object is not iterable

You are returning bot_status, a boolean, from get_queryset, which needs to return a QuerySet.
def get_queryset(self):
return Trader.objects.filter(trader=self.request.user)

Related

DRF- Got assertion error when I give Post Request

Error
AssertionError: The `.create()` method does not support writable dotted-source fields by default.
Write an explicit `.create()` method for serializer `hrm_apps.configuration.serializers.CurrencySerializer`, or set `read_only=True` on dotted-source serializer fields.
models.py,
class CurrencyMaster(models.Model):
code = models.CharField(max_length=3, null=False, unique=True)
name = models.CharField(max_length=100, null=False, unique=True)
def __str__(self):
return self.name
class Currency(models.Model):
currency_master = models.OneToOneField(CurrencyMaster, on_delete=models.RESTRICT)
conversion_rate = models.FloatField(null=False)
def __str__(self):
return self.currency_master.name
views.py,
class CurrencyViewSet(viewsets.ModelViewSet):
queryset = Currency.objects.all()
serializer_class = CurrencySerializer
lookup_field = 'id'
serializers.py,
class CurrencySerializer(serializers.ModelSerializer):
currency_master = serializers.CharField(source="currency_master.name")
class Meta:
model = Currency
fields = ['id', 'currency_master', 'conversion_rate']
When i give post request i got assertion error like above,
class CurrencySerializer(serializers.ModelSerializer):
currency_master = serializers.CharField(source="currency_master.name")
class Meta:
model = Currency
fields = ['id', 'currency_master', 'conversion_rate']
def create(self, validated_data):
return Currency.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.currency_master = validated_data.get('currency_master', instance.currency_master)
instance.conversion_rate = validated_data.get('conversion_rate', instance.conversion_rate)
return instance
I tried above i got this error "ValueError: Cannot assign "{'name': 'ALL - Albania Lek'}": "Currency.currency_master" must be a "CurrencyMaster" instance". How to resolve this???
Customize the create method.
class CurrencySerializer(serializers.ModelSerializer):
currency_master = serializers.CharField(source="currency_master.name")
class Meta:
model = Currency
fields = ['id', 'currency_master', 'conversion_rate']
def create(self, validated_data):
currency_master_name = validated_data.pop('currency_master')["name"]
currency_master_obj = get_object_or_404(CurrencyMaster, name=currency_master_name)
validated_data["currency_master"] = currency_master_obj
return Currency.objects.create(**validated_data)

Django Rest Framework nested serializer gives attribute error

I am trying to setup a nested serializer below I've posted the models and serializer. why am I getting the below error ?
Got AttributeError when attempting to get a value for field `balance_sheet` on serializer `StockSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Stock` instance.
Original exception text was: 'Stock' object has no attribute 'balance_sheet'.
serializers.py
class StockSerializer(serializers.ModelSerializer):
income_statement = IncomeStatementSerializer(many=True)
balance_sheet = BalanceSheetSerializer(many=True)
cashflows_statement = CashflowsStatementSerializer(many=True)
def create(self, validated_data):
temp_income_statement_data = validated_data.pop("income_statement")
temp_balance_sheet_data = validated_data.pop("balance_sheet")
temp_cashflows_statement_data = validated_data.pop("cashflows_statement")
new_stock = Stock.objects.create(**validated_data)
for i in temp_income_statement_data:
IncomeStatement.objects.create(**i, ticker=new_stock)
for x in temp_balance_sheet_data:
BalanceSheet.objects.create(**x, ticker=new_stock)
for y in temp_cashflows_statement_data:
CashflowsStatement.objects.create(**y, ticker=new_stock)
return new_stock
IncomeStatementSerializer, BalanceSheetSerializer and CashflowsStatementSerializer are all typical ModelSerializer's
models.py
class Stock(models.Model):
id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
ticker = models.CharField(max_length=10, unique=True, primary_key=True)
slug = models.SlugField(default="", editable=False)
def save(self, *args, **kwargs):
value = self.ticker
self.slug = slugify(value, allow_unicode=True)
super().save(*args, **kwargs)
def __str__(self):
return self.ticker
class Meta:
verbose_name = "stock"
verbose_name_plural = "stocks"
ordering = ["ticker"]
IncomeStatement, BalanceSheet and CashflowsStatement are all typical models.Model with a ForeignKey relationship to Stock
views.py
class StockList(generics.ListCreateAPIView):
queryset = Stock.objects.all()
serializer_class = StockSerializer
lookup_field = "slug"

django rest framework : nested model get not working. 'str' object has no attribute 'values'

I have a customer model in Bcustomer app that extends the django User model, So I will save the basic details such as name in User table and the remaining data (city, etc) in customer table.
Saving is working perfectly. But now it is showing the following error when I call the GET method.
AttributeError at /api/v1/customer 'str' object has no attribute 'values'
Request Method: GET
bcustomer/models.py
class BCustomer(models.Model):
customer = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True, blank=True )
address = models.CharField(max_length=50)
city = models.CharField(max_length=256)
state = models.CharField(max_length=50)
user = models.ForeignKey(settings.AUTH_USER_MODEL, db_index=True, on_delete=models.CASCADE, related_name='customer_creator')
# more fields to go
def __str__(self):
# return str(self.name) (This should print first and last name in User model)
class Meta:
app_label = 'bcustomer'
bcusomer/serializers.py
class CustomerDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = BCustomer
fields = ('city', 'phone')
class CustomerSerializer(serializers.ModelSerializer):
customer_details = CustomerDetailsSerializer()
class Meta:
model = get_user_model()
fields = ('id','first_name', 'email', 'customer_details')
def create(self, validated_data):
request = self.context.get('request')
customer_details_data = validated_data.pop('customer_details')
customer_user = get_user_model().objects.create(**validated_data)
BCustomer.objects.create(customer=customer_user, user=request.user, **customer_details_data)
customer_user.customer_details = customer_details_data
return customer_user
class CustomerListSerializer(serializers.ModelSerializer):
model = get_user_model()
fields = '__all__'
class Meta:
model = get_user_model()
fields = '__all__'
bcustomer/views.py
class CustomerViewSet(viewsets.ModelViewSet):
customer_photo_thumb = BCustomer.get_thumbnail_url
permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
queryset = BCustomer.objects.all()
serializer_class = CustomerSerializer
def get_queryset(self):
queryset = BCustomer.objects.all()
return queryset
def get_serializer_class(self):
if self.action == 'list' or self.action == 'retrieve':
return CustomerListSerializer
return CustomerSerializer
bcustomer/urls.py
router.register(r'customer', views.CustomerViewSet, 'customers')
Data post parameter format
{
"first_name":"Myname",
"email":"testemail#gmail.com",
"customer_details": {
"city":"citys",
"phone":"04722874567",
}
}
You should remove model and fields from CustomListSerializer
class CustomerListSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
fields = '__all__'
customer_details = CustomerDetailsSerializer()
You need to set the source argument to point to the user model's customer. Most probably:
customer_details = CustomerDetailsSerializer(source='customer')
(or maybe source='bcustomer', not sure if it reversed the field name or class name).
On a side not, you should not need the ListSerializer at all. The list method will call the serializer with the many=True argument on CustomerSerializer which will create the ListSerializer appropriately.

Could not resolve URL for hyperlinked relationship using view name "place-info".

I search a lot for this problem but no any solution work for me. I am get Could not resolve URL for hyperlinked relationship using view name "place-info". You may have failed to include the related model in your API, or incorrectly configured the lookup_field attribute on this field. when I want to access this resource through my API in django.
I am getting error like this:
Could not resolve URL for hyperlinked relationship using view name "place-info". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
My model is ass follows:
class TourSite(models.Model):
"""Destination place"""
place_name = models.CharField(max_length=100, blank=False, default='')
place_address = models.CharField(max_length=200, blank=False, default='')
place_image = models.ImageField(upload_to="TourSite", blank=True)
def get_place_name(self):
return self.place_name
def get_place_address(self):
return self.place_address
def save(self, *args, **kwargs):
super(TourSite, self).save(*args, **kwargs)
def __str__(self):
return self.place_name
class Info(models.Model):
"""Stores information about the place."""
place_name = models.OneToOneField(
TourSite,
on_delete = models.CASCADE,
primary_key = True,
)
famous_for = models.CharField(max_length=200, blank=True, default='')
brief_info = models.TextField(blank=True, default='')
def get_famous_for(self):
return self.famous_for
def get_brief_info(self):
return self.brief_info
def get_place_name(self):
return self.place_name
def save(self, *args, **kwargs):
super(Info, self).save(*args, **kwargs)
def __str__(self):
return "%s is famous for %s"% (self.place_name, self.famous_for)
My Serailizer :
class InfoSerializer(serializers.ModelSerializer):
class Meta:
model = Info
fields = '__all__'
class TourSiteSerializer(serializers.HyperlinkedModelSerializer):
place_info = serializers.HyperlinkedIdentityField(view_name='place-info')
class Meta:
model = TourSite
fields = ('id', 'place_name','place_info', 'place_address', 'place_image')
My views:
#api_view(['GET'])
def api_root(request):
return Response({
'places': reverse('places-list', request=request),
})
class TourSiteList(DefaultsMixin, generics.ListAPIView):
queryset = TourSite.objects.all()
search_fields = ("place_name", "place_address", )
serializer_class = TourSiteSerializer
class TourSiteDetail(DefaultsMixin, generics.RetrieveUpdateDestroyAPIView):
queryset = TourSite.objects.all()
serializer_class = TourSiteSerializer
class Info(generics.ListAPIView):
queryset = Info.objects.all()
serializer_class = InfoSerializer
My urls
urlpatterns = [
url(r'^$', views.api_root),
url(r'^places/$', views.TourSiteList.as_view(), name="places-list"),
url(r'^places/(?P<pk>[0-9]+)/$', views.TourSiteDetail.as_view(), name="places-detail"),
url(r'^info/$', views.Info.as_view(), name='place-info'),
]
How can I resolve this issue?
Since I can't comment:
Your class Meta classes have the wrong indentation. They should be indented inside of their appropriate classes. If it is just a transcription error then it should be fixed for the question.
I had a similar situation involving HyperlinkedRelatedField on a OneToOneField that was a model's primary key.
Ended up needing to specify both the lookup_field and the lookup_url_kwarg arguments for HyperlinkedRelatedField.
Here is what this solution would look like applied to your serializer:
class TourSiteSerializer(serializers.HyperlinkedModelSerializer):
place_info = serializers.HyperlinkedIdentityField(
view_name='place-info',
lookup_field='place_info_id', # <-- note the `_id` suffix
lookup_url_kwarg='place_info',
)
class Meta:
model = TourSite
fields = ('id', 'place_name','place_info', 'place_address', 'place_image')

Django REST Framework (DRF): Set current user id as field value

I have model NewsModel and 2 serializers for him:
models.py
class NewsModel(models.Model):
title = models.CharField('Заголовок', max_length=255, help_text='Максимальная длина - 255 символов')
announce = models.TextField('Анонс', help_text='Краткий анонс новости')
author = models.ForeignKey(settings.AUTH_USER_MODEL, help_text='Автор новости', related_name='news')
full_text = models.TextField('Полный текст новости', help_text='Полный текст новости')
pub_date = models.DateTimeField('Дата публикации', auto_now_add=True, default=timezone.now, help_text='Дата публикации')
def comments_count(self):
return NewsComment.objects.filter(news=self.id).count()
def get_author_full_name(self):
return self.author.get_full_name()
class Meta:
db_table = 'news'
ordering = ('-pub_date',)
serilizers.py:
from rest_framework import serializers
from .models import NewsModel
from extuser.serializers import UserMiniSerializer
class NewsReadSerializer(serializers.ModelSerializer):
author = UserMiniSerializer()
class Meta:
model = NewsModel
fields = ('id', 'title', 'announce', 'comments_count', 'reviews', 'author_name')
def get_author_full_name(self, obj):
return obj.get_author_full_name()
class NewsWriteSerializer(serializers.ModelSerializer):
def validate_author(self, value):
value = self.request.user.id
return value
class Meta:
model = NewsModel
I select serializers in the api.py:
class NewsList(ListCreateAPIView):
queryset = NewsModel.objects.order_by('-pub_date')
def get_serializer_class(self, *args, **kwargs):
if self.request.method == 'GET':
return NewsReadSerializer
return NewsWriteSerializer
class Meta:
model = NewsModel
But when I will create NewsModel item, I see Error 400: Bad request [{'author': 'This field is required'}]
How I can set current user id as NewsItem.author value on creating new item?
I don't think you're using the serializer properly. A better practice to set request related data is to override perform_create in your view:
def perform_create(self, serializer):
serializer.save(author=self.request.user)
def perform_update(self, serializer):
serializer.save(author=self.request.user)
and then set your author serializer to read-only:
author = UserMiniSerializer(read_only=True)
this way you can simply use one single NewsSerializer for both read and write actions.
In new DRF you can write
owner = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
See http://www.django-rest-framework.org/api-guide/validators/#currentuserdefault
In DRF version prior 3 field must be declader with allow_null=True and default=None. DRF don't run checking fields without this params. Result code:
class NewsReadSerializer(serializers.ModelSerializer):
"""
Serializer only for reading.
author field serialized with other custom serializer
"""
author = UserMiniSerializer()
class Meta:
model = NewsModel
fields = ('id', 'title', 'announce', 'comments_count', 'reviews', 'author', 'pub_date',)
class NewsWriteSerializer(serializers.ModelSerializer):
"""
Serializer for creating and updating records.
author here is the instance of PrimaryKeyRelatedField, linked to all users
"""
author = serializers.PrimaryKeyRelatedField(
queryset=User.objects.all(), # Or User.objects.filter(active=True)
required=False,
allow_null=True,
default=None
)
# Get the current user from request context
def validate_author(self, value):
return self.context['request'].user
class Meta:
model = NewsModel
fields = ('title', 'announce', 'full_text', 'author',)
I would try something like this:
your models.py
class NewsModel(models.Model):
title = models.CharField(
'Заголовок', max_length=255,
help_text='Максимальная длина - 255 символов')
announce = models.TextField('Анонс',
help_text='Краткий анонс новости')
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
help_text='Автор новости', related_name='news')
full_text = models.TextField(
'Полный текст новости',
help_text='Полный текст новости')
pub_date = models.DateTimeField(
'Дата публикации', auto_now_add=True,
default=timezone.now, help_text='Дата публикации')
def comments_count(self):
return NewsComment.objects.filter(news=self.id).count()
def get_author_full_name(self):
return self.author.get_full_name()
class Meta:
db_table = 'news'
ordering = ('-pub_date',)
serializers.py
(ref.: http://www.django-rest-framework.org/api-guide/validators/#currentuserdefault)
from <yourapp>.models import NewsModel
from rest_framework import serializers
class NewsModelSerializer(serializers.ModelSerializer):
author = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = NewsModel
Also you should set settings.py to something like this:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',)
}