esabo
esabo

Reputation: 49

Using name instead of '<int:ok>' urls.py Django API

Goal
I am trying to create a simple Stock management Django REST API. When I specify by id in the urls.py, it successfully retrieves all the data. However, I would like to use the name of the product to retrieve data instead of the id number. I am new for Django, so if anybody could help me out I appreciate it.
Tried
I tried str:name instead of int:pk
-> Error: AssertionError: Expected view StockDetail to be called with a URL keyword argument named "pk". Fix your URL conf, or set the .lookup_field attribute on the view correctly.

When I added to lookup_fields = ('name')
->Error: 'StockDetailView' has no attribute '_meta'

When I added class Meta: under StockDetail in the views.py
it still gave me the same error

I have seen some answers for similar questions using assigning names to slug and using the slug instead of id. I tried by looking at some posts on StackOverflow, but could not able to implement to the goal. If using slug is the case, please demonstrate slug using my code.

Again, I am new to django, so I might be silly question, but I appreciate for the help.

models.py

from django.db import models

# Create your models here.
class Stock(models.Model):
    name = models.CharField(max_length=50)
    stock_number = models.IntegerField('Number of Stocks', )
    price = models.DecimalField(max_digits=6, decimal_places=2)


    def __str__(self):
        return self.name

views.py

from rest_framework import generics
from .models import Stock
from .serializers import StockSerializer

class StockList(generics.ListCreateAPIView): 
    queryset = Stock.objects.all() 
    serializer_class = StockSerializer


class StockDetail(generics.RetrieveUpdateDestroyAPIView): 
    queryset = Stock.objects.all()
    serializer_class = StockSerializer

Serializers.py

from rest_framework import serializers 
from .models import Stock

class StockSerializer(serializers.ModelSerializer):

    
    class Meta:
        fields = ('id', 'name', 'stock_number', 'price') 
        model = Stock

urls.py

from django.urls import path
from .views import StockList, StockDetail
urlpatterns = [
    path('<int:ok>/', StockDetail.as_view()),
    path('', StockList.as_view()),
]

Upvotes: 1

Views: 80

Answers (1)

Amin
Amin

Reputation: 2863

First of all, note that name field is not unique. So you shouldn't try to get one object with just a name.

But, assuming that name is unique, lookup_field should not be a tuple instance:

models:

class Stock(models.Model):
    name = models.CharField(max_length=50, unique=True)
    ...

views:

class StockDetail(generics.RetrieveUpdateDestroyAPIView): 
    queryset = Stock.objects.all()
    serializer_class = StockSerializer
    lookup_field = 'name'

urls:

...
path('<str:name>/', StockDetail.as_view()),

And if your name is not unique(makes more sense), use your StockList and override get_queryset():

class StockList(generics.ListCreateAPIView):
    serializer_class = StockSerializer

    def get_queryset(self):
        name = self.kwargs['name']
        return Stock.objects.filter(name=name)

Upvotes: 1

Related Questions