Objects not deleting - django

I have several ViewSets.They have one serializer and model.
For example - ViewSet "Posts" and "Favorites". If I use DELETE request on Post object, he is deleted from "Posts", but in Favorites, I can see them. BUT, every object has a "URL" field. So, if some object from "Posts" will be deleted, then in "Favorites" I will see it and if I go to the link from the "URL" field, then I get "404 not found".
Why does it happen?
Model:
class Post(models.Model):
name = models.CharField(verbose_name='name', db_index=True, max_length=64)
city = models.CharField(verbose_name='city', db_index=True, max_length=64)
created = models.DateTimeField(auto_now_add=True)
end_time = models.DateTimeField(default=next_month, blank=True, editable=False)
description = models.CharField(verbose_name='description', db_index=True, max_length=64)
isFan = models.BooleanField(null=True)
main_image = models.ImageField(upload_to=get_auth_dir_path, null=True, max_length=255)
first_image = models.ImageField(upload_to=get_auth_dir_path, null=True, max_length=255)
second_image = models.ImageField(upload_to=get_auth_dir_path, null=True, max_length=255)
ViewSets:
class PostViewSet(LikedMixin, viewsets.ModelViewSet):
queryset = Post.objects.is_actual().order_by('-created')
serializer_class = PostSerializer
authentication_classes = (TokenAuthentication, SessionAuthentication, )
filter_backends = (DjangoFilterBackend, )
filterset_fields = (...)
def perform_create(self, serializer):
serializer.save(author=self.request.user)
class ClosedPostViewSet(LikedMixin, viewsets.ModelViewSet):
queryset = Post.objects.is_not_actual().order_by('-end_time')
serializer_class = PostSerializer
authentication_classes = (TokenAuthentication, SessionAuthentication,)
filter_backends = (DjangoFilterBackend,)
filterset_fields = (...)
def perform_create(self, serializer):
serializer.save(author=self.request.user)
class SearchViewSet(LikedMixin, viewsets.ModelViewSet):
pagination_class = None
queryset = Post.objects.is_actual()
serializer_class = PostSerializer
authentication_classes = (TokenAuthentication, SessionAuthentication, )
filter_backends = (DjangoFilterBackend, )
filterset_fields = (...)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
result_list = list(queryset.values('city').annotate(count=Count('city')))
return Response(result_list)
def perform_create(self, serializer):
serializer.save(author=self.request.user)

Related

Cannot assign "<django.contrib.auth.models.AnonymousUser object at 0x000001D4CBCD96A0>": "Album.owner" must be a "User" instance

I don't know why I have this error, I didn't have it befor, I'm sure that I'm logged in before trying call the api, please find below the code :
views.py
class AlbumCreate(generics.CreateAPIView):
serializer_class = AlbumsSerializer
def perform_create(self, serializer):
owner2 = self.request.user
serializer.save(owner=owner2)
class AlbumList(generics.ListAPIView):
permission_classes = [IsAuthenticated]
queryset = Album.objects.all()
serializer_class = AlbumsSerializer
class AlbumDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Album.objects.all()
serializer_class = AlbumsSerializer
Serializer
class AlbumsSerializer(serializers.ModelSerializer):
owner = serializers.StringRelatedField(read_only=True)
class Meta:
model = Album
fields = "__all__"
models
def upload_path(instance, filname):
return '/'.join(['covers', str(instance.title), filname])
class Album(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=30)
cover = models.IntegerField(default=0)
photos_number = models.IntegerField(default=0)
image = models.ImageField(blank=True, null=True, upload_to=upload_path)
def __str__(self):
return self.title

How to return articles from followed users only?

Right now i am successfully able to return every article without issue.
But what i want to do is this:
I want to return the articles,only followed by the current authenticated user. How can i do it?
models.py
class User(AbstractUser,PermissionsMixin):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
email = models.CharField(max_length=255,unique=True)
username =models.CharField(max_length=80,unique=True,default='undefinedusername')
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
class Article(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author = models.ForeignKey(User,on_delete=models.CASCADE,related_name='articles')
caption = models.CharField(max_length=250)
class UserFollow(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author = models.ForeignKey(User,on_delete=models.CASCADE,related_name='following')
profile = models.ForeignKey(User,on_delete=models.CASCADE,related_name='followers')
serializers.py
class UserSerializer(DynamicFieldsMixin,serializers.ModelSerializer):
userfollowers_set = UserFollowSerializer(source='followers',required=False,many=True)
userfollowing_set = UserFollowSerializer(source='following',required=False,many=True)
class Meta:
model = User
fields = ('id','email','username','userfollowing_set','userfollowers_set')
views.py
class ArticleViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
queryset = Article.objects.all().order_by('-timestamp')
serializer_class = ArticleSerializer
Error 1:
class FollowedAuthorFilterBackend(filters.BaseFilterBackend):
NameError: name 'filters' is not defined
You can filter with:
class ArticleViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
queryset = Article.objects.all().order_by('-timestamp')
serializer_class = ArticleSerializer
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).filter(
author__following__author=request.user
)
We can also move the filtering logic into a FilterBackend:
class FollowedAuthorFilterBackend(filters.BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
return queryset.filter(
author__following__profile=request.user
)
Then we can plug in this FollowedAuthorFilterBackend where we want to filter this, so we can rewrite our ArticleViewSet to:
class ArticleViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
queryset = Article.objects.all().order_by('-timestamp')
serializer_class = ArticleSerializer
filter_backends = [FollowedAuthorFilterBackend]
# no get_queryset

Django RF - nested serializers with ModelViewSet

I have a problem with nested serializers.
In Shell everything works, but when I make an HTTP request i'ts always an error like "field required".
Models:
class Product(models.Model):
index = models.CharField(max_length=12, unique=True, db_index=True)
quantity = models.PositiveIntegerField(default=0)
def __str__(self):
return self.index
class Name(models.Model):
product = models.ForeignKey(Product, related_name='names', on_delete=models.CASCADE, null=True)
language = models.CharField(max_length=50, default="name_pl")
title = models.CharField(max_length=300, blank=True, null=True)
def __str__(self):
return self.language
Serializers:
class ProductSerializer(serializers.ModelSerializer):
names = NameSerializer(many=True)
class Meta:
model = Product
fields = ["index", "quantity", "names"]
def create(self, validated_data):
names = validated_data.pop('names')
product = Product.objects.create(**validated_data)
for name in names:
Name.objects.create(product=product, **name)
return product
views:
class NameView(viewsets.ModelViewSet):
queryset = Name.objects.all()
serializer_class = NameSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ('id',)
search_fields = ['id']
class ProductView(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ('id',)
search_fields = ['id']
permission_classes = (CustomDjangoModelPermissions,)
I'm trying to POST data:
data = {
"index": "11111",
"quantity": 1213,
"names": [
{"language": "DE","title": "GER"},
{"language": "CZ","title": "CZZ"}
]
}
RESPOND:
names field required
I've tried to override create in view, to "look" whats wrong:
def create(self, request):
data = request.data
serializer = ProductSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(request.data, status=400)
Then I get:
{'index': '11111', 'quantity': '1213', 'names': 'title'}
So it can't send all of data, so it can't validate.
Need help, pls ;)
Problem solved:
Just forget to add in request:
data = json.dumps(data)

how to fix django Model instance

error messages
ValueError: Cannot assign "<User: user0#example.com>": "Diagnoses.owner" must be a "Patient" instance
i get the above error when i try to create either a new card or diagnoses.
The card and diagnoses are meant to be an instance of the patient, just like the way a patient has a card and also diagnoses. The patient class has a foregin key referencing the User.
Here is the code
views.py
from django.shortcuts import render
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from .serializers import PatientsSerializer, PatientsCardSerializer, PatientsDiagnosesSerializer
from .models import Patient, Card, Diagnoses
from rest_framework import permissions
from .permissions import IsOwner
# Patient Views
class PatientListAPIView(ListCreateAPIView):
serializer_class = PatientsSerializer
queryset = Patient.objects.all()
permission_classes = (permissions.IsAuthenticated, IsOwner,)
def perform_create(self, serializer):
return serializer.save(owner=self.request.user)
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
class PatientDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = PatientsSerializer
permission_classes = (permissions.IsAuthenticated, IsOwner,)
queryset = Patient.objects.all()
lookup_field = "id"
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
class PatientCardListAPIView(ListCreateAPIView):
serializer_class = PatientsCardSerializer
queryset = Card.objects.all()
permission_classes = (permissions.IsAuthenticated,)
def perform_create(self, serializer):
return serializer.save(owner=self.request.user)
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
class PatientCardDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = PatientsCardSerializer
permission_classes = (permissions.IsAuthenticated, IsOwner,)
queryset = Card.objects.all()
lookup_field = "id"
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
class PatientDiagnosesListAPIView(ListCreateAPIView):
serializer_class = PatientsDiagnosesSerializer
queryset = Diagnoses.objects.all()
permission_classes = (permissions.IsAuthenticated,)
def perform_create(self, serializer):
return serializer.save(owner=self.request.user)
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
class PatientDiagnosesDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = PatientsDiagnosesSerializer
permission_classes = (permissions.IsAuthenticated, IsOwner,)
queryset = Diagnoses.objects.all()
lookup_field = "id"
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
Models.py
class Patient(models.Model):
name = models.CharField(max_length=255, null=True)
country = models.CharField(max_length=255, null=True)
state = models.CharField(max_length=255, null=True)
phone = models.CharField(max_length=255, null=True)
email = models.CharField(max_length=255, null=True)
owner = models.ForeignKey(to=User, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Card(models.Model):
name = models.CharField(max_length=255, null=True)
card_number = models.CharField(max_length=255, null=True)
owner = models.OneToOneField(Patient, null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return (self.patient.name)+"'s card"
class Diagnoses(models.Model):
sickness = models.CharField(max_length=255, null=True)
note = models.TextField(max_length=255, null=True)
owner = models.ForeignKey(Patient, null=True, on_delete=models.SET_NULL)
def __str__(self):
return (self.patient.name)+"'s diagnoses"
So far, self.request.user is a User Object. You cannot save it to the API or save to the model because of that. And for clarity, it's not a Patient Object.
Based on your situation, I would queue the Patient object with the User object (if this was a one-way reference object), and put that in the argument and do the save() method.
class PatientCardListAPIView(ListCreateAPIView):
serializer_class = PatientsCardSerializer
queryset = Card.objects.all()
permission_classes = (permissions.IsAuthenticated,)
def perform_create(self, serializer):
getPatientFromUser = Patient.objects.get(owner=self.request.user)
# getPatientFromUser returns `Patient` Instance. So you could bind it in `Card` Model.
return serializer.save(owner=getPatientFromUser)
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
Notes:
This is a solution for a one-way reference. (User being referred to as Patient)
If you have a cross-reference relationship between User and Patience (where User and Patience has a ForeignKey on each other), then declare your User Model.
The solution queries the Patient from User. As User is incompatible with that Foreign Object.

Django_filter on an apiview

I have been trying to use the Django_filter on an APIView, but it just does not work. I am trying to implement a filter search, on some fields on a model.
below is how the model is set up
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
name = models.CharField(max_length=250)
picture = models.TextField(null=True, blank=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=255, unique=True, blank=True)
class Skill(models.Model):
name = models.CharField(max_length=60)
subcategory = models.CharField(max_length=60, blank=True, null=True)
created_on = models.DateTimeField(auto_now=True)
updated_on = models.DateTimeField(auto_now_add=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.DO_NOTHING)
the views.py set up is also as shown below
from django_filters import rest_framework as filters
class UserFilter(filters.FilterSet):
email = filters.CharFilter(lookup_expr='icontains')
name = filters.CharFilter(lookup_expr='icontains')
profiles__skills = filters.CharFilter(lookup_expr='icontains')
class Meta:
model = User
fields = ('email', 'name', 'profiles__skills')
class ListUsersView(APIView, MyPaginationMixin):
'''
Gets all the users in the database
'''
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [AllowAny]
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
filterset_class = UserFilter
def get(self, request):
page = self.paginate_queryset(self.queryset)
if page is not None:
serializer_context = {"request": request}
serializer = self.serializer_class(page, context=serializer_context, many=True)
return self.get_paginated_response(serializer.data)
and finally my serializer.py
class UserSerializer(serializers.ModelSerializer):
slug = serializers.SlugField(read_only=True)
class Meta:
model = User
fields = ('email', 'name', 'slug', 'picture')
read_only_fields = ('email', 'name', 'slug',)
my urls.py
path('users/', qv.ListUsersView.as_view(), name='list-users'),
this is how my result looks like
please, how can I get the Django filter to work on the APIView
It seems you are trying to get the similar or exact behavior of DRF ListAPIView by using APIView. I would suggest using ListAPIView over APIView in your case.
from rest_framework import generics
from django_filters import rest_framework as filters
class ListUsersView(generics.ListAPIView):
'''
Gets all the users in the database
'''
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [AllowAny]
filterset_class = UserFilter
filter_backends = (filters.backends.DjangoFilterBackend,)
To add filtering capability in APIView,
class MyAPIViewKlass(APIView):
filter_backends = (filters.DjangoFilterBackend,)
def filter_queryset(self, queryset):
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
def get(self, request, *args, **kwargs):
base_qs = MyModel.objects.all()
filtered_qs = self.filter_queryset(base_qs)
serializer = MySerializer(filtered_qs, many=True)
return Response(serializer.data)