Home > Software engineering >  How to relate two Django models without Foreign Key in Django Rest Framework using PostgreSQL DB
How to relate two Django models without Foreign Key in Django Rest Framework using PostgreSQL DB

Time:11-04

If I was to have two Django models as shown below with Book related to Category, how else can i show the relation without using a Foreign Key when using Django Rest Framework using PostgreSQL DB to make the Foreign Key field editable in a HTML form?

CATEGORIES = [
    ('Fiction', ('Fiction')),
    ('Non-Fiction', ('Non-Fiction'))
]

class Category(models.Model):
   category_name = models.CharField(max_length=255, choices=CATEGORIES)

class Book(models.Model):
   title = models.CharField(max_length=255)
   author = models.CharField(max_length=255)
   pages = models.IntergerField(max_length=255)
   category = models.ForeignKey(Category, on_delete=models.CASCADE)

My challenge comes up in the DB when in the book table the category column in represented as category_id which are integers. This creates a problem as when performing CRUD functions especially EDIT since i can't edit the category from the front-end in a form because it's represented as i.e. 1,2,3..... instead of the actual categories. I want to achieve this with a REST API.

My serializer

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

My API views

@api_view(['POST'])
def AddBookAPI(request):
    serializer = BookSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['PUT'])
def EditBookAPI(request, id):
    book_record =get_object_or_404(Book, id=id)
    serializer = BookSerializer(instance=book_record, data=request.data)
    if serializer.is_valid(raise_exception=True):
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    return Response(serializer.errors, status=status.HTTP_304_NOT_MODIFIED)

@api_view(['DELETE'])
def DeleteBookAPI(request, id):
    book = get_object_or_404(Book, id=id)
    book.delete()

    return Response('Book Record Successfully Deleted!', status=status.HTTP_200_OK)

And a sample response

    {
        "id": 1,
        "title": "The Green Light",
        "author": "Peris Fuller",
        "pages": 456,
        "category": 2,
    },

Any help on this would be appreciated.

CodePudding user response:

It may be okay to have the id for categories. If you want to edit from the frontend, make a get request to get all categories (you did not report category serializer, but there must be id and category_name).

I guess you want to change categories via a select menu. If so, associate each option with the id of each category as a value and the category_name of each category as the text to be displayed.

When you go to edit the model, you will serialize id again, but you will be able to read the category_name.

CodePudding user response:

Add __str__ or __unicode__ methods in your models that will help you to show the name instead of id on the UI.

Like this shared the example of both methods:-

class Category(models.Model):
   category_name = models.CharField(max_length=255, choices=CATEGORIES)

    def __unicode__(self):
        return self.category_name

    def __str__(self):
        return self.category_name

In your BookSerializer you can lookup for the id or name into the Category model and map the values accordingly.

  • Related