I am new to Django and React. I am taking over a Django / React project and have an issue where an api url is called:
GET /api/admin/parents/
but the underlying sql statement:
from django.http import HttpResponseRedirect
from django.db.models import Q
from .models import *
from rest_framework import permissions, status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.generics import ListAPIView, ListCreateAPIView, CreateAPIView, RetrieveUpdateAPIView, DestroyAPIView
from .serializers import *
from twilio.rest import Client
class AdminAllParentsView(ListAPIView):
serializer_class = UserSerializer
queryset = User.objects.filter(is_staff=False, is_parent=True, is_active=True)
does not get re-executed each time the GET /api/admin/parents/ call is performed.
Say for instance.. a sql record is changed so that there are fewer records matching the is_parent=True part of the api call / query... the results returned by the api call don't reflect the real / current status of the query. The GET /api/admin/parents/ still returns the data from a previous, sql query ( a cached version I assume ) and does not re-execute the query.
The urls.py part of this is:
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
from .views import *
urlpatterns = [
path('admin/parents/', AdminAllParentsView.as_view())
So how to I get current sql data from this each time I do a api call?
jack
... I see in the browser that the /api/admin/parents/ request goes out and returns the old data via json data. It's not a cached browser html thing.
and
... here is the user serializer code... someone said that this might be important too.
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings
from .models import *
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = (
'id',
'email',
'first_name',
'last_name',
'is_parent',
'phone',
'mobile_phone',
'address',
'city',
'zip',
'county',
'agency_name',
'caseworker_name',
'caseworker_email',
'caseworker_phone',
'caseworker_ext',
'is_active',
'agency_approved',
)
class UserSerializerWithToken(serializers.ModelSerializer):
token = serializers.SerializerMethodField()
password = serializers.CharField(write_only=True)
def get_token(self, obj):
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(obj)
token = jwt_encode_handler(payload)
return token
def create(self, validated_data):
password = validated_data.pop('password', None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
class Meta:
model = User
fields = '__all__'
Related
I am using the Django default User model to do user registration. When I was trying to create a user I got this error message. Direct assignment to the forward side of a many-to-many set is prohibited. Use groups.set() instead.
# views.py
from django.contrib.auth.models import User
from rest_framework import viewsets
from app.serializers import UserSerializer
# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
extra_kwargs = {'password': {'write_only': True, 'required': False}}
def create(self, validated_data):
print(validated_data)
user = User.objects.create_user(**validated_data)
return user
# urls.py
from django.urls import path, include
from rest_framework import routers
from app import views
from rest_framework.authtoken.views import obtain_auth_token
router = routers.SimpleRouter()
router.register(r'users', views.UserViewSet)
urlpatterns = [
path('auth/', obtain_auth_token),
]
urlpatterns += router.urls
I only insert the user record, there is no foreign table or many-to-many relationship. Not sure why the system throws this error.
Attached with the postman screenshot.
I've checked the DRF official documentation, have read the below posts and copy-pasted code from some answers to avoid any typo, but I still can't authenticate in my unit tests. I always get a 401 response code.
I have a custom User model that just has a couple of none required fields so far.
Can anyone see any logic issue, or error in the code?
Could the issue originate from having a proper local DB and a testing DB and the authentication mixing both up somehow?
I've had to use self.client.force_authenticate(user=self.user, token=None) to bypass the authentication issue. But that defeats the purpose of the tests.
Checked posts that did not solve the problem:
DRF documentation
SO post 1
SO post 2
SO post 3
So here's my code.
Unit test
from django.test.testcases import SimpleTestCase
from django.urls import reverse, resolve
from rest_framework import status
from rest_framework.test import APITestCase
from rest_framework.authtoken.models import Token
from test_project.models.user import *
from test_project.views import UserViewSet
# from django.contrib.auth.models import User
from test_project.models import *
class UserAPIViewTests(APITestCase):
def setUp(self) -> None:
self.users_list_url = reverse('user-list')
self.users_detail_url = reverse('user-detail', args=[1])
self.user =User.objects.create(
username="admin",
password="admin",
email="test#necktie.com",
first_name="test first name",
last_name="test last name",
is_superuser=True,
is_staff=True,
is_active=True
)
self.token = Token.objects.create(user=user)
self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + self.token.key)
# The testing DB is automatically torn down, no implementation required for those tests
def tearDown(self) -> None:
pass
def test_get_users_authenticated(self):
"""
Test that an authenticated user can get the users' list
"""
response = self.client.get(self.users_list_url)
self.assertEquals(response.status_code, status.HTTP_200_OK)
User model
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import gettext_lazy as _
class User(AbstractUser):
"""auth/login-related fields"""
gender = models.CharField(_('gender'), max_length=50, null=True)
nationality = models.CharField(_('nationality'), max_length=50, null=True)
def __str__(self):
return "{} {}".format(self.first_name, self.last_name)
User View
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import permissions
from ..models.user import User
from ..serializers.user import *
from ..permissions import *
class UserViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
def get_permissions(self):
"""
Method to apply permissions depending on request type (GET, PUT etc.)
"""
if self.request.method == 'GET':
return [permissions.IsAuthenticated(), IsStaff()]
else:
return [permissions.IsAuthenticated(), IsSuperuser()]
User serializers
from rest_framework import serializers
from ..models.user import User
class UserSerializer(serializers.ModelSerializer):
"""
Serializer for all actions on User model
"""
class Meta:
model = User
fields = [
'id',
'username',
'first_name',
'last_name',
'is_staff',
'is_superuser',
'is_active',
'date_joined'
]
Thanks for the help!
I am new with integrating mixpanel to Django backend to track events,As i try to track, it gives me empty brackets anyone with ideas or resources please help me am quite stack
views.py
from django.shortcuts import render
from django.views import View
from rest_framework.generics import ListCreateAPIView
from rest_framework.views import APIView
from rest_framework.response import Response
from .serialize import UserSerializer, TweakSerializer, ChannelSerializer, SubscriberSerializer
from tweaks.models import Tweak
from accounts.models import User
from channels.models import Channel, Subscriber
from mixpanel import Mixpanel
import json
# Create your views here.
mp = Mixpanel('TOKEN')
class userApi(ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
def get(self, request):
queryset = self.get_queryset()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
apiuser=userApi()
point = json.dumps(apiuser.__dict__)
mp.track(point, 'users')
serializers.py
from rest_framework import routers, serializers, viewsets
from django.urls import path, include
from accounts.models import User
from tweaks.models import Tweak
from channels.models import Channel, Subscriber
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = 'username', 'email', 'first_name', 'last_name', 'date_joined'
I created an API with django
What I want to do is to fetch data from my django API and store it in my database.
serializers.py
from rest_framework import serializers, generics
from Usersapi.models import Userdata
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Userdata
fields = '__all__'
viewsets.py
from Usersapi.models import Userdata
from .serializers import UserSerializer
from rest_framework import viewsets
class UserViewSet(viewsets.ModelViewSet):
queryset = Userdata.objects.all()
serializer_class = UserSerializer
main--> urls.py
from django.contrib import admin
from django.urls import include, path
from rest_framework.urlpatterns import format_suffix_patterns
from .router import router
urlpatterns = [
path('admin/', admin.site.urls),
# path('',include('Usersapi.urls')),
path('client/',include('clientside.urls')),
path('api/', include(router.urls))
]
This is where I am trying to retrieve data from API
clientside--> views.py
from django.shortcuts import render
import coreapi
import json
from django.views import generic
import io
from rest_framework.parsers import JSONParser
def home(request):
client = coreapi.Client()
response = client.get('http://127.0.0.1:8000/api/Usersapi/1/')
stream = io.BytesIO(response)
data = JSONParser().parse(stream)
name = data.get("name")
age = data.get("age")
gender = data.get("gender")
user = UserReceived.objects.create( name = name, age= age, gender = gender)
user.save()
return render(request, 'books.html')
This code is not working. How do I retrieve the data from ('http://127.0.0.1:8000/api/Usersapi/1/')
and store it in my models.py i.e database
clientside --> models.py
from django.db import models
class UserReceived(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
gender = models.CharField(max_length=50)
Your problem is that the corapi client already returns an ordered dict.
This will work:
def home(request):
client = coreapi.Client()
data = client.get('http://127.0.0.1:8000/api/usersapi/1/')
name = data.get("name")
age = data.get("age")
gender = data.get("gender")
user = UserReceived.objects.create(name=name, age=age, gender=gender)
user.save()
return HttpResponse(f"OKAY, got and saved user {name}")
I created a minimal working example here:
https://github.com/CarliJoy/MWE_SO_59668515
django rest framework is showing http 202 ok when I set a wrong value and I want to show http 404 on the api django rest framework, when set a wrong value in djangofilterbackend but I don't know how to implement it.
my views.py:
from rest_framework import viewsets
from .models import Producto
from .serializers import ProductoSerializer
from django_filters.rest_framework import DjangoFilterBackend
class ProductoViewSet(viewsets.ModelViewSet):
filter_backends = [DjangoFilterBackend]
filterset_fields = ['Codigo_Producto']
queryset = Producto.objects.all()
serializer_class = ProductoSerializer
my serializers.py:
from .models import Producto
from rest_framework import serializers, viewsets
class ProductoSerializer(serializers.ModelSerializer):
Nombre_Producto = serializers.SerializerMethodField
class Meta:
model = Producto
fields = [
'id',
'Nombre_Producto',
'Codigo_Producto',
'Precio_sugerido',
'stock',
]
def get_Producto_name(self,obj:Producto):
return obj.Producto.get_full_name()
urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from rest_framework import routers
from GestionadorApp.views import ProductoViewSet
# Routers provide an easy way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register('Producto', ProductoViewSet)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('api/', include(router.urls)),
path('admin/', admin.site.urls),
]
The way I found is overriding the filter backend to ensure that the parameters are what I want else raise a error Http404.
to show a solution I had to take part of code from Django Filter Backend
from rest_framework import filters
from django.http import Http404
class ObjektFilterBackend(filters.BaseFilterBackend):
allowed_fields = ['username', 'email']
def filter_queryset(self, request, queryset, view):
flt = {}
for param in request.query_params:
#put your logic here
if request.query_params[param] is None:
raise Http404
for fld in self.allowed_fields:
if param.startswith(fld):
flt[param] = request.query_params[param]
return queryset.filter(**flt)
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = [ObjektFilterBackend]
search_fields = ['username', 'email']
In another hand you may override the get_queryset method to ensure data too.
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = [DjangoFilterBackend]
search_fields = ['username', 'email']
def get_queryset(self):
username = self.request.query_params.get('username', None)
if username is None:
raise http404
return self.queryset
django rest framework filtering