I want to get only one element in a JSON object, from Django Rest Framework.
I got the next code Serializer:
class OneUserSerializer(serializers.ModelSerializer):
class Meta:
model = Usuario
fields = ('usuario', 'nombre', 'apellidos', 'mensajes')
The View Set:
class OneUserViewSet(viewsets.ModelViewSet):
queryset = Usuario.objects.filter(id = 'Here is the PARAMETER')
serializer_class = OneUserSerializer
The url:
router.register(r'user', views.OneUserViewSet)
I want to get only one object 'Usuario' passing the id from the url for example url/id_user
If you're using SimpleRouter, then urls will be generated for you:
class OneUserViewSet(viewsets.ModelViewSet):
queryset = Usuario.objects.all()
serializer_class = OneUserSerializer
urls.py
from rest_framework import routers
router = routers.SimpleRouter()
router.register(r'user', views.OneUserViewSet)
urlpatterns = router.urls
This will generate the following url (among others):
^users/{pk}/$
Related
I created a serializer and an API endpoint so I can retrieve some data from a Django DB in my React app but getting this error message:
AttributeError: 'ProgrammingChallengesView' object has no attribute 'get'
Here is my models.py:
#creating programming challenges
class ProgrammingChallenges(models.Model):
challenge_id = models.AutoField(primary_key=True)
challenge_name = models.CharField(max_length=200)
challenge_description = models.TextField()
challenge_expectations = models.TextField()
my serializer:
from accounts.models import ProgrammingChallenges
...
class ProgrammingChallengesView(serializers.ModelSerializer):
class Meta:
model = ProgrammingChallenges
fields = '__all__'
and my urls.py:
path('api/programming_challenges/', ProgrammingChallengesView, name='programming_challenges'),
Thanks to the comments; I clearly didn't understand that a serializer only transforms my data to make it available through an API. I still had to create a view for my API's endpoint.
I opted to create a ReadOnlyModelView because I only want to GET data from this endpoint.
Here is what I wrote in my views:
class ProgrammingChallengesView(ReadOnlyModelViewSet):
serializer_class = ProgrammingChallengesSerializer
queryset = ProgrammingChallenges.objects.all()
#action(detail=False)
def get_list(self, request):
pass
and in my urls.py:
path('api/programming_challenges/', ProgrammingChallengesView.as_view({'get':'list'}), name='programming_challenges'),
I think you shouldn't hurry read the docs again. You are trying to use serializers as views.
Models - are representation of db tables as class.
Serializer serializes the data to json.
View accepts the reqeust from client and returns a Response.
Code shoudld be:
models.py
class ProgrammingChallenge(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
expectations = models.TextField()
Your model name should be ProgrammingChallenge(singular) not ProgrammingChallenges(plural).
You should't add prefix challenge before all field names. Because we already know that the fields are in a Model called ProgrammingChallenge. And it is easy to access them like ProgrammingChallenge.name than ProgrammingChallenge.challenge_name
You don't have to add field id manually. Django model automatically adds id field as primary_key
serializer.py
from accounts.models import ProgrammingChallenge
...
class ProgrammingChallengeSerializer(serializers.ModelSerializer):
class Meta:
model = ProgrammingChallenge
fields = '__all__'
No problem in serialize.
Now, main problem is you don't have any view. You definetly read docs. You can use APIView, generic views or viewset. In this example i'm going to use ViewSet that handles CRUD operations built in.
viewsets.py
from rest_framework.viewsets import ModelViewSet
from .models import ProgrammingChallenge
from .serializers import ProgrammingChallengSerializer
class ProgrammingChallengViewSet(ModelViewSet):
queryset = ProgrammingChallenge.objects.all()
serializer_class = ProgrammingChallengeSerializer
urls.py
from rest_framework.routers import SimpleRouter
from .viewsets import ProgrammingChallenge
router = SimpleRouter()
router.register('challengr', ProgrammingChallengeViewSet)
urlpatterns = router.urls
Another advantage of using viewset, it also generate all endpoint for it's CRUD methods automatically via routes.
It should help you to start your first project.
AGAIN, READ THE DOCS!
A newbie here in the world of Django. I am struggling with creating a hyperlink for a nested route.
The error I am getting is:
Could not resolve URL for hyperlinked relationship using view name "rest:campaign-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
Some project setup notes
Using django rest framework
using DRF-extensions to create the routes
Using ModelViewSet
Expected end points:
/accounts/
/accounts/< pk >/
/accounts/< pk >/campaigns/
/accounts/< pk >/campaigns/< pk >/
/accounts/< pk >/campaigns/adgroup/
/accounts/< pk >/campaigns/adgroup/< pk >/
Set a namespace of rest in urls.py
Using HyperlinkedIdentityField to create the hyperlink. It only works with the parent object i.e.
url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')
However fails with any nested object i.e.
url = serializers.HyperlinkedIdentityField(view_name='rest:campaign-detail')
The model is quiet simple, an Account can have many Campaigns, and a campaign can have many AdGroups. See code below:
models.py
from django.db import models
from django.db.models import Q
from model_utils import Choices
ORDER_COLUMN_CHOICES = Choices(
('0', 'id'),
('1', 'keyword'),
('2', 'status'),
('3', 'match_type'),
)
# Account
class Account(models.Model):
account_name = models.CharField(max_length=128)
def __str__(self):
return self.account_name
# Campaign
class Campaign(models.Model):
class Status(models.TextChoices):
Enabled = "Enabled"
Paused = "Paused"
account = models.ForeignKey(
to=Account, on_delete=models.CASCADE, related_name='campaigns'
)
campaign_name = models.CharField(max_length=128)
status = models.CharField(max_length=21, choices=Status.choices, default=Status.Paused)
def __str__(self):
return self.campaign_name
# AdGroup
class AdGroup(models.Model):
class Status(models.TextChoices):
Enabled = "Enabled"
Paused = "Paused"
campaign = models.ForeignKey(
to=Campaign, on_delete=models.CASCADE, related_name='adgroups'
)
adgroup_name = models.CharField(max_length=128)
status = models.CharField(max_length=21, choices=Status.choices, default=Status.Enabled)
def __str__(self):
return self.adgroup_name
views.py
from rest_framework import viewsets
from .serializers import *
from . import models
from rest_framework_extensions.mixins import NestedViewSetMixin
class AccountViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = AccountSerializer
queryset = models.Account.objects.all()
class CampaignViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = CampaignSerializer
queryset = models.Campaign.objects.all()
class AdGroupViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = AdGroupSerializer
queryset = models.AdGroup.objects.all()
serializers.py
from rest_framework import serializers
from . import models
class CampaignSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="rest:campaign-detail")
class Meta:
model = models.Campaign
fields = '__all__'
class AccountSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')
class Meta:
model = models.Account
fields = '__all__'
class AdGroupSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='rest:adgroup-detail')
class Meta:
model = models.AdGroup
fields = '__all__'
I have 2 URL files. The project is named Vanilla and an app named rest where the DRF logic sits.
Vanilla urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('rest.urls', namespace='rest')),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('admin/', admin.site.urls)
]
Rest urls.py
from django.urls import include, path
from . import views
from rest_framework_extensions.routers import ExtendedSimpleRouter
app_name = 'rest'
router = ExtendedSimpleRouter()
(
router.register(r'accounts',
views.AccountViewSet,
basename='account')
.register(r'campaigns',
views.CampaignViewSet,
basename='campaign',
parents_query_lookups=['account__id'])
.register(r'adgroups',
views.AdGroupViewSet,
basename='adgroup',
parents_query_lookups=['campaign__account', 'campaign'])
Thank You!
use hyperlinkedModelSerializer in all of your related serializer. that should work
I am having a hard time to understand how to display function based views URLS with Django REST FRAMEWORK.
I have the setup below of my project but for some reason I am unable to display the endpoint while MovieListViewSet works.
PROJECT.URLS
from users import views
router = routers.DefaultRouter()
router.register(r'movies', MovieListViewSet)
urlpatterns = [
path('', include(router.urls)),
path('admin/', admin.site.urls),
path('profile/', views.ProfileList, name='ProfileList')
]
users.model
User = settings.AUTH_USER_MODEL
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500)
location = models.CharField(max_length=50)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return self.user.username
serializers
from rest_framework import serializers
from users.models import Profile
class ProfileSerializer(serializers.ModelSerializer):
user = serializers.StringRelatedField(read_only=True)
class Meta:
model = Profile
fields = (
'id',
'user',
#'bio',
#'location',
'image',
)
I have comment bio and location because when they are uncommented, I receive this message.
Got AttributeError when attempting to get a value for field `bio` on serializer `ProfileSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `QuerySet` instance.
Original exception text was: 'QuerySet' object has no attribute 'bio'.
users.views (app)
#api_view(["GET"])
def ProfileList(APIView):
profile = Profile.objects.all()
serializer = ProfileSerializer(profile)
return Response(serializer.data)
I am unable to see ProfileList view as endpoint
Can someone point me to what I am doing wrong to display this endpoint to django rest framework.
You should specify many=True while serialization.
serializer = ProfileSerializer(profile, many=True)
You are mixing up functions and class based view definition here:
#api_view(["GET"])
def ProfileList(APIView):
profile = Profile.objects.all()
serializer = ProfileSerializer(profile)
return Response(serializer.data)
Either you define a class based view like this:
class ProfileView(APIView):
profile = Profile.objects.all()
serializer = ProfileSerializer
def list(request):
return Response(self.serializer_class(self.get_queryset(), many=True).data)
Or a function base view like:
#api_view(["GET])
def profile_list(request):
return Response(ProfileSerializer(Profile.objects.all(), many=True).data)
[Error][1]
AssertionError at /api/client-details/ Expected view Client_view to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly. Request Method: DELETE Request URL:
http://127.0.0.1:8000/api/client-details/ Django Version: 2.2.6 Python Executable: C:\Users\AravindManoj\PycharmProjects\Client\venv\Scripts\python.exe Python Version: 3.7.4 Python Path:
['C:\\Users\\AravindManoj\\PycharmProjects\\Client\\Client',
'C:\\Users\\AravindManoj\\AppData\\Local\\Programs\\Python\\Python37\\python37.zip',
While using Generic view in Django it Showing Error while using DELETE function.Please anyone give me the syntax of generic views in model set i didnt find any problem but no Delete function
Views.py
from django.http import Http404, HttpResponse
from rest_framework import viewsets, status, generics
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import ClassSerializer
from .models import Client
class Client_view(viewsets.ModelViewSet, generics.RetrieveUpdateDestroyAPIView):
queryset = Client.objects.all().order_by('-Name')
serializer_class = ClassSerializer*
lookup_fields = ['Name', 'UserName', 'Mobile', 'Email', 'Address']
urls.py
from rest_framework import routers
from .views import Client_view
router = routers.DefaultRouter()
router.register('', Client_view)
urlpatterns = router.urls
models.py
from django.db import models
class Client(models.Model):
Name = models.CharField(max_length=15)
UserName = models.CharField(max_length=15)
Email = models.CharField(max_length=20)
Mobile = models.CharField(max_length=10)
Address = models.CharField(max_length=20)
serializer.py
from rest_framework import serializers
from .models import Client
class ClassSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Client
fields = ['Name', 'UserName', 'Email', 'Mobile', 'Address']
You have used lookup_fields which is not any built-in feature. Try to do it with a custom mixin like described here in the docs.
When using a ViewSet (in your case you are using a ModelViewSet) the view requires a pk value from urls. This is done automatically when using a router.
The router will create a number of urls:
Example:
router.register(r'', Client_view)
URL pattern: ^$ Name: 'client_view-list'
URL pattern: ^{pk}/$ Name: 'client_view-detail'
One of the attributes of a ViewSet is lookup_field, the lookup field allows you to change the name of the url capture you are using. In your case, you seem to have lookup_fields and specified multiple values. Try changing this to lookup_field='pk.
As a side note, it can be helpful to take a look at the restframework source code around Views.
just add lookup_field = 'pk' on the Client_view...
ie:
class Client_view(viewsets.ModelViewSet, generics.RetrieveUpdateDestroyAPIView):
queryset = Client.objects.all().order_by('-Name')
serializer_class = ClassSerializer*
lookup_field = 'pk'
I am new to Django REST Frameworks and despite doing the tutorial twice and reading lots of documentation I can't work out exactly how to handle/access the arguments in a URL in the DRF ViewSet.
My URL looks like this:
/api/v1/user/<user-id>/<age>/update
In my base urls.py I have the urlpattern:
url(r'^api/v1/', include('api.urls'))
In the api/urls.py I have:
from django.conf.urls import url, include
from rest_framework import routers
from api import views
router = routers.DefaultRouter()
router.register(r'user', views.UserViewSet)
urlpatterns = [
url(r'^', include(router.urls))
]
My question is what should my UserViewSet look like to handle the url, extract the user id and age fields, and update the UserDetails model so the given user has the given age?
My model hasn't been created yet but will look something like this:
class UserDetails(models.Model):
user = models.ForeignKey(User)
age = models.BigIntegerField(blank=True, null=True)
In the serializers.py adde the ParameterisedHyperlinkedIdentityField as a serializer.
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
url = ParameterisedHyperlinkedIdentityField(view_name='user-detail', lookup_fields=(('id', 'id'), ('age', 'age')), read_only=True)
class Meta:
model = UserDetails
urls.py
from .viewsets import UserViewSet
user_list = UserViewSet.as_view({'get':'list'})
user_detail = UserViewSet.as_view({'get':'retrieve'})
urlpatterns= [
url(r'^user/(?P<id>\d+)/(?P<age>[-\w\d]+)/update/$', user_detail, name='user-detail')
]
viewsets.py
class UserViewset(viewsets.ModelViewSet):
lookup_field = 'id'
serializer_class = UserSerializer
queryset = UserDetails.objects.all()