fengsp / django-grpc-framework

gRPC for Django.
https://djangogrpcframework.readthedocs.io/
Apache License 2.0
390 stars 53 forks source link

details = "Exception calling application: 'BlogProtoSerializer' object has no attribute 'proto_class'" #45

Open JonesThePotato opened 1 year ago

JonesThePotato commented 1 year ago

I checked everything and followed every step of the document. Got as much as help from AIs too, no progress. I'll share any code if necessary.

AMontagu commented 1 year ago

You forgot to add one line in your serializers. See: https://djangogrpcframework.readthedocs.io/en/latest/quickstart.html#writing-serializers

For information this repo is no more maintained. If you are at the start of your projet considere looking at: https://github.com/socotecio/django-socio-grpc/

JonesThePotato commented 1 year ago
from django_grpc_framework.proto_serializers import ModelProtoSerializer
from django_grpc_framework import proto_serializers
from .models import Blog, Tag, Category, ImageModel
import blog_pb2 as blog_pb2 

class ImageModelProtoSerializer(proto_serializers.ModelProtoSerializer):
    class Meta:
        model = ImageModel
        proto_class = blog_pb2.ImageModel
        fields = ('id', 'content_photo',)
        read_only_fields = ('id',)

class TagProtoSerializer(proto_serializers.ModelProtoSerializer):
    class Meta:
        model = Tag
        proto_class = blog_pb2.Tag
        fields = ('id', 'title', 'description',)
        read_only_fields = ('id',)

class CategoryProtoSerializer(proto_serializers.ModelProtoSerializer):
    class Meta:
        model = Category
        proto_class = blog_pb2.Category
        fields = ('id', 'title', 'description', 'photo',)
        read_only_fields = ('id',)

class BlogProtoSerializer(proto_serializers.ModelProtoSerializer):
    image_models = ImageModelProtoSerializer(many=True, required=False)

    class Meta:
        model = Blog
        proto_class = blog_pb2.Blog
        fields = ('id', 'author', 'created_at', 'updated_at', 'tag', 'category', 'title', 'main_photo', 'content_photo', 'like', 'comment', 'image_models',)
        read_only_fields = ('id', 'created_at', 'updated_at', 'like', 'comment',)
        write_only_fields = ('main_photo',)

    def to_proto(self, instance):
        proto = self.proto_class(
            id=instance.id,
            author=instance.author,
            created_at=instance.created_at,
            updated_at=instance.updated_at,
            tag=instance.tag,
            category=instance.category,
            title=instance.title,
            main_photo=instance.main_photo,
            content_photo=instance.content_photo,
            like=instance.like,
            comment=instance.comment,
            image_models=[self.image_models.to_proto(image) for image in instance.image_models],
        )
        return proto

I checked. Everything is how it's supposed to be.

AMontagu commented 1 year ago
def to_proto(self, instance):
        proto = self.proto_class(
            id=instance.id,
            author=instance.author,
            created_at=instance.created_at,
            updated_at=instance.updated_at,
            tag=instance.tag,
            category=instance.category,
            title=instance.title,
            main_photo=instance.main_photo,
            content_photo=instance.content_photo,
            like=instance.like,
            comment=instance.comment,
            image_models=[self.image_models.to_proto(image) for image in instance.image_models],
        )
        return proto

You call self.proto_class but it should be self.Meta.proto_class.

JonesThePotato commented 1 year ago

Thank you for your insight. Now I am running into another error. No idea where to look at. PS : Thank you so much for your responds! I have been stuck for few weeks. Error : PS C:\Users\JonseThePotato\Documents\Work\microservices> py coresystem.py

  1. List All Blogs
  2. View a Blog
  3. Create a Blog
  4. Update a Blog
  5. Delete a Blog
  6. Quit Enter your choice (1-6): 1 Traceback (most recent call last): File "C:\Users\JonseThePotato\Documents\Work\microservices\coresystem.py", line 99, in run() File "C:\Users\JonseThePotato\Documents\Work\microservices\coresystem.py", line 36, in run list_blogs(stub) File "C:\Users\JonseThePotato\Documents\Work\microservices\coresystem.py", line 52, in list_blogs response = stub.List(list_request) ^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python311\Lib\site-packages\grpc_channel.py", line 1030, in call return _end_unary_response_blocking(state, call, False, None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python311\Lib\site-packages\grpc_channel.py", line 910, in _end_unary_response_blocking raise _InactiveRpcError(state) # pytype: disable=not-instantiable ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with: status = StatusCode.UNKNOWN details = "Exception calling application: Message must be initialized with a dict: blog.Blog" debug_error_string = "UNKNOWN:Error received from peer {created_time:"2023-06-19T16:59:52.950338936+00:00", grpc_status:2, grpc_message:"Exception calling application: Message must be initialized with a dict: blog.Blog"}"

blog.proto :``` syntax = "proto3";

package blog;

import "google/protobuf/timestamp.proto";

message ImageModel { string content_photo = 1; }

message Tag { int32 id = 1; string title = 2; string description = 3; }

message Category { int32 id = 1; string title = 2; string description = 3; string photo = 4; }

message Blog { int32 id = 1; string author = 2; google.protobuf.Timestamp created_at = 3; google.protobuf.Timestamp updated_at = 4; Tag tag = 5; Category category = 6; string title = 7; string main_photo = 8; repeated ImageModel content_photo = 9; int32 like = 10; string comment = 11; int32 category_id = 12; int32 tag_id = 13; }

// Request and Response messages for your gRPC service methods message BlogListRequest { // ... }

message BlogListResponse { repeated Blog blogs = 1; }

// ... Add other request and response messages for Retrieve, Create, Update, and Delete methods

// Retrieve message BlogRetrieveRequest { int32 id = 1; }

message BlogRetrieveResponse { Blog blog = 1; }

// Create message BlogCreateRequest { Blog blog = 1; }

message BlogCreateResponse { Blog blog = 1; }

// Update message BlogUpdateRequest { int32 id = 1; Blog blog = 2; }

message BlogUpdateResponse { Blog blog = 1; }

// Delete message BlogDeleteRequest { int32 id = 1; }

message BlogDeleteResponse { bool success = 1; }

service BlogService { rpc List (BlogListRequest) returns (BlogListResponse); rpc Retrieve (BlogRetrieveRequest) returns (BlogRetrieveResponse); rpc Create (BlogCreateRequest) returns (BlogCreateResponse); rpc Update (BlogUpdateRequest) returns (BlogUpdateResponse); rpc Delete (BlogDeleteRequest) returns (BlogDeleteResponse); }


services.py : ```
import grpc
import blog_pb2 as blog_pb2
import blog_pb2_grpc as blog_pb2_grpc
from django.shortcuts import get_object_or_404
from django_grpc_framework.services import Service
from blog.serializers import BlogProtoSerializer 
from .models import Blog

class BlogService(blog_pb2_grpc.BlogServiceServicer):
    def List(self, request, context):
        blogs = Blog.objects.all()
        serializer = BlogProtoSerializer()  # Instantiate the serializer
        blog_protos = [serializer.to_proto(blog) for blog in blogs]
        return blog_pb2.BlogListResponse(blogs=blog_protos)

    def Retrieve(self, request, context):
        blog = get_object_or_404(Blog, id=request.id)
        serializer = BlogProtoSerializer()  # Instantiate the serializer
        blog_proto = serializer.to_proto(blog)
        return blog_proto

    def Create(self, request, context):
        serializer = BlogProtoSerializer()  # Instantiate the serializer
        blog = serializer.create(request)
        blog.save()
        blog_proto = serializer.to_proto(blog)
        return blog_proto

    def Update(self, request, context):
        blog = get_object_or_404(Blog, id=request.id)
        serializer = BlogProtoSerializer()  # Instantiate the serializer
        updated_blog = serializer.update(blog, request)
        updated_blog.save()
        blog_proto = serializer.to_proto(updated_blog)
        return blog_proto

    def Delete(self, request, context):
        blog = get_object_or_404(Blog, id=request.id)
        blog.delete()
        return blog_pb2.Empty()

handlers.py : ``` from blog.services import BlogService import blog_pb2_grpc

def grpc_handlers(server): """ Register the BlogService with the gRPC server. """ blog_pb2_grpc.add_BlogServiceServicer_to_server(BlogService(), server)


client.py : ```
import logging
import os
import sys
import grpc
import django
from django.conf import settings
from django.shortcuts import get_object_or_404
from django_grpc_framework.services import Service
sys.path.append('c:/Users/JonseThePotato/Documents/Work/MicroServices/BlogSystem/BlogSystem')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'BlogSystem.settings')
django.setup()
from blog.serializers import BlogProtoSerializer
from blog.models import Blog
import blog_pb2_grpc
import blog_pb2

logging.basicConfig(level=logging.INFO)

def run():
    channel = grpc.insecure_channel('localhost:50051')
    stub = blog_pb2_grpc.BlogServiceStub(channel)

    while True:
        print("1. List All Blogs")
        print("2. View a Blog")
        print("3. Create a Blog")
        print("4. Update a Blog")
        print("5. Delete a Blog")
        print("6. Quit")

        choice = input("Enter your choice (1-6): ")

        if choice == '1':
            list_blogs(stub)
        elif choice == '2':
            retrieve_blog(stub)
        elif choice == '3':
            create_blog(stub)
        elif choice == '4':
            update_blog(stub)
        elif choice == '5':
            delete_blog(stub)
        elif choice == '6':
            break
        else:
            print("Invalid choice. Please try again.")

def list_blogs(stub):
    list_request = blog_pb2.BlogListRequest()
    response = stub.List(list_request)

    print("Blogs:")
    for blog in response.blogs:
        print(f"ID: {blog.id}, Title: {blog.title}, Content: {blog.content}")
    print()

def retrieve_blog(stub):
    blog_id = input("Enter the ID of the blog: ")
    retrieve_request = blog_pb2.BlogRetrieveRequest(id=int(blog_id))
    response = stub.Retrieve(retrieve_request)

    print(f"Blog - ID: {response.id}, Title: {response.title}, Content: {response.content}")
    print()

def create_blog(stub):
    title = input("Enter the title of the blog: ")
    content = input("Enter the content of the blog: ")
    blog = blog_pb2.Blog(title=title, main_photo=content)  
    create_request = blog_pb2.BlogCreateRequest(blog=blog)  
    response = stub.Create(create_request)

    print(f"Created Blog - ID: {response.blog.id}, Title: {response.blog.title}, Content: {response.blog.main_photo}")
    print()

def update_blog(stub):
    blog_id = input("Enter the ID of the blog to update: ")
    title = input("Enter the new title of the blog: ")
    content = input("Enter the new content of the blog: ")
    blog = blog_pb2.Blog(id=int(blog_id), title=title, main_photo=content)  
    update_request = blog_pb2.BlogUpdateRequest(id=int(blog_id), blog=blog)  
    response = stub.Update(update_request)

    print(f"Updated Blog - ID: {response.blog.id}, Title: {response.blog.title}, Content: {response.blog.main_photo}")
    print()

def delete_blog(stub):
    blog_id = input("Enter the ID of the blog to delete: ")
    delete_request = blog_pb2.BlogDeleteRequest(id=int(blog_id))
    response = stub.Delete(delete_request)

    print("Blog deleted successfully.")
    print()

if __name__ == '__main__':
    run()
AMontagu commented 1 year ago

As I said in my first message: For information this repo is no more maintained. If you are at the start of your projet considere looking at: https://github.com/socotecio/django-socio-grpc/

It look like you are doing a small school project. Django is a web framework mostly used for website not CMD program. Have you considered not using django and gRPC and just basic python to learn ? Or it it specific to learn gRPC ?

JonesThePotato commented 1 year ago

I just started working at a company and still learning. This is a small part I was trusted with. I was told to do what I am doing right now. I must use this framework.

JonesThePotato commented 1 year ago

I would really appreciate it if you could guide me through.