DRF Newbie - Stuck in small mistake kindly assist - python-3.x

I created 1 API its all working fine from all ends.
I created 2nd API the DRF headings title showing the headings of old api where i am doing mistake kindly assist.
serializers.py
from rest_framework import serializers
from .models import Brand, Category
class BrandSerializer(serializers.ModelSerializer):
class Meta:
model = Brand
fields = (
'id',
'name',
'slug',
'icon',
'featured_image',
'url'
)
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = (
'id',
'name',
'slug',
'featured_image',
)
products.url
router = routers.DefaultRouter()
router.register(r'', BrandViewSet)
router.register(r'', CategoryViewSet)
urlpatterns = [
path('', include(router.urls)),
]
product.view
class CategoryViewSet(viewsets.GenericViewSet, mixins.RetrieveModelMixin, mixins.ListModelMixin):
"""
API endpoint that allows sites to be viewed or edited
"""
queryset = Category.objects.all()
serializer_class = CategorySerializer
There is no error but in brower when i run the API url it shows brand list instead of category list,

The problem is that you have the views registered to the same endpoint. So it resolves the first one it finds.
So do the register to different endpoints like this:
router = routers.DefaultRouter()
router.register(r'brands', BrandViewSet)
router.register(r'categories', CategoryViewSet)
urlpatterns = [
path('', include(router.urls)),
]
So you can access brands via 127.0.0.1:8000/brands and categories via 127.0.0.1:8000/categories

Related

Why django-rest-framework is generating same api url for two views (both views having same queryset)?

My Project Configuration is this. This is realated to Contact Form. Here I have two approach: Customer from frontend can only post (i.e. send message) and admin can only retrieve and list the contacts.
Models.py
class Contact(models.Model):
full_name = models.CharField(max_length=100)
email = models.EmailField()
phone_no = models.CharField(max_length=10, validators=[validate_phone_no])
message = models.TextField()
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
def __str__(self):
return self.email
serializers.py
class ContactSerializer(serializers.ModelSerializer):
class Meta:
model = Contact
fields = [
'full_name',
'email',
'phone_no',
'message',
]
Views.py
class ContactViewset(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
queryset = Contact.objects.all()
search_fields = []
ordering_fields = []
ordering = []
http_method_names = ["options", "head", "get"]
serializer_class = ContactSerializer
class CustomerContactViewSet(viewsets.ModelViewSet):
permission_classes = [AllowAny]
queryset = Contact.objects.all()
http_method_names = ['post']
serializer_class = ContactSerializer
urls.py
router.register("contacts-detail", ContactViewset)
router.register("contact-form", CustomerContactViewSet)
My question is: Why DRF is generating the same url for both views although I have given different names for both:
'contact-form'----> for posting and
'contact-detail'--------> for listing the contacts
Both views are pointing to same Model - Is this the Reason?
Click Here to see generated api url
See last urls are same: and redirecting to "contact-form". and I know I can give base_name to seperate both.
But I wanted to know the mechanism behind generating same url:
If anyone could explain this? Clearly
The problem is with the way you have defined the router.register calls in your urls.py file.
The first argument of the router.register function is the base name for the viewset. This base name is used to generate the URL patterns for the viewset. If you use the same base name for multiple viewsets, then the router will generate the same URL pattern for both viewsets.
For example, in your code you have defined the following lines:
router.register("contacts-detail", ContactViewset)
router.register("contact-form", CustomerContactViewSet)
Here, you have used the base name "contacts-detail" for the ContactViewset and the base name "contact-form" for the CustomerContactViewSet. This will result in two different URL patterns being generated:
/contacts-detail/
/contact-form/
However, since both viewsets are using the same model (Contact), the router will generate the same set of URL patterns for both viewsets. This is why you are seeing the same URL patterns for both viewsets in your API.
To fix this problem, you can use different base names for the two viewsets. For example, you could use "contacts" for the ContactViewset and "customer-contacts" for the CustomerContactViewSet. This would result in the following URL patterns being generated:
/contacts/
/customer-contacts/

How to upload multiple images and multiple data fields in django rest framework

Read:How to upload multiple files in django rest framework
read:django rest framework for multiple image upload
But still unable to follow as proper description is not given
hi,
i am creating a rest api and new to django rest framework. I need help with few points mentioned below:
How to create Foreign key correctly.I have two tables one where images will be uploaded and one where data will be saved, i want id of these two tables should be foreign key so that when i select data from table 1 i can make query and get images related to id of table 1 from images table
I have created serializers but they say when i run my code to check errors using serializers.error
{'image': ['Incorrect type. Expected pk value, received bytes.'], 'img_id':
['Invalid pk "1" - object does not exist.']}
I am writing a post api to i need to save data and images first
How can i achieve this
my code
models
from django.db import models
# Create your models here.
class ImageModels(models.Model):
media = models.ImageField(upload_to="images")
class categoryRegistration(models.Model):
name = models.CharField(max_length=100)
image=models.ManyToManyField(ImageModels,related_name="file_content",blank=True,null=True)
description = models.TextField()
price = models.IntegerField()
img_id = models.ForeignKey(ImageModels,on_delete=models.CASCADE)
serializer
from rest_framework import serializers
from apps.categorymanagement.models import categoryRegistration
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = categoryRegistration
fields = ("id",'name', 'image', 'description', 'price',"img_id")
extra_kwargs = {
"image":{
"required":False,
},
}
urls:
from django.conf.urls import url
from apps.categorymanagement import views
urlpatterns = [
url( r'^object/categories$',views.category_list ,name="categoryList"),
url( r'^categories/data/(?P<pk>[0-9]+)$',views.category_detail,name="categoryDetails" ),
url( r'^categories/released$',views.category_released,name="categoryReleased" )
]
views:
from django.http.response import JsonResponse
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rest_framework import status
from apps.categorymanagement.models import ImageModels, categoryRegistration
from apps.categorymanagement.serializers import CategorySerializer
from rest_framework.decorators import api_view
# all the views written here are fuctions based
#api_view(['GET','POST','DELETE'])
def category_list(request):
# get list of all categories
if request.method=="POST":
files = request.FILES.getlist("file_content")
form_data = {}
form_data["name"] = request.data["name"]
form_data["description"] = request.data["description"]
form_data["price"] = request.data["price"]
form_data["img_id"] = request.data["img_id"]
for images in files:
form_data["image"] = images
serializer = CategorySerializer(data=form_data)
print(serializer.is_valid())
print(serializer.errors)
return Response('ok')

Django rest framework. Setting up dynamic routes

I am setting up an API for a blog. I configured the output of comments for the post
Here is a portion of my views.py with #action:
urls.py
router = DefaultRouter()
router.register('api/posts', APIPost)
urlpatterns = [
path('', include(router.urls)),
]
views.py
...
#action(methods=['get'], detail=True)
def comments(self, request, pk=None):
if request.method == 'GET':
queryset = Comment.objects.filter(post__id=pk)
serializer = CommentSerializer(queryset, many=True)
return Response(serializer.data)
return Response(status=status.HTTP_403_FORBIDDEN)
Now I can get all comments on a post at.
http://127.0.0.1:8000/api/posts/{post_pk}/comments/
The problem is that I just can't figure out how to get a separate comment at
http://127.0.0.1:8000/api/posts/{post_pk}/comments/{comment_pk}
I keep getting '404 Not Found' error
You should create another CommentViewSet. (docs)
views.py
from rest_framework import viewsets
class CommentViewSet(viewsets.ModelViewSet):
queryset = Comment.objects.all()
serializer_class = CommentSerializer
urls.py
from .views import CommentViewSet
router = DefaultRouter()
router.register("api/posts", APIPost)
router.register("api/comments", CommentViewSet)
urlpatterns = [
path('', include(router.urls)),
]
and then you can retrieve by making a request to http://127.0.0.1:8000/api/comments/{pk}.
also, in your code,
#action(methods=['get'], detail=True) it should be #action(methods=['get'], detail=False) instead because the comments action is to retrieve list of all comments. detail=True is for returning a single object.
You don't need to manually check for the if request.method == 'GET' as DRF is already doing that internally because you already specified methods=["get"].
You should define URL Path or Route to a certain Address for the comments to load .
Like you defined the APIPost model ...comment url route should be like below
router.register(r"comments", comments)

How to fix "ImproperlyConfigured" erros in django rest_framework urls.py

I am trying to figure out how django rest framework works and write some code. But i am getting
django.core.exceptions.ImproperlyConfigured: The included URLconf 'tutorial.urls' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused by a circular import
what is circular import? I can't understand. I created a app called quickstart inside i create serializers.py file.
quickstart/serializers.py
from django.contrib.auth.models import User, Group
from rest_framework import serializers
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email', 'groups')
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ('url', 'name')
quickstart/views.py
from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from quickstart.serializers import UserSerializer, GroupSerializer
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
class GroupViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
queryset = Group.objects.all()
serializer_class = GroupSerializer
quickstar/urls.py
from rest_framework import routers
from .views import UserViewSet, GroupViewSet
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
urlpatterns = router.urls
testing/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('quickstart.urls')),
# path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('admin/', admin.site.urls),
]
can you please describe why this error happened frequently?
Thank you!

How can I list all the nodes in my database?

I'm trying to create a simple model Node and a simple web page that shows all of my nodes in a list. But it seems not working and everytime I change the code I got a new error. So I gave up and came to here.This is what I did:
I created a Node model:
class Node(models.Model):
ID = models.DecimalField(max_digits=9, decimal_places=6)
nb_solenoid = models.DecimalField(max_digits=9, decimal_places=6, null=True, blank=True)
connexion = models.CharField(max_length=255)
def get_absolute_url(self):
return reverse("node:index", kwargs={"id": self.id})
with this form:
class NodeForm(forms.ModelForm):
ID = forms.DecimalField(initial=0)
nb_solenoid = forms.DecimalField(initial=1)
connexion = forms.CharField(required=False,
widget=forms.Textarea(
attrs={
"placeholder": "type of connexion"
}))
class Meta:
model = Node
fields = [
'ID',
'nb_solenoid',
'connexion'
]
And this is my views.py:
def index(request):
queryset = Node.objects.all()
context = {
"object_list": queryset
}
return render(request, "node/index.html", context)
This is my code in urls.py:
urlpatterns = [path('', views.index, name='index')]
When I call this url: http://localhost:8000/node I get this error now:
NoReverseMatch at /node
Reverse for 'index' with keyword arguments '{'id': 1}' not found. 1 pattern(s) tried: ['node$']
What is a NoReverseMatch error and how do I fix my problem? Let me say that I'm a Django beginner developer.
Thank you.
The issue is that your named url path node:index takes no arguments (presumably because that view is just listing out all the nodes, not a specific node), yet your model's get_absolute_url is trying to reverse the pattern with a kwarg of id. The core problem is your get_absolute_url method; however, you really probably also would benefit from just using class based generic views:
urls.py:
urlpatterns = [
path('nodes/', NodeList.as_view(), name="node-list"),
path('node/<id>/', NodeDetail.as_view(), name="node-detail")
]
view.py:
from django.views.generic import ListView, DetailView
from .models import Node
class NodeList(ListView):
model = Node
class NodeDetail(DetailView):
model = Node
models.py:
class Node(models.Model):
<snip>
def get_absolute_url(self):
return reverse("node-detail", kwargs={"id": self.id})
I really should have mentioned, documentation for class based generic views are at: https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-display/

Resources