I want to add a class-based view to return users created from one date to another date. I have tried the following are there other ways to filter the user-created between two dates?
While doing this I get:
TypeError: get() missing 1 required positional argument: 'to_date'
views.py
class RegisteredUserFilter(APIView):
serializer = RegisteredUserFilterSerializer
def get(self, from_date, to_date):
userondate = User.objects.filter(created_at__range=[from_date, to_date]).values()
return Response({"User": userondate})
serializers.py
class RegisteredUserFilterSerializer(serializers.Serializer):
from_date = serializers.DateField()
to_date = serializers.DateField()
model = User
full code at: https://github.com/abinashkarki/rest_framework_authentication/tree/master/authapp
using Django filters
serilaizers.py
add the following
class RegisteredUserFilterSerializer(serializers.Serializer):
class Meta:
model = User
fields = ['username', 'created_at']
make file name it filters.py in same path of views.py
filters.py
from django_filters.rest_framework import FilterSet
import django_filters
from .models import User
from django_filters.widgets import RangeWidget
class UserFilter(FilterSet):
date_range = django_filters.DateFromToRangeFilter(label='Date Range', field_name='created_at',
widget=RangeWidget(attrs={'type': 'date'}))
class Meta:
model = User
fields = ['created_at']
Views.py
from .serializers import RegisteredUserFilterSerializer
from .filters import UserFilter
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.generics import ListAPIView
class RegisteredUserFilter(ListAPIView):
serializer_class = RegisteredUserFilterSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = UserFilter
model = User
urls.py add
from django.urls import path
from .views import RegisteredUserFilter
urlpatterns = [
path('users-filter/', RegisteredUserFilter.as_view(), name="user-filter"),
]
finally do not forget to make
pip install django-filter
and add it to installed app in settings.py
INSTALLED_APPS = [
...
'django_filters',
]
for more information refer to https://django-filter.readthedocs.io/en/stable/guide/rest_framework.html
another approach
you can make this process manually by overriding the get method and getting query parameters manually
and return response after serializing the query set
Related
I was trying to do put request on Postman and it's successful, but when I try the get method to get same result one of the fields which is car_year shows null.
from django.shortcuts import render
from django.http import HttpResponse,JsonResponse
from rest_framework.parsers import JSONParser
from .models import Driver
from .serializers import DriverSerializer
from django.views.decorators.csrf import csrf_exempt
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from rest_framework import generics
from rest_framework import mixins
from rest_framework.views import APIView
# Create your views here.
class GenericAPIView(generics.GenericAPIView,mixins.ListModelMixin,mixins.CreateModelMixin,mixins.UpdateModelMixin,mixins.RetrieveModelMixin,mixins.DestroyModelMixin):
serializer_class = DriverSerializer
queryset = Driver.objects.all()
lookup_field = 'id'
def get(self,request,id=None):
if id:
return self.retrieve(request)
else:
return self.list(request)
def post(self,request):
return self.create(request)
def put(self,request,id=None):
return self.update(request,id)
from django.db import models
# Create your models here.
class Driver(models.Model):
name=models.CharField(max_length=100)
email=models.EmailField(max_length=100)
phone_number=models.IntegerField(max_length=None)
car_model=models.CharField(max_length=100)
car_year=models.IntegerField(max_length=None)
def __str__(self):
return self.name
from rest_framework import serializers
from .models import Driver
class DriverSerializer(serializers.ModelSerializer):
class Meta:
model=Driver
fields=['id','name','email','phone_number','car_model','car_year'] ```
Instead of using that very GenericAPIView class that you've made, look into using a ModelViewSet. Besides that, you are missing the permissions_classes in your APIView.
Try this:
from rest_framework import viewsets, permissions
class DriverViewSet(viewsets.ModelViewSet):
queryset = Driver.objects.all()
serializer_class = DriverSerializer
permission_classes = [permissions.IsAuthenticated]
Also, your serializer looks fine.
car_year and phone_number are IntegerFields and you've set the max_length on them. That max_length=None should be removed.
Try the things I mentioned and it should would fine. I'm guessing it's most likely the view you are using but it could also be the integer field.
Also, if this is going to be a production app, the phone_number field shouldn't be an integer but rather a string, or better yet, you can use the django-phonenumber-field library.
My models have multiple attributes, all of which are being serialized.
According to the user's request, I want my API to return only limited information
This is my model's code
from django.db import models
class User(models.Model):
name = models.CharField(max_length=50)
age = models.PositiveSmallIntegerField()
description = models.CharField(max_length=200)
def __str__(self) -> str:
return self.name
This is my Serializer's code
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
This is my View's code
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import User
from .serializers import UserSerializer
from rest_framework import serializers
from rest_framework import status
from django.http import JsonResponse
#api_view(['GET'])
def viewUsers(request):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return JsonResponse({'id': serializer.data['id'], 'name': serializer.data['name']})
The code below works if I want to return a single attribute/field
return JsonResponse(serializer.data['id'])
but when I try to fetch more than one attribute by the dictionary method, it throws this error
list indices must be integers or slices, not str
many=True passed to UserSerializer indicates that serializer.data will contain a list of dicts where each particular dict will be a result of serializing User instance to expected dict
Taking into account serializer.data is a list then if you try to execute serializer.data['id'] it raises
list indices must be integers or slices, not str
You may want to update the return statement to
return JsonResponse([{'id': item['id'] for item in serializer.data}])
or specify that you expect only id field to be returned by the serializer
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ("id",)
and then in the view
return JsonResponse(serializer.data)
I have model Product with field MoneyField in /products/models.py
class Product(SeoModel, ModelWithMetadata, PublishableModel):
name = models.CharField(max_length=128)
currency = models.CharField(
max_length=settings.DEFAULT_CURRENCY_CODE_LENGTH,
default=settings.DEFAULT_CURRENCY,
)
price_amount = models.DecimalField(
max_digits=settings.DEFAULT_MAX_DIGITS,
decimal_places=settings.DEFAULT_DECIMAL_PLACES,
)
price = MoneyField(amount_field="price_amount", currency_field="currency")
My views.py is:
from .models import Product
from .serializers import ProductListSerializer
from rest_framework import generics
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductListSerializer
and serializers.py:
from rest_framework import serializers
from .models import Product
class ProductListSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ['name', 'id']
and when i go to url i have error:
AttributeError at /ru/products/api/
'MoneyField' object has no attribute 'serialize'
Request Method: GET
Request URL: http://127.0.0.1:8000/ru/products/api/
Django Version: 2.2.6
Exception Type: AttributeError
Exception Value:
'MoneyField' object has no attribute 'serialize'
Can you help me? Thank you!
DRF's ModelSerializer assumes fields that are on the model extend django.db.models.fields.Field, which MoneyField does not. This is a problem when ModelSerializer is collecting fields:
# rest_framework.utils.model_meta._get_fields
def _get_fields(opts):
fields = OrderedDict()
for field in [field for field in opts.fields if field.serialize and not field.remote_field]:
fields[field.name] = field
return fields
You can fix the problem by subclassing MoneyField:
from django_prices.models import MoneyField as BaseMoneyField
class MoneyField(BaseMoneyField):
serialize = True
This will probably lead to your next problem ;)
In Django REST Framework. By default it uses - /?search= in URL while searching for anything.
For Example http://127.0.0.1:8000/api/branches/?search=RTGS
And this url successfully getting the result.
But I need to change the URL to http://127.0.0.1:8000/api/branches/autocomplete?q=RTGS
In the documentation, https://www.django-rest-framework.org/api-guide/settings/#search_param
It is given that it is set by default. https://www.django-rest-framework.org/api-guide/settings/#search_paramd we can change.
I am wondering how.
Thanks
https://www.django-rest-framework.org/api-guide/settings/#search_param
urls.py
from django.urls import path, include
from . import views
from rest_framework import routers
router = routers.DefaultRouter()
# router.register('bank', views.BankView)
router.register('branches/autocomplete', views.BankDetailView)
# router.register('branches/list', views.BankAPIListView)
urlpatterns = [
path('api/', include(router.urls)),
]
views.py
from django.shortcuts import render, redirect
from rest_framework import viewsets
from .models import Branches
from .serializers import BranchesSerializer
from rest_framework import filters
from rest_framework.filters import OrderingFilter
from rest_framework.pagination import PageNumberPagination
# from django_filters.rest_framework import DjangoFilterBackend
class BankDetailView(viewsets.ModelViewSet):
queryset = Branches.objects.all()
serializer_class = BranchesSerializer
filter_backends = [filters.SearchFilter, OrderingFilter]
# Partial Search with the field in branch
search_fields = ['^branch']
# Ordering Filter field by ifsc in ascending order
# filter_backends = [DjangoFilterBackend]
# filterset_fields = ['ifsc']
serializers.py
from rest_framework import serializers
from .models import Branches
class BranchesSerializer(serializers.HyperlinkedModelSerializer):
class Meta :
model = Branches
fields = ['url' ,'ifsc', 'bank_id', 'branch', 'address', 'city',
'district', 'state']
http://127.0.0.1:8000/api/branches/autocomplete?q=RTGS&limit=3&offset=0
From the docs:
By default, the search parameter is named 'search', but this may be overridden with the SEARCH_PARAM setting.
Thus, in your settings.py:
REST_FRAMEWORK = {
'SEARCH_PARAM': 'q'
}
EDIT:
Here you can see the actual code:
Settings: https://github.com/encode/django-rest-framework/blob/master/rest_framework/settings.py#L68
Filters: https://github.com/encode/django-rest-framework/blob/master/rest_framework/filters.py#L42
If you'd like to change query parameter key in only one view, you can extend SearchFilter and then add it to filter_backends of your view.
class CustomSearchFilter(SearchFilter):
search_param = "q"
class MyListView(ListAPIView):
# ...
filter_backends = [CustomSearchFilter]
# ...
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!