models.py:
class Project(models.Model):
project_code = models.CharField(max_length=250, null=False, blank=False)
description = models.CharField(max_length=1000, null=True, blank=True)
class ProjectManager(models.Model):
name = models.CharField(max_length=250, null=False, blank=False)
project_id = models.ForeignKey(
Project,
on_delete=models.CASCADE
)
views.py:
def ajax_search(request):
if request.method == 'GET':
category = request.GET['category']
if category == 'Project':
result = Project.objects.all()
data = serialize("json", result, cls=DatetimeJSONEncoder)
return HttpResponse(data, content_type="application/json")
else:
result = ProjectManager.objects.select_related('project_id').all()
data = serialize("json", result, cls=DatetimeJSONEncoder)
return HttpResponse(data, content_type="application/json")
return HttpResponse('')
return HttpResponse('')
I would like to return a json response with the content of ProjectManager + the content of the Project associated to that ProjectManager (ForeignKey).
According to what I have read in the Django documentation, to do a left join, the best thing to do would be to use select_related.
In fact, it works, but when I serialize ProjectManager, the Project values are not included in the JSON string. How could I put all into the JSON?
you can create serializers.py file and insert this code there
# import your models
from rest_framework import serializers
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = "__all__"
class ProjectManagerSerializer(serializers.ModelSerializer):
project_id = ProjectSerializer(many=True)
class Meta:
model = ProjectManager
fields = "__all__"
# views.py
qs = ProjectManager.objects.select_related('project_id').all()
resp = ProjectManagerSerializer(qs, many=True).data
Related
I have this type of Post model
class Post(models.model):
id = models.UUIDField(primary_key=True, default=uuid4)
user = models.ForeignKey(UserProfile, null=True, on_delete=models.CASCADE)
tags = models.ManyToManyField("Tags", blank=True, related_name="posts")
title = models.CharField(max_length=200)
body = RichTextField(blank=True, null=True)
post_views = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=("created_at"))
in the serializer, I want to nest title, body, created_at under another key named article
serializers.py
class ArticleSerializer(serializers.ModelSerializer):
title = serializers.CharField()
content = serializers.CharField(source="body")
created_at = serializers.CharField()
class Meta:
model = Post
fields = ("title", "body", "created_at")
class PostSerializer(serializers.ModelSerializer):
user = serializers.SlugRelatedField(slug_field="email", read_only=True)
article = ArticleSerializer(required=True)
tags = TagSerializer(many=True, required=False)
post_views = serializers.IntegerField(read_only=True)
def to_representation(self, instance):
data = super().to_representation(instance)
cat = data.pop("category")
title = data.pop("title")
content = data.pop("body")
created_at = data.pop("created_at")
data["categories"] = cat
data["article"] = {"title": title, "content": content, "created_at": created_at}
return data
class Meta:
model = Post
fields = "__all__"
views.py
class ArticleView(APIView):
def get_object(self, pk: int):
try:
if pk:
return Post.objects.filter(pk=pk, draft=False)
return Post.objects.filter(draft=False)
except Post.DoesNotExist:
raise Http404
def get(self, request: Request, pk=None):
post = self.get_object(pk)
serializer = PostSerializer(post, many=True)
return Response(serializer.data)
The error that I'm getting
AttributeError: Got AttributeError when attempting to get a value for field `article` on
serializer `PostSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the
`Post` instance.
Original exception text was: 'Post' object has no attribute 'article'
fields = ["article","modelfield", etc etc]
in post serializer instead of all, call the fields
I have these Models Below
class Campaign(models.Model):
title = models.CharField(max_length=120)
img = models.ImageField(upload_to='products/')
def __str__(self):
return self.title
class Product(models.Model):
title = models.CharField(max_length=100)
data = models.DateField(auto_now_add=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
image = models.ImageField(upload_to="products/")
campaign = models.ForeignKey(Campaign, on_delete=models.DO_NOTHING, null=True, blank=True, related_name="products")
offer = models.ForeignKey(Offer, on_delete=models.DO_NOTHING, null=True, blank=True)
market_price = models.PositiveIntegerField()
selling_price = models.PositiveIntegerField()
description = models.TextField()
def __str__(self):
return self.title
I want to show campaign_wise products. But i cant find any solution for this. Though i tried reading the docs of DRF
Here is my Serializer
class CampaignProductsSerializer(serializers.ModelSerializer):
products = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
class Meta:
model = Campaign
fields = ['title', 'products']
Whenever i try to run this i get 'Product' object has no attribute 'products'
Here is my URL
path('campaign_products/<int:id>/', CampaignProducts.as_view()),
Here is my View:
class CampaignProducts(APIView):
def get(self, request, id):
campaigns = Campaign.objects.all()
query = Product.objects.filter(campaign_id = id)
serializer = CampaignProductsSerializer(query, many=True)
return Response(serializer.data)
In that case you should make two serializers, one for the Product and one for the Campaign, so:
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['title'] # etc.
class CampaignProductsSerializer(serializers.ModelSerializer):
products = ProductSerializer(read_only=True, many=True)
class Meta:
model = Campaign
fields = ['title', 'products']
In the view, you then serializer a Campaign:
from django.shortcuts import get_object_or_404
# returns the title of the campaign, and the products
class CampaignProducts(APIView):
def get(self, request, id):
campaign = get_object_or_404(Campaign, id=id)
serializer = CampaignProductsSerializer(campaign)
return Response(serializer.data)
In case you do not want to include the data of the campaign, we can work with the ProductSerializer:
# returns only the related products
class CampaignProducts(APIView):
def get(self, request, id):
products = Product.objects.filter(campaign_id=id)
serializer = ProductSerializer(products, many=True)
return Response({'data': serializer.data})
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
I'm facing below issue in ModelSerializer file upload.
Issue 1) I'm trying to upload files using ModelSerializer. I have two models BlogFilesSerializer and BlogSerializer. when trying to upload a file it shows too many values to unpack error and I know its meaning why is this occurring but don't know how to handle these exceptions.
serializers.py
class BlogFilesSerializer(ModelSerializer):
created_at = serializers.SerializerMethodField()
updated_at = serializers.SerializerMethodField()
class Meta:
model = BlogFilesModel
fields = ('blog_files_id', 'blog', 'path',
'created_at', 'updated_at')
class BlogSerializer(ModelSerializer):
blog_files = serializers.SerializerMethodField()
uploaded_files = serializers.FileField(required=True, source='*')
blog_created_at = serializers.SerializerMethodField()
def get_blog_files(self, obj):
info = BlogFilesSerializer(BlogFilesModel.objects.filter(
blog=obj).order_by('-pk'), many=True)
if info.data:
for i in info.data:
user_detail = User.objects.get(pk=obj.user.id)
i.__setitem__('user_detail', UserSerializer(user_detail).data)
if i.get('user_detail'):
try:
del i['user_detail']['password']
except expression as identifier:
pass
return info.data
def get_blog_created_at(self, obj):
formatted_date = obj.created_at.strftime("%d-%m-%Y")
return formatted_date
class Meta:
model = BlogModel
fields = ('blog_id', 'user', 'title', 'content',
'status',
'blog_files', 'blog_created_at',
'uploaded_files'
)
def create(self, validated_data):
instance = BlogModel.objects.create(**validated_data)
return instance
views.py
class BlogViewSet(viewsets.ModelViewSet):
queryset = BlogModel.objects.all()
lookup_field = 'blog_id'
serializer_class = BlogSerializer
parser_classes = (MultiPartParser, FormParser,FileUploadParser)
models.py
class BlogModel(models.Model):
BLOG_STATUS = (
('PUBLISH', 'Publish'),
('DRAFT', 'Draft'),
)
blog_id = models.AutoField(primary_key=True)
user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='blogs')
title = models.CharField(max_length=255)
content = models.TextField(blank=True, null=True)
status = models.CharField(max_length=7, choices=BLOG_STATUS)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta():
db_table = 'blogs'
verbose_name = 'Blog'
verbose_name_plural = 'Blogs'
def __str__(self):
return self.title
#property
def files(self):
return 'something'
def blog_directory_path(instance, filename):
return 'uploads/blogs/{}'.format(filename+str(datetime.now()))
class BlogFilesModel(models.Model):
blog_files_id = models.AutoField(primary_key=True)
blog = models.ForeignKey(
BlogModel, on_delete=models.CASCADE, related_name='blogs',blank=True)
path = models.FileField(blank=False, null=False,upload_to=blog_directory_path)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta():
db_table = 'blog_files'
verbose_name = 'Blog'
verbose_name_plural = 'Blogs'
def __str__(self):
return str(self.path)
Issue 2) i'm also unable to select multiple files for upload in BlogSerializer and in field uploaded_files = serializers.FileField(required=True, source='*') and their is no detailed explanation is DRF documentation. How can i add multple attribute to file field.
EDIT 1: I tried and got till here in def to_internal_value(self, data): the field.source_attrs = [] their is no key so i'm getting this error.
in my ModelSerializer i tried this uploaded_files = serializers.FileField(required=True, source='files') added files as property to BlogModel now i'm getting 'Error = files' is an invalid keyword argument for this function can someone guide me here.
Hope is have explained my problem well.
Thank you.
Question about PrimaryKeyRelatedField serialization in Django DRF version 3.4.7.
models
class UserModel(AbstractEmailUser):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.email)
class Conversation(models.Model):
admin = models.ForeignKey('UserModel', db_index=True, related_name='admin_user')
patient = models.ForeignKey('UserModel', db_index=True)
subject = models.CharField(max_length=255, db_index=True)
user_reply = models.BooleanField(default=False)
admin_seen = models.BooleanField(default=False)
expire = models.DateTimeField()
conversation_type = models.ForeignKey('ConversationType', db_index=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.admin)
class ConversationMessages(models.Model):
text = models.TextField(db_index=True)
conversation = models.ForeignKey('Conversation', db_index=True, related_name='msg_conv')
user = models.ForeignKey('UserModel', db_index=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.user)
class ConversationFiles(models.Model):
message = models.ForeignKey('ConversationMessages', db_index=True, related_name='message')
file = models.FileField(upload_to='conversations', db_index=True)
def __str__(self):
return str(self.user)
Every model has related field for Rest Framework.
Logic is create conversation, then take ID from conversation and save message model.
serialize's
class MessagesSerializer(serializers.ModelSerializer):
text = serializers.CharField(required=False)
conversation = serializers.PrimaryKeyRelatedField(queryset=Conversation.objects.all(), required=False)
user = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all(), required=False)
class Meta:
model = ConversationMessages
class ConversationSerializer(serializers.ModelSerializer):
admin = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all(), required=False)
msg_conv = MessagesSerializer()
class Meta:
model = Conversation
def create(self, validated_data):
msg_conv = validated_data.pop('msg_conv', None)
admin_user = Conversation.objects.create(**validated_data)
ConversationMessages.objects.create(conversation_id=Conversation.objects.get(id=admin_user.id).id, **msg_conv)
return admin_user
Serializer is problem on POST method. Everything works great POST object create data in database, but problem is when serializer save object i get this message: 'RelatedManager' object has no attribute 'conversation'.
View
class ConversationView(APIView):
authentication_classes = (JSONWebTokenAuthentication,)
#parser_classes((FormParser, MultiPartParser, FileUploadParser))
def post(self, request):
admin = request.user.id
data = request.data
my_time = datetime.datetime.strptime('07/05/15', '%m/%d/%y')
my_time = my_time.replace(hour=23, minute=59)
data['admin'] = admin
data['expire'] = my_time
data['msg_conv']['user'] = admin
serializer = ConversationSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(data={'success': True, 'user': serializer.data}, status=status.HTTP_200_OK)
else:
return Response(data={'success': False, 'msg': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
POST json
{
"subject":"aloha",
"conversation_type":1,
"patient":3,
"msg_conv":{
"text":"ovo je neki teks"
}
}
Can't figure out how to return data from serializer to view.
Django version : 1.10.2
Python: 3.4.3
The issue is there:
class ConversationSerializer(serializers.ModelSerializer):
msg_conv = MessagesSerializer()
By doing this, you are saying that Conversation has a FK to Message. Therefore DRF tries to do the mapping and fails because it's the oposit.
You just need to add the many=True argument to let DRF knows this is a reversed FK.