Trying to use a Model method in View Django - python

So I'm working on this project (an Inventory app). I have this model method I am trying to use in my View. I'm trying to call it in my view.
But I'm always getting an error: 'QuerySet' object has no attribute 'get_quantities_sold'
Here is my model:
generate_ref_no = str(uuid.uuid1())
class Transaction(models.Model):
business = models.ForeignKey(Business_Account, on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True)
amount = models.FloatField()
productSold = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
quanties_of_product_sold = models.IntegerField()
transaction_date = models.DateTimeField(auto_now_add=True)
payment_method = models.CharField(choices=PAYMENT_METHOD, max_length=50)
reference_num = models.CharField(max_length=50, editable=False, default=generate_ref_no)
def __str__(self):
return f'{self.customer} '
def get_quantities_sold(self,quantities_sold):
return print(quantities_sold)
My view:
class TransactionView(generics.GenericAPIView):
def post(self,request, business=None):
serializer = TransactionSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
getTransaction = Transaction.objects.filter(reference_num=serializer.data['reference_num'])
getTransaction_serializer = TransactionSerializer(getTransaction, many=True)
getTransaction.get_quantities_sold(serializer.data['quanties_of_product_sold '])
return Response(data=serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(data=serializer.errors, status=status.HTTP_404_NOT_FOUND)
I'm trying to call the 'get_quantities_sold' method from the Transaction model in my transaction view but I'm an error: QuerySet' object has no attribute 'get_quantities_sold'

getTransaction is in your method is a QuerySet and thus a collection of items, not a single item, hence getTransaction.get_quantities_sold makes no sense. You can retrieve a single Transaction object by using .get(…) [Django-doc] over .filter(…) [Django-doc]:
getTransaction = Transaction.objects.get(
reference_num=serializer.data['reference_num']
)
It might also be worth to guarantee uniqueness for the reference_num with:
reference_num = models.CharField(
max_length=50,
editable=False,
default=generate_ref_no,
unique=True
)

Related

Django filtering ForeignKey

This is view:
def post(self, request):
author_request = request.data.get("author")
queryset = Book.objects.filter(author=author_request)
serializer = BookSerializer(queryset, None)
return Response(serializer.data, HTTP_200_OK)
This is model:
class Author(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
full_name = models.CharField(max_length=255, null=True, blank=True)
about = models.TextField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.full_name
class Meta:
verbose_name = 'Author'
verbose_name_plural = 'Authors'
So, when i try to filter the book by author i get the error. The error tells me that the POST data that i entered which is "Aleksa Petrovic" a name of a author that exists in the database is not an UUID. So when i filter it, it filters by UUID and i want it to filter by "full_name"
You can .filter(…) [Django-doc] with:
Book.objects.filter(author__full_name=name_of_author)
One can use double underscores (__) to look "through" relations.
The view thus looks like:
def post(self, request):
author_request = request.data.get('author')
queryset = Book.objects.filter(author__full_name=author_request)
serializer = BookSerializer(queryset, None)
return Response(serializer.data, HTTP_200_OK)
Typically searches with a filter are not handled by a POST request, but by a GET request, since a GET request is supposed to retrieve data from the web server.

Is there a way to add custom fields in Django Rest Framework

I am creating a rest API for my Django blog project and I have models Post and PostLike models as you below:
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
text = models.TextField()
approved = models.BooleanField(default=False)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField( default=timezone.now, blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.text[0:100]
class PostLike(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
created_date = models.DateTimeField(default=timezone.now)
And I have a Post serialiser like
class PostSerializers(ModelSerializer):
likes_count = serializers.IntegerField(read_only=True)
class Meta:
model= Post
fields = ['id','text','author', 'approved','created_date', 'likes_count' ]
I wish the likes_count to be count for the PostLike objects with the post of the queried post. What is the right way to implement it?
The SerializerMethodField allows you to return a value based on the return value of a class method.
EDIT:
Note that the method accepts the object as a parameter. Therefore to achieve what you want, you can return:
def like_count(self, obj):
return obj.postlike_set.count()

Add new item in many to many field via api in Django

I'm calling an API to update the my liked_products many to many model in Django but, when calling the prod ID to add the item to the list, I get the error:
AttributeError at /api/customer/like_product/
'ReturnDict' object has no attribute 'liked_products'
Here is my API:
#csrf_exempt
def updated_liked_products(request):
customer = get_user(request)
if not customer:
return JsonResponse({'invalid token'})
customer_details = CustomerDetailSerializer(CustomerDetails.objects.get(
customer=customer)).data
customer_details.liked_products.add(request.data['prodId'])
customer_details.save()
return JsonResponse({"success": 'updated'})
Customer Details Model:
age = models.IntegerField(default="21", blank=True)
address = models.CharField(
default='', max_length=254, null=True, blank=True)
nick_name = models.CharField(
default='', max_length=254, blank=True)
average_order = models.FloatField(default="0.0", blank=True)
completed_orders = models.IntegerField(default="0", blank=True)
customer = models.ForeignKey(
Customer, on_delete=models.CASCADE)
customer_type = MultiSelectField(
choices=CUSTYPE, default=CUSTYPE, max_length=100)
current_selfie = models.ImageField(
upload_to='sefies/', blank=True, default='')
email_confirmed = models.BooleanField(default=False)
last_signin = models.DateTimeField(default=timezone.now)
liked_products = models.ManyToManyField('Product')
needs_help_with = MultiSelectField(
choices=CATEGORIES, max_length=1000, default='')
phone = models.CharField(
I am using Postman to update the data like this so I can see the liked product field but, cannot access it.:
You're having this error because you're trying to access liked_products attribute on a serialized data that is an instance of ReturnDict and not CustomerDetails.
It seems like there is not much point in the serializer usage in this API so you should be able to achieve what you want with just this:
#csrf_exempt
def updated_liked_products(request):
customer = get_user(request)
if not customer:
return JsonResponse({'invalid token'})
customer_details = CustomerDetails.objects.get(customer=customer)
customer_details.liked_products.add(request.data['prodId'])
return JsonResponse({"success": 'updated'})

Django viewset error: 'QuerySet' object has no attribute 'title'

I'm trying to create a ViewSet for the Course model (to simply display all courses), but I'm getting the following error when trying to access it. I'm new to creating ViewSets and Django in general, what am I doing wrong?
Django 2.2
Error
AttributeError: Got AttributeError when attempting to get a value for field `title` on serializer `CourseSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `QuerySet` instance.
Original exception text was: 'QuerySet' object has no attribute 'title'.
CourseViewSet
class CourseViewSet(viewsets.ModelViewSet):
def list(self, request):
queryset = Course.objects.all()
serializer = CourseSerializer(queryset)
return Response(serializer.data)
CourseSerializer
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = (
'id',
'title',
'description',
'active',
'individual_result',
'course_duration',
'video',
'manager_id'
)
models/Course
class Course(models.Model):
title = models.CharField(max_length=255, blank=False, null=False)
description = models.CharField(max_length=255, blank=True, null=True)
active = models.BooleanField(default=True)
individual_result = models.BooleanField(default=False)
course_duration = models.CharField(max_length=255, blank=True, null=True)
video = models.CharField(max_length=255, blank=True, null=True)
manager_id = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.title
You should serialize with many=True, since a queryset is a collection of objects that can contain zero, one, or more elements:
serializer = CourseSerializer(queryset, many=True)
For more information, see the Dealing with multiple objects section [drf-doc].

Django many-to-many model DRF

I have the following model structure:
class Project(models.Model):
author = models.ManyToManyField(Account)
name = models.CharField(max_length=40, default='NewBook')
class Account(AbstractBaseUser):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
tagline = models.CharField(max_length=140, blank=True)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
My view looks like this:
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.order_by('-name')
serializer_class = ProjectSerializer
def perform_create(self, serializer):
instance = serializer.save(author=self.request.user)
return super(ProjectViewSet, self).perform_create(serializer)
After calling the view function, a classifier gets created in the database. But after that, I get the following error:
TypeError: 'Account' object is not iterable
The error gets thrown in this line:
instance = serializer.save(author=self.request.user)
Anyone how can help me with this?
There are two problems here:
Showing nested relationships for M2M field:
If the field is used to represent a to-many relationship, you should add the many=True flag to the serializer field.
So you need to add many=True to AccountSerializer:
author = AccountSerializer(read_only=True, required=False, many=True)
A writable nested serializer:
By default nested serializers are read-only. If you want to support write-operations to a nested serializer field you'll need to create create() and/or update() methods in order to explicitly specify how the child relationships should be saved.
So if you look at the example and the documentation it seems that you need to implement create or update method.
You need to set many=True when dealing with multiple relation - either a m2m or a reversed FK:
author = AccountSerializer(read_only=True, required=False, many=True)
Since your Author field is many to many, you will need to override the create method on your serializer.
def create(self, validated_data):
author = validated_data.pop(author, None)
project = Project.objects.save(validated_data)
if author:
project.author.add(author)
You will also probably need to set the update method on the serializer, the behavior here can be tricky so make sure you test and make sure the behavior is what you expect.
Ok, my previous answer, though could be an issue, isn't the root cause of the actual crash.
When calling the serializer, you set:
instance = serializer.save(author=self.request.user)
However, author is a ManyToManyField which means you should call the serializer as:
instance = serializer.save(author=[self.request.user])
NB: you still require the many=True on the serializer's author field.
Please check...
your model.py
class Account(AbstractBaseUser):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
tagline = models.CharField(max_length=140, blank=True)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
class Project(models.Model):
author = models.ManyToManyField(Account)
name = models.CharField(max_length=40, default='NewBook')
your serializer.py
class ProjectSerializer(serializers.ModelSerializer):
author = AccountSerializer(read_only=True, required=False)
class Meta:
model = Project
fields = ('id', 'author', 'name')
read_only_fields = ('id')
def get_validation_exclusions(self, *args, **kwargs):
exclusions = super(ProjectSerializer, self).get_validation_exclusions()
return exclusions + ['author']
and finally your view.py is
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.order_by('-name')
serializer_class = ProjectSerializer
def perform_create(self, serializer):
instance = serializer.save(author=self.request.user)
return super(ProjectViewSet, self).perform_create(serializer)

Categories