I've setup a Django REST framework project but the api root hasn't been populated with anything eg a users ViewSet and I can't access the expected url with a list of users.
There is one app users, with a custom user model. (and the django project is named api)
main urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('users.urls')),
]
the users app urls.py
from django.contrib import admin
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from users.views import CustomUserViewSet
router = DefaultRouter()
router.register("users", CustomUserViewSet, 'users')
urlpatterns = [
]
urlpatterns += router.urls
users models.py
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
pass
def __str__(self):
return self.username
users serialisers.py
from rest_framework.serializers import ModelSerializer
from .models import CustomUser
class CustomUserSerializer(ModelSerializer):
class Meta:
model = CustomUser
fields = '__all__'
users app views.py
from django.shortcuts import render
from rest_framework.viewsets import ViewSet
from .serializers import CustomUserSerializer
from .models import CustomUser
class CustomUserViewSet(ViewSet):
serializer_class = CustomUserSerializer
queryset = CustomUser.objects.all(
And empty api root at localhost:8000/api/
and 404 error at localhost:8000/api/users/
If you are using just Viewset, you need to implement the actions.
From the docs:
The ViewSet class does not provide any implementations of actions. In
order to use a ViewSet class you'll override the class and define the
action implementations explicitly
You can add a list action like in the example:
from rest_framework.response import Response
class CustomUserViewSet(ViewSet):
serializer_class = CustomUserSerializer
queryset = CustomUser.objects.all()
def list(self, request):
queryset = CustomUser.objects.all()
serializer = CustomUserSerializer(queryset, many=True)
return Response(serializer.data)
Or (maybe what you are looking for) using something like ModelViewSet that already includes implementations for various actions:
class CustomUserViewSet(viewsets.ModelViewSet):
serializer_class = CustomUserSerializer
queryset = CustomUser.objects.all()
In your case, you have to simply replace
class CustomUserViewSet(ViewSet):
with
class CustomUserViewSet(viewsets.ModelViewSet):
Related
I have a Datatable that's working perfectly, and I wanted Server-side process to be true and not client-side.
But when I enable server-side the sorting, paging and search became faulty.
TestCase: https://codepen.io/TheNerdy97/pen/gOvNeeo?html-preprocessor=pug
I'm using this module https://github.com/izimobil/django-rest-framework-datatables
For seamless integration between Django REST framework and Datatables.
I did as the doc said but it still won't work as expected.
models.py
from unittest.util import _MAX_LENGTH
from django.db import models
#from django.utils.translation import gettext as __
# Create your models here.
class Fresh(models.Model):
code = models.CharField(("code"), max_length=255)
orbs = models.IntegerField(("orbs"))
orbs_display = models.CharField(('orbs_display'), max_length=255)
price = models.IntegerField(("price"))
price_display = models.CharField(('price_display'), max_length=255)
images = models.CharField(("images"), max_length=10000000)
date = models.CharField(("date"), max_length=255)
class Meta:
ordering = ['code', 'orbs', 'price']
def __str__(self):
return self.code
views.py
from django.shortcuts import render
from accounts.models import Fresh, Orbs
from rest_framework import viewsets
from accounts.serializers import FreshSerializer
from django.core import serializers
# Create your views here.
def index (request):
return render(request, 'index.html')
class FreshViewSet(viewsets.ModelViewSet):
queryset = Fresh.objects.all().order_by('price')
serializer_class = FreshSerializer
urls.py
import accounts
from . import views
from django.urls import path, include, re_path
from rest_framework import routers
from main import views
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'fresh', views.FreshViewSet)
router.register(r'orbs', views.OrbsViewSet)
urlpatterns = [
path('', views.index, name='index'),
path('fresh', views.fresh, name='fresh'),
re_path('^api/', include(router.urls)),
]
So I get AttributeError at /api/test
type object 'Product' has no attribute 'objects' error when I try to load up the page via get request, I'm trying to make an API using django rest framework and it says Product has no objects attribute.
views.py
from django.shortcuts import render
from rest_framework import viewsets
from .serializers import ProductSerializer
from .models import Product
from rest_framework.views import APIView
from rest_framework.response import Response
class Product(APIView):
def get(self, request, format=None):
products = Product.objects.all()
serializer = ProductSerializer(products)
return Response(serializer)
urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from . import views
# router = routers.DefaultRouter()
# router.register('products', views.ProductViewSet)
# router.register('test', views.Product)
# urlpatterns = router.urls
urlpatterns = [
path('test', views.Product.as_view())
]
serializers.py
class ProductSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Product
fields = ['name','price','description']
change the name of view, ProductView because its overriding Product model thats why you are getting this error
I am developing a Web API using the Django REST framework. I am new to Django and Python. The problem I am having now is that I cannot return the serializer class.
This is my project structure
I created quickstart/serializers.py with the following definition
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')
This is my quickstart/views.py definition
from django.shortcuts import render
# Create your views here.
from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from quickstart.serializers import UserSerializer, GroupSerializer
class UserViewSet (viewsets.ModelViewSet):
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
class GroupViewSet(viewsets.ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
This is the definition of quickstart/urls.py
from django.urls import path
from quickstart import views
urlpatterns = [
path('users/', views.UserViewSet)
]
This is the urls.py inside the secondly red-lined folder
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
from quickstart import views
from rest_framework import routers
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('quickstart.urls'))
]
When I access to this url (http://127.0.0.1:9191/users/) in the browser, I get this error.
TypeError at /users/
__init__() takes 1 positional argument but 2 were given
Request Method: GET
Request URL: http://127.0.0.1:9191/users/
Django Version: 2.1.2
Exception Type: TypeError
Exception Value:
__init__() takes 1 positional argument but 2 were given
Exception Location: C:\Users\Acer\PycharmProjects\MementoDjango\venv\lib\site-packages\django\core\handlers\base.py in _get_response, line 124
Python Executable: C:\Users\Acer\PycharmProjects\MementoDjango\venv\Scripts\python.exe
Python Version: 3.6.5
Python Path:
['C:\\Users\\Acer\\PycharmProjects\\MementoDjango',
'C:\\Users\\Acer\\PycharmProjects\\MementoDjango\\venv\\Scripts\\python36.zip',
'C:\\Users\\Acer\\AppData\\Local\\Programs\\Python\\Python36-32\\DLLs',
'C:\\Users\\Acer\\AppData\\Local\\Programs\\Python\\Python36-32\\lib',
'C:\\Users\\Acer\\AppData\\Local\\Programs\\Python\\Python36-32',
'C:\\Users\\Acer\\PycharmProjects\\MementoDjango\\venv',
'C:\\Users\\Acer\\PycharmProjects\\MementoDjango\\venv\\lib\\site-packages',
'C:\\Users\\Acer\\PycharmProjects\\MementoDjango\\venv\\lib\\site-packages\\setuptools-39.1.0-py3.6.egg',
'C:\\Users\\Acer\\PycharmProjects\\MementoDjango\\venv\\lib\\site-packages\\pip-10.0.1-py3.6.egg']
Server time: Sat, 13 Oct 2018 20:33:23 +0000
How can I fix it?
This doesn't have anything to do with "returning a serializer class".
The problem is in your urls.py; this isn't at all how you use a ViewSet there. You need to use it with a Router: see the documentation, which has exactly your use case:
router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
urlpatterns = router.urls
Settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES':('rest_framework.authentication.BasicAuthentication',),
'DEFAULT_PERMISSION_CLASSES':('rest_framework.permissions.IsAuthenticated',)
}
models.py
from django.db import models
class Emp(models.Model):
eid = models.IntegerField()
ename = models.CharField(max_length=30)
sal = models.IntegerField()
def __str__(self):
return self.ename
admin.py
from django.contrib import admin
from .models import Emp
class AdminEmp(admin.ModelAdmin):
list_display = ['eid','ename','sal']
admin.site.register(Emp,AdminEmp)
serializers.py
from .models import Emp
from rest_framework import serializers
class EmpSerializer(serializers.ModelSerializer):
class Meta:
model = Emp
fields = ('eid','ename','sal')
views.py
from .serializers import EmpSerializer
from .models import Emp
from rest_framework import viewsets
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import IsAuthenticated
class EmpViewSet2(viewsets.ModelViewSet):
authentication_classes = (BaseAuthentication,)
permission_classes = (IsAuthenticated,)
queryset = Emp.objects.all()
serializer_class = EmpSerializer
app level urls.py
from django.conf.urls import url,include
from .views import EmpViewSet2
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('emp_viewset',EmpViewSet2,base_name='emp_viewset2')
urlpatterns = [
url(r'',include(router.urls)) ]
Project level urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('Basic_Authentication_App.urls'))
]
Username and password window
Django Rest Framework window but when i click on this link
"emp_viewset":"http://127.0.0.1:3499/api/emp_viewset/"
it shows like below:
NotImplementedError at /api/emp_viewset/
.authenticate() must be overridden.
You need to write your own authentication back-end. You can see an example from the official django documentation that explains in detail how to implement (i.e. override) the authenticate function.
Of course, if you want to provide your own permissions, you can implement a custom authentication back-end.
Remove below code from views.py:-
authentication_classes = (BaseAuthentication,)
permission_classes = (IsAuthenticated,)
everything will work properly.
and if you want to change permissions than just add in views.py
permission_classes = []
no need to add
authentication_classes
So the
permission_classes
in views.py will override the permission given in settings.py..
Thankyou.
I try to create Django Build-in API Documentation however I can't add objects to the list on the left. When I open localhost:8000/docs/ I don't see list of my objects as at the top of the official Django REST documentation (in this case snippets and users). Currently I am trying in this way:
urls.py:
from rest_framework.documentation import include_docs_urls
API_TITLE = 'API title'
API_DESCRIPTION = '..df.'
urlpatterns = [
url(r'^docs/', include_docs_urls(title=API_TITLE, description=API_DESCRIPTION)),
]
models.py:
class Object1(models.Model):
user = models.ForeignKey(User)
value = models.FloatField()
admin.py based on developer.mozilla.org:
from django.contrib import admin
from .models import Object1
# Register your models here.
admin.site.register(Object1)
I also based on https://docs.djangoproject.com and I tried with this admin.py version:
class Object1Admin(admin.ModelAdmin):
pass
admin.site.register(Object1, Object1Admin)
I was using also other versions but I did not get a positive result with them, too. Any suggestions?
UPDATE
I was trying to create ViewSet in my views file and import that in url to define router as Raja Simon suggested:
views.py:
from rest_framework import viewset
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
urls.py:
from rest_framework.routers import DefaultRouter
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'users', views.UserViewSet)
urlpatterns = [
url(r'^', include(router.urls))
]
However I didn't achieve what I wanted to. At this moment my list on Django site looks in this way:
But I would like to have list of my objects like in this case:
Change this
user = models.ForeignKey(User)
To
user = models.ForeignKey('auth.User')
It should probably work.
Just create ViewSet in your views file and import that in url to define router
views.py
from rest_framework import viewset
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
urls.py
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'users', views.UserViewSet)
url(r'^', include(router.urls)),