I setup everything for implementing elastic search in Django rest framework. I launched the elastic server using bat file and it runs successfully in the background. Then when I call the api , it throws me above error.
class Category(models.Model):
name = models.CharField(max_length=255)
name = models.CharField(max_length=255)
description = models.TextField(blank=True)
status = models.BooleanField(default=True)
My search.py
class PaginatedElasticSearchAPIView(APIView, LimitOffsetPagination):
serializer_class = None
document_class = None
#abc.abstractmethod
def generate_q_expression(self, query):
"""This method should be overridden
and return a Q() expression."""
def get(self, request, query):
try:
q = self.generate_q_expression(query)
search = self.document_class.search().query(q)
response = search.execute()
print(f'Found {response.hits.total.value} hit(s) for query: "{query}"')
results = self.paginate_queryset(response, request, view=self)
serializer = self.serializer_class(results, many=True)
return self.get_paginated_response(serializer.data)
except Exception as e:
return HttpResponse(e, status=500)
class CategorySearchView(PaginatedElasticSearchAPIView):
serializer_class = CategorySerializers
document_class = CategoryDocument
def generate_q_expression(self, query):
return Q(
"multi_match",
query=query,
fields=[
"name",
],
fuzziness="auto",
)
My serializers. py
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Subject
fields = ["id", "name","description","status"]
My documents.py:
#registry.register_document
class CategoryDocument(Document):
# name = TextField()
class Index:
name = "category"
settings = {"number_of_shards": 1, "number_of_replicas": 0}
class Django:
model = Category
fields = [
"name","description"
]
My urls.py :
http://localhost:8000/elastic/search/Math/
I tried to call this api family but it shows the above error. Is this because I have some models which has a foreign key fields associated with the Category model?
Related
I have this URL and I send the currently logged in user's id (viewer (33)) and the id of the user being looked at (user (1)) in the URL:
path("users/<int:viewer>/<int:user>/profile/", OtherProfile.as_view()),
Here is the view handling that URL:
class OtherProfile(generics.RetrieveAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = ProfileSerializer
name = "other-profile"
lookup_field = "user"
def get_queryset(self):
breakpoint()
viewer = self.kwargs["viewer"]
user = self.kwargs["user"]
return Profile.objects.all().filter(user_id=user)
There is a breakpoint here and the result of
print(self.kwargs["viewer"]) gives 33 which is correct
print(self.kwargs["user"]) gives 1 which is also correct
Here is the profile serializer as specified in the serializer_class:
class ProfileSerializer(serializers.ModelSerializer):
location = serializers.SerializerMethodField()
user = UserSerializer()
followers = serializers.SerializerMethodField()
class Meta:
model = Profile
fields = [
"id",
"background",
"photo",
"first_name",
"middle_name",
"last_name",
"birthdate",
"gender",
"bio",
"occupation",
"is_verified",
"verification",
"website",
"location",
"user",
"followers",
"created_at",
"updated_at",
]
def get_location(self, obj):
location_obj = Location.objects.filter(profile=obj.id)
if location_obj:
location_obj = Location.objects.get(profile=obj.id)
location = LocationSerializer(location_obj)
return location.data
def get_followers(self, obj):
breakpoint()
followers = Follow.objects.filter(followee=obj.user.id)
return followers.count()
I put a breakpoint on the get_followers method so I can look at the data.
print(self.context["view"].kwargs) - prints ["viewer", "user"]
My question:
Why does print(self.context["view"].kwargs["user"]) print 33 when on the view the kwargs user should be 1?
Why does it give me a key error when I try and print(self.context["view"].kwargs["viewer"])?
I have two tables in my database to insert a product record. I am storing the product info in the Product table and the rest of the info like Pirce, Quantity etc storing to another table which is ProductStock.
I am planning to send the data to a server something like this.
{
"name":'product name',
"brand":"socialcodia"
"product_stock":{
"price":"100",
"quantity":"50"
}
}
I am easily able to validate the product info from ProductSerializer. But I don't have any perfect idea to validate the ProductStockSerializer data.
ProductSerializer
from rest_framework import serializers
from .models import Product
from .models import Medical
class ProductSerializer(serializers.ModelSerializer):
medical = serializers.CharField(read_only=True)
id = serializers.CharField(read_only=True)
is_visible = serializers.CharField(read_only=True,default=True)
class Meta:
model = Product
fields = ['id','medical','category','item','brand','is_visible']
def validate(self, attrs):
request = self.context.get('request')
attrs['medical'] = Medical.objects.get(pk=request.info.get('medical'))
return attrs
Here I want to validate the product_stock info as well. cuz it's coming with a single request. So is there any way that i can import the ProductStockSerializer into ProductSerializer and pass the data to that serializer. then validate it.
ProductStockSerializer
from rest_framework import serializers
from .models import ProductStock
from medical.models import Medical
class ProductStockSerializer(serializers.ModelSerializer):
medical = serializers.CharField(read_only=True)
class Meta:
model = ProductStock
fields = ['medical','distributer','product','variant','batch','purchase_price','price','quantity','location','low_stock','expire_date']
def validate(self, attrs):
attrs['medical'] = Medical.objects.get(self.context.get('request').info.get('medical'))
batch = attrs.get('batch')
purchase_price = attrs.get('purchase_price')
price = attrs.get('price'),
if len(batch) < 3 or len(batch) > 30:
raise serializers.ValidationError("Invalid Batch Number")
if type(purchase_price) != int or type(purchase_price) != float:
raise serializers.ValidationError("Invalid Purchase Price")
if type(price) != int or type(price) != float:
raise serializers.ValidationError("Invalid Price")
return attrs;
ProductViewSet
class ProductViewSet(ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def get_queryset(self):
if self.request.user.is_superuser:
return Product.objects.all()
return Product.objects.filter(medical=self.request.info['medical'])
I literally don't have any idea how to do this.
Thanks
How about adding your ProductStockSerializer data as a field to your ProductSerializer
class ProductSerializer(serializers.ModelSerializer):
...
product_stock = ProductStockSerializer()
class Meta:
fields = [ ... , product_stock ]
You should be able to use product_stock in your validation. If you plan to create ProductStock objects using this nested serializer please make sure to read on writable nested serializers.
The #coderiot answer is absolutely right.
Here's How I Solved, But it has a lot more code than the above answer.
class ProductSerializer(serializers.ModelSerializer):
medical = serializers.CharField(read_only=True)
id = serializers.CharField(read_only=True)
is_visible = serializers.CharField(read_only=True,default=True)
stock = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Product
fields = ['stock','id','medical','category','item','brand','is_visible']
def get_stock(self,instance):
return ProductStockSerializer(instance=instance.stock,context=self.context).data
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.fields['stock'] = ProductStockSerializer(context=self.context)
def validate(self, attrs):
request = self.context.get('request')
attrs['medical'] = Medical.objects.get(pk=request.info.get('medical'))
return attrs
I am using serializers.Serializer instead of ModelSerializer which doesn't require Meta class but it keep saying object has no attribute Meta. Iam not sure what is the issue but when I run the localserver, the main page gives error saying api fetch error and in the terminal it says AttributeError: 'Serializer' object has no attribute 'Meta'.
My view:
class ClassView(viewsets.ModelViewSet):
queryset = Class.objects.all().order_by('-created_at')
serializer_class = ClassSerializer
serializer_action_classes = {
'get_all_students_of_a_class': ClassDetailSerializer,
}
# .annotate(total_students=Count('students_in_class'))
def get_serializer_class(self):
"""
returns a serializer class based on the action
that has been defined.
"""
try:
return self.serializer_action_classes[self.action]
except (KeyError, AttributeError):
return super(ClassView, self).get_serializer_class()
def get_all_students_of_a_class(self,request,pk=None):
"""
returns a class details with all the students signed up for the
class along with the subject.
"""
id = pk
if self.is_teacher(id):
online_classes = get_object_or_404(Class, id=id)
students = Student.objects.filter(online_class__id=id)
subject_details = Subject.objects.get(online_class__id=id)
total_students_in_class = online_classes.total_students_in_class
created_at = online_classes.created_at
updated_at = online_classes.updated_at
data = {
"teacher": self.get_teacher_instance(),
'total_students_in_class': total_students_in_class,
"students_in_class": students,
"subject": subject_details,
'created_at': created_at,
'last_updated_at': updated_at,
}
serializer_class = self.get_serializer_class()
serializer = serializer_class(data)
return Response(serializer.data, status=status.HTTP_200_OK)
My serializer:
class ClassDetailSerializer(serializers.Serializer):
teacher = serializers.StringRelatedField()
subject = SubjectLevelSerializer()
total_students_in_class = serializers.ReadOnlyField()
students_in_class = serializers.StringRelatedField(many=True)
created_at = serializers.DateTimeField(read_only=True)
last_updated_at = serializers.DateTimeField(read_only=True)
My url:
path("class/<int:pk>/",teacher.ClassView.as_view({"get": "get_all_students_of_a_class","delete":"destroy"}),
),
However it works and I can perform action if I go to localhost/admin and other api calls from localhost.
Add a Meta class with model = YourModel
class ExampleDetailSerializer(serializers.Serializer):
employee = serializers.StringRelatedField()
person = PersonSerializer()
class Meta:
model = Example # model name
fields = ('__all__')
Try to use "ViewSet" instead of "ModelViewSet". And while using ViewSet make sure to define list, create, etc. function by your own.
I'm working a project, and use Django REST framework and mongo engine, and I'm confused a question two days, and the detail see below:
class Jvv(EmbeddedDocument):
unit = fields.StringField()
unitValue = fields.IntField()
class Meta:
db_table = 'imagerecognition'
class ImageRecognition(Document):
imageUrl = fields.StringField(default='', max_length=100)
createTime = fields.DateTimeField(default=datetime.now())
ddPercent = fields.FloatField(required=False, default='')
jvv = fields.ListField(fields.EmbeddedDocumentField(Jvv))
def __str__(self):
return self.imageUrl
class Meta:
db_table = 'imagerecognition'
then the serializer.p document is :
class JvvSerializer(mongoserializers.EmbeddedDocumentSerializer):
class Meta:
model = Jvv
fields = '__all__'
class ImageUrlSerializer(mongoserializers.DocumentSerializer):
jvv = JvvSerializer(many=True)
class Meta:
model = ImageRecognition
fields = ('imageUrl', 'createTime', 'ddPercent', 'jvv')
and the views.py content is below:
class ImageUrlSave(views.APIView):
def get(self, request, *args, **kwargs):
imgs = ImageRecognition.objects(imageUrl='白菜')
serializer = ImageUrlSerializer(imgs, many=True)
ImageRecognition(imageUrl='土豆', ddPercent=8.22, jvv={'unit':'m', 'unitValue':12}).save()
data = serializer.data
return Response({
'msg': 'SUCCESS',
'code_status': 1000,
'result': data
})
the question is the mongodatabases have been completed, I want to take some data from it, but when I runserver, it shows
raise ValueError("The source SON object needs to be of type 'dict'")
ValueError: The source SON object needs to be of type 'dict', how can I handle this problem, and I am Looking forward to get answer. Thank you.
I have 2 databases. One containing the AUTH that's also extended in the following models.py -
from django.contrib.auth.models import User
class FileIndex(models.Model):
filename = models.CharField(max_length=256)
filetype = models.CharField(max_length=16)
vendorid = models.IntegerField()
vendorname = models.CharField(max_length=256)
tablename = models.CharField(max_length=256)
class Meta:
db_table = 'file_index'
verbose_name = 'File/Vendor Index'
verbose_name_plural = 'File/Vendor Indicies'
def __str__(self):
return self.filename
class UserFile(models.Model):
userid = models.ForeignKey(User)
fileid = models.ForeignKey(FileIndex)
grant_date = models.DateTimeField()
revoke_date = models.DateTimeField(blank=True)
class Meta:
db_table = 'auth_files'
verbose_name = 'User File Matrix'
verbose_name_plural = 'User File Matricies'
the 'tablename' field in FileIndex references a Table Name in another database referenced in a separate App. My current test view I'm using is follows in my views.py
class File_List(generics.ListAPIView):
model = cdx_composites_csv
serializer_class = cdx_compositesSerializer
def get_queryset(self):
"""
This view should return a list of all the purchases for
the user as determined by the username portion of the URL.
"""
filename = self.request.GET.get('filename')
model = get_model('markit', filename)
filedate = self.request.GET.get('filedate')
queryset = model.objects.using('markitdb').filter(Date__contains=filedate)
return queryset
If I'm not logged in it works fine and gives "not authorized" but regardless of if I've set view permissions on the table or not my user can still execute the view.
Model is listed before the function or else it will complain about the model not being there. I want to figure that out later. First I'm trying to understand why my view is still executing even if the user does not have group permission to view the Model.
I've attacked this by doing the following in my view -
class ExampleView(APIView):
model = cdx_composites_csv
serializer_class = cdx_compositesSerializer
def get(self, request, format=None):
if UserFile.objects.filter(fileid_id=1, userid_id=2).exists():
content = {
'status': 'Request Successful.'
}
return Response(content)
else:
content = {
'status': 'Request Failed.'
}
return Response(content)
Essentially after authentication it's doing a query against the UserFile to validate the User and the file exists and if it does then I can write it to do the queryset or not.