how not to do an action when condition met in Django - django

I have a couple of models named User, Book, Issue. Model Book has a field named remaining which holds the value of the number of available books.
what I want:
When there is zero book available, Issuing a book is closed.
models.py
from django.db import models
from datetime import date, timedelta, datetime
class Book(models.Model):
name = models.CharField(max_length=30)
author_name = models.CharField(max_length=30)
category = models.CharField(max_length=30)
remaining = models.IntegerField()
def __str__(self):
return self.name
class Issue(models.Model):
issue_id = models.CharField(max_length=10)
roll = models.ForeignKey(User, on_delete=models.CASCADE)
book_name = models.ForeignKey(Book, on_delete=models.CASCADE)
issue_date = models.DateField(auto_now=False, auto_now_add=True)
def save(self, *args, **kwargs):
if not self.pk:
super().save(*args, **kwargs)
if self.book_name.remaining > 0:
self.book_name.remaining -= 1
self.book_name.save()
elif self.book_name.remaining == 0:
print('hi')
else:
super().save(*args, **kwargs)
admin.py
from django.contrib import admin
from django.contrib.auth.models import Group
from .models import User, Book, Issue
class BookAdmin(admin.ModelAdmin):
list_display = ('name', 'author_name', 'remaining', 'category')
list_filter = ('category', 'author_name')
search_fields = ('name', 'author_name')
class IssueAdmin(admin.ModelAdmin):
list_display = ('issue_id', 'issue_date', 'return_date', 'fine',)
list_filter = ('issue_date',)
search_fields = ('issue_id',)
admin.site.register(Book, BookAdmin)
admin.site.register(Issue, IssueAdmin)
I want to Implement this in Admin Dashboard
Regards

On the clean function just check to see if the books are available.
And raise validation error if there are not any available.
def clean(self, *args, **kwargs):
from django.core.exceptions import ValidationError
super().clean()
if self.book_name.remaining < 1:
raise ValidationError("No books available")
else:
self.book_name.remaining -= 1
self.book_name.save()

Related

Django Admin is not allowing me to change any user settings after implementing a AbstractUser

Following a video on Youtube I want to creat a website with different Roles for students and teachers. I also would like to save off the School ID in to the user.
Here is what I want to change but when I hit save it does nothing.
I've tried creating custom forms to use for the create and change but it doesn't seem to matter. I feel like I missed typed something in the model.py or I'm missing something. Creating users works like a charm so that's why I'm confused why it wouldn't update a user correctly. I have done a fully custom user class before but shouldn't need to for this simple of change.
In the setting is have this line
AUTH_USER_MODEL = "account_app.User"
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db.models.signals import post_save
from django.dispatch import receiver
class School(models.Model):
name = models.CharField('School Name', max_length=240)
address1 = models.CharField('Address 1', max_length=240)
address2 = models.CharField('Address 2', max_length=240)
city = models.CharField('City', max_length=240)
district = models.CharField('District', max_length=240)
state = models.CharField('State', max_length=2)
zip_code = models.IntegerField('Zip Code')
country =models.CharField('Country', max_length=240)
phone = models.IntegerField('School Phone Number')
time_zone = models.CharField(max_length=50)
def __str__(self):
return f'{self.name}'
class User(AbstractUser):
class Role(models.TextChoices):
ADMIN = "ADMIN", "Admin"
STUDENT = "STUDENT", "Student"
TEACHER = "TEACHER", "Teacher"
base_role = Role.ADMIN
role = models.CharField(max_length=50, choices=Role.choices)
school_id = models.ForeignKey(School,blank=True, null=True, on_delete=models.DO_NOTHING)
def save(self, *args, **kwargs):
if not self.pk:
self.role = self.base_role
return super().save(*args, **kwargs)
class StudentManager(BaseUserManager):
def get_queryset(self, *args, **kwargs):
results = super().get_queryset(*args, **kwargs)
return results.filter(role=User.Role.STUDENT)
class Student(User):
base_role = User.Role.STUDENT
student = StudentManager()
class Meta:
proxy = True
def save(self, *args, **kwargs):
if not self.pk:
self.role = User.role.STUDENT
return super().save(*args, **kwargs)
def welcome(self):
return "Only for students"
class TeacherManager(BaseUserManager):
def get_queryset(self, *args, **kwargs):
results = super().get_queryset(*args, **kwargs)
return results.filter(role=User.Role.TEACHER)
class Teacher(User):
base_role = User.Role.TEACHER
teacher = TeacherManager()
class Meta:
proxy = True
def save(self, *args, **kwargs):
if not self.pk:
self.role = User.role.TEACHER
return super().save(*args, **kwargs)
def welcome(self):
return "Only for teachers"
this is the admin.py
from django.contrib import admin
from .models import User
from .models import Student
from .models import Teacher
admin.site.register(User)
admin.site.register(Teacher)
admin.site.register(Student)
EDIT - Honestly have no clue how I fixed it but I did change my files
admin.py
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
from .forms import UserCreationForm
from .models import School
from .models import UserProfile
"""
*** Used to create users in the Admin
if you didn't do this it would use the default account in django.
"""
class UserCreateForm(UserCreationForm):
class Meta:
model = UserProfile
fields = ('email','first_name')
class AccountsUserAdmin(AuthUserAdmin):
# Displays accounts better on the view
list_display = ('id','username','email', 'first_name', 'last_name', 'role','is_staff')
# Used to search people at top of view
search_fields = ('username','last_name','email')
filter_horizontal = ()
list_filter = ()
add_form: UserCreateForm
## Viewing an and changing existing user
fieldsets = (
(None, {'fields': ('username','password')}),
(('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(('Important dates'), {'fields': ('last_login', 'date_joined')}),
(('Additional info'), {'fields': ('role', 'school_id')}),
)
## Adding a new User
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username','first_name','last_name','email','role','school_id','password1','password2'),}),)
admin.site.register(UserProfile, AccountsUserAdmin)
admin.site.register(School)
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
from .models import UserProfile, School
class RegisterUserForm(UserCreationForm):
ROLE_CHOICES =(
("ADMIN", "Admin"),
("STUDENT", "Student"),
("TEACHER", "Teacher"),)
role = forms.ChoiceField(choices=ROLE_CHOICES, required=True)
school_id = forms.ModelChoiceField(queryset=School.objects.all(), required=False)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name','email', 'role' , 'school_id' , 'password1', 'password2')
class UserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = User
fields = '__all__'
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.dispatch import receiver
from django.db.models.signals import post_save
class School(models.Model):
name = models.CharField('School Name', max_length=240)
address1 = models.CharField('Address 1', max_length=240)
address2 = models.CharField('Address 2', max_length=240)
city = models.CharField('City', max_length=240)
district = models.CharField('District', max_length=240)
state = models.CharField('State', max_length=2)
zip_code = models.IntegerField('Zip Code')
country =models.CharField('Country', max_length=240)
phone = models.IntegerField('School Phone Number')
time_zone = models.CharField(max_length=50)
def __str__(self):
return f'{self.name}'
class UserProfile(AbstractUser):
class Role(models.TextChoices):
ADMIN = "ADMIN", "Admin"
STUDENT = "STUDENT", "Student"
TEACHER = "TEACHER", "Teacher"
role = models.CharField(max_length=50, choices=Role.choices, blank=True, null=True)
school_id = models.ForeignKey(School,blank=True, null=True, on_delete=models.DO_NOTHING)
class UserProfileManagerTeachers(models.Manager):
def get_queryset(self):
return super(UserProfile, self).get_queryset().filter(role="TEACHER")
class UserProfileManagerStudents(models.Manager):
def get_queryset(self):
return super(UserProfile, self).get_queryset().filter(role="STUDENT")
It seems that you changed the default permissions for the Abstracted User Class, So you can try this way to add custom permission for each Model, For ex.:
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
#admin.register(User)
class CustomUserAdmin(UserAdmin):
def has_change_permission(self, request, obj=None):
return True
def has_delete_permission(self, request, obj=None):
return False
Here is the full documentation: Admin Panel Permissions Doc.

How to stop the Post request, if there is already the same data is in the Model

I am trying to stop the instance if the data matches in the DB. But i tried and failed again and again.
My Code:
models.py
class Doctor(models.Model):
"""
Manages data of consulting doctors working in the Hospital
"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=40)
contact = models.IntegerField()
department = models.CharField(max_length=50)
active = models.BooleanField(default=False)
def __str__(self):
return f"{self.user} ({self.department})"
class Patient(models.Model):
"""
Manages data of patient
"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=40)
contact = models.IntegerField()
symptoms = models.CharField(max_length=50)
active = models.BooleanField(default=False)
def __str__(self):
return f"{self.user} ({self.symptoms})"
class Appointment(models.Model):
"""
Manages the appointment details
"""
patient_name = models.ForeignKey(Patient, on_delete=models.CASCADE, related_name='doctor')
doctor_name = models.ForeignKey(Doctor, on_delete=models.CASCADE, related_name='patient')
appointment_date = models.DateTimeField()
active = models.BooleanField(default=False)
def __str__(self):
return str(self.patient_name) + " has appointment with " + str(self.doctor_name)
serializers.py
from rest_framework import serializers
from api.models import Patient, Doctor, Appointment
class AppointmentSerializer(serializers.ModelSerializer):
"""
Appointment serializer class
"""
class Meta:
model = Appointment
fields = "__all__"
class DoctorSerializer(serializers.ModelSerializer):
"""
Doctor serializer class
"""
user = serializers.StringRelatedField(read_only=True)
patient = AppointmentSerializer(many=True, read_only=True)
class Meta:
model = Doctor
fields = "__all__"
class PatientSerializer(serializers.ModelSerializer):
"""
Patient serializer class
"""
user = serializers.StringRelatedField(read_only=True)
doctor = AppointmentSerializer(many=True, read_only=True)
class Meta:
model = Patient
fields = "__all__"
views.py
from django.shortcuts import render
from rest_framework.exceptions import ValidationError
from rest_framework.response import Response
from rest_framework import status, viewsets
from rest_framework.views import APIView
from api.models import Doctor, Patient, Appointment
from api.serializers import DoctorSerializer, PatientSerializer, AppointmentSerializer
from rest_framework import generics
from rest_framework.decorators import action
# Create your views here.
class DoctorAPI(generics.ListAPIView):
"""
Doctor working in hospitals list
"""
queryset = Doctor.objects.all()
serializer_class = DoctorSerializer
class PatientAPI(generics.ListAPIView):
"""
Patient visiting in hospital list
"""
queryset = Patient.objects.all()
serializer_class = PatientSerializer
class DoctorDetailAPI(generics.ListAPIView):
serializer_class = DoctorSerializer
def get_queryset(self):
pk = self.kwargs['pk']
return Doctor.objects.filter(patient=pk)
class PatientDetailAPI(generics.ListAPIView):
serializer_class = PatientSerializer
def get_queryset(self):
pk = self.kwargs['pk']
return Patient.objects.filter(doctor=pk)
class AppointmentDetailAPI(APIView):
def get(self, request):
appointment = Appointment.objects.all()
serializer = AppointmentSerializer(appointment, many=True)
return Response(serializer.data)
def post(self, request):
serializer = AppointmentSerializer(data=request.data)
patient_name = Patient.objects.all()
doctor_name = Doctor.objects.all()
# print(serializer)
if serializer.is_valid():
appoint_data = Appointment.objects.filter(patient_name=patient_name)
print(appoint_data)
class AppointmentCreateAPI(generics.RetrieveUpdateDestroyAPIView):
queryset = Appointment.objects.all()
serializer_class = AppointmentSerializer
My task:
--> TO Resitrict the user to make appointment if there is already an appoinment is schedule to the Doctor.
You can also add a validation in the serializer to check if an existing appointment already exists like this:
class AppointmentSerializer(serializers.ModelSerializer):
...
def validate(self, attrs):
if not self.instance: # I'm creating an appointment
if Appointment.objects.filter(
doctor_name=attrs['doctor_name'],
appointment_date=attrs['appointment_date'],
active=True,
).exists():
raise serializers.ValidationError(
f'Appointment already exists for {attrs['doctor_name']}'
)
You have to override post method in LISTAPIVIEW and get data which you are going to filter before saving. For example;
class DoctorAPI(generics.ListAPIView):
queryset = Doctor.objects.all()
serializer_class = DoctorSerializer
def post(self,request,*args,**kwargs):
data=request.data.get("the name of input")
instance = Doctor.objects.filter(the field name which you are going
to compare).exist()
if instance:
return Response({"error":"This data is in database"})

positiveintegerfield's choice appears on frontende, but its key is visible. value does not appear

I'm developing a backend with the django rest api. I have the same problem with my advertise model except for my user model. My choice linked to positiveintegerfielder is not displayed in restframework for post method.I'm doing an action like in serializer.py, whose photo I shared to display. When I do this, it is not displayed in restframework and I cannot use the post method.
Thank you very much in advance
serializer.py##
from user.models import User
from rest_auth.serializers import *
class ChoicesSerializerField(serializers.SerializerMethodField):
def __init__(self, choices, **kwargs):
self._choices = choices
super(ChoicesSerializerField, self).__init__(**kwargs)
def to_representation(self, value):
# sample: 'get_XXXX_display'
method_name = 'get_{field_name}_display'.format(field_name=self.field_name)
# retrieve instance method
method = getattr(value, method_name)
# finally use instance method to return result of get_XXXX_display()
return method()
def to_internal_value(self, data):
return getattr(self._choices, data)
class UserSerializer(serializers.ModelSerializer):
gender = ChoicesSerializerField(choices=User.gender)
class Meta:
model = User
fields = ('gender',)
view.py##
from rest_framework.viewsets import ModelViewSet
from user.serializer import UserSerializer
from .models import *
from rest_framework import permissions
from rest_framework.generics import CreateAPIView, ListAPIView, GenericAPIView, get_object_or_404
class CreateUserView(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
User model##
from django.contrib.auth.models import AbstractUser
from django.core.validators import RegexValidator
from django.db import models
from user.choices.choice import MartialStatusChoices,
EducationalStatusChoices, ProfessionChoices, GenderChoices
class Interest(models.Model):
name = models.CharField(max_length=50, null=True, blank=True )
def __str__(self):
return self.name
class User(AbstractUser):
birthday = models.DateField(null=True)
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$')
phone_number = models.CharField(validators=[phone_regex],
max_length=17, blank=True)
gender =
models.PositiveIntegerField(null=True,choices=GenderChoices.CHOICES)
martial_status = models.PositiveIntegerField(null=True,
choices=MartialStatusChoices.CHOICES)
educational_status = models.PositiveIntegerField(null=True,
choices=EducationalStatusChoices.CHOICES)
profession = models.PositiveIntegerField(null=True,
choices=ProfessionChoices.CHOICES)
interests = models.ManyToManyField(to=Interest,null=True,
blank=True)
class Meta:
verbose_name= "User"
You should try serializers.ChoiceField.
from user.choices.choice import GenderChoices
class UserSerializer(serializers.ModelSerializer):
gender = serializers.ChoiceField(choices=GenderChoices.CHOICES)
class Meta:
model = User
fields = ('gender',)
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
class UserView(APIView):
permission_classes = (permissions.AllowAny,) # remove this if you're using authentication
def get(self, request):
serializer = UserSerializer(instance=request.user)
serializer.is_valid(raise_exception=True)
return Response(serializer.data)
def post(self, request):
serializer = UserSerializer(instance=request.user, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response()

Nested AbstractUser model failing during update operation with "null value in column "user_id" violates not-null constraint"

I am creating nested abstract user "Teacher from User", My use case is "Create User" -> "Then make user to teacher"
I am able to create user and make the user to Teacher, but I am unable to update the field, In below case want to update "teacher_cost"
Model.py
from django.contrib.postgres.fields import JSONField
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
uid = models.AutoField(verbose_name='ID',
serialize=False,
auto_created=True,
primary_key=True)
TEACHER = "Teacher"
STUDENT = "Student"
user_type = models.CharField(max_length=30, default=STUDENT)
contact_number = models.CharField(max_length=20, null=True, blank=True)
address = models.TextField(null=True, blank=True)
photo = models.ImageField(null=True, blank=True)
image = models.ImageField(upload_to='users/',
default='default/avatar.png')
approved = models.BooleanField(default=True)
def save(self, *args, **kwargs):
if self.user_type == User.TEACHER and self._state.adding:
self.approved = False
super().save(*args, **kwargs)
#property
def dishes(self):
ret = self.teacher.dish_set.all()
if ret:
return ret
else:
return ''
class Teacher(models.Model):
uid = models.AutoField(verbose_name='ID',
serialize=False,
auto_created=True,
primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(null=True, blank=True)
teacher_cost = models.DecimalField(
max_digits=5, decimal_places=2, null=True, blank=True)
languages = models.CharField(
max_length=50, null=True, blank=True)
address = models.TextField(null=True, blank=True)
def __str__(self):
return self.user.username
Serializer.py
from rest_framework import serializers, exceptions
from django.contrib.auth.forms import PasswordResetForm
from django.conf import settings
from .models import *
from rest_auth import serializers as rest_auth_serializers
from django.utils.translation import ugettext_lazy as _
class UserDetailsSerializer(serializers.ModelSerializer):
"""
User model w/o password
"""
class Meta:
model = User
fields = ('pk', 'username', 'email',
'first_name', 'last_name', 'contact_number', 'user_type', 'photo', 'address')
read_only_fields = ('email', )
class UserTeacher(serializers.ModelSerializer):
class Meta:
model = User
fields = ('teacher',)
class TeacherDetails(serializers.ModelSerializer):
class Meta:
model = Teacher
fields = '__all__'
class TeacherFullDetails(serializers.ModelSerializer):
user_id = serializers.CharField(source='user.uid')
username = serializers.CharField(source='user.username')
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
photo = serializers.ImageField(
source='user.photo', max_length=None, use_url=True)
class Meta:
model = Teacher
fields = ('user_id', 'username', 'first_name', 'last_name', 'photo', 'teacher_cost')
class TeacherBriefDetails(serializers.ModelSerializer):
uid = serializers.CharField(source='user.uid')
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
class Meta:
model = Teacher
fields = ('uid', 'first_name', 'last_name',)
class TeacherProfileDetails(serializers.ModelSerializer):
contact_number = serializers.CharField(source='user.contact_number', required=False)
first_name = serializers.CharField(source='user.first_name', required=False)
last_name = serializers.CharField(source='user.last_name', required=False)
email = serializers.CharField(source='user.email', required=False)
photo = serializers.ImageField(
source='user.photo', max_length=None, use_url=True, required=False)
user = UserDetailsSerializer(read_only=True)
teacher_cost = serializers.CharField()
class Meta:
model = Teacher
fields = ('user', 'first_name', 'last_name', 'contact_number', 'email', 'photo',
'bio', 'teacher_cost')
class TeacherProfileSerializer(serializers.ModelSerializer):
user = UserDetailsSerializer()
class Meta:
model = Teacher
fields = ("bio", "teacher_cost", "user")
view.py
from rest_framework import generics, viewsets, status, permissions
from .models import *
from .serializers import *
from rest_framework.response import Response
from django.db.models import Q
from .permissions import IsAuthenticatedAndOwner, IsTeacher
from django.shortcuts import get_object_or_404
from django.utils.datastructures import MultiValueDictKeyError
from rest_framework.views import APIView
import json
import logging
class TeacherProfile(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
lookup_field = "username"
def get_object(self):
if self.action == "partial_update":
return get_object_or_404(User, username=self.kwargs['username'])
return get_object_or_404(Teacher, user__username=self.kwargs['username'])
def get_serializer_class(self):
if self.action == "partial_update":
return UserDetailsSerializer
else:
return TeacherProfileDetails
class TeacherListCreateAPIView(APIView):
logger = logging.getLogger(__name__)
def get(self, request, *args, **kwargs):
teacherList = Teacher.objects.filter(user__username=kwargs["username"])
self.logger.info("Printing teacher list")
self.logger.info(teacherList)
serializers = TeacherProfileDetails(teacherList, many=True)
return Response(serializers.data)
def post(self, request, *args, **kwargs):
self.logger.info("-----------------put ------------")
serializers = TeacherProfileDetails(data=request.data)
# photo = request.FILES['file']
if serializers.is_valid():
serializers.save()
return Response(serializers.data, status=status.HTTP_201_CREATED)
return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)
def put(self, request, *args, **kwargs):
serializers = TeacherProfileDetails(data=request.data, many=True)
self.logger.info(serializers)
if serializers.is_valid():
serializers.save()
return Response(serializers.data, status=status.HTTP_201_CREATED)
return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)
# /user/<str:username>/profile
class UserProfile(viewsets.ModelViewSet):
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
lookup_field = "username"
def get_object(self):
return get_object_or_404(User, username=self.kwargs['username'])
def get_serializer_class(self):
return UserDetailsSerializer
urls.py
from django.urls import path
from .views import *
urlpatterns = [
path('teacher/<str:username>/profile',
TeacherProfile.as_view({'get': 'retrieve', 'delete': 'destroy', 'patch': 'partial_update'})),
path('teacherlist/<str:username>/',
TeacherListCreateAPIView.as_view(), name="teacher-list"),
]
Getting below error while calling post command to update the user profile
post
http://localhost:8002/api/v1/teacherlist/rayees/
Form json data
{
"teacher_cost": "25.00"
}
Getting below error
IntegrityError at /api/v1/teacherlist/rayees/
null value in column "user_id" violates not-null constraint
DETAIL: Failing row contains (2, null, 25.00, null, null, null).
Request Method: POST
Request URL: http://localhost:8002/api/v1/teacherlist/rayees/
Django Version: 2.2.4
since in model Teacher user is required fields, and you are sending the post request, it will create the new teacher with that user.If you want create new teacher then you should use the post, for that you need the user
if you want update the details of the user you can use patch method, checkout the put method code
class TeacherListCreateAPIView(APIView):
logger = logging.getLogger(__name__)
def get(self, request, *args, **kwargs):
teacherList = Teacher.objects.filter(user__username=kwargs["username"])
self.logger.info("Printing teacher list")
self.logger.info(teacherList)
serializers = TeacherProfileDetails(teacherList, many=True)
return Response(serializers.data)
def post(self, request, *args, **kwargs):
""" creating new user """
serializers = TeacherProfileDetails(data=request.data)
# photo = request.FILES['file']
if serializers.is_valid():
serializer.validated_data['user'] = User.objects.filter(username=kwarsg['username'])
serializers.save()
return Response(serializers.data, status=status.HTTP_201_CREATED)
return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, *args, **kwargs):
teacher = TeacherProfileDetails.objects.get(user__username=kwargs['username'])
serializers = TeacherProfileDetails(data=request.data, instance=teacher)
self.logger.info(serializers)
if serializers.is_valid():
serializers.save()
return Response(serializers.data, status=status.HTTP_201_CREATED)
return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)
now you can make patch request on http://localhost:8002/api/v1/teacherlist/rayees/
with given data it will update the record.

How to bined a detailview field to a form field in django and save into database

I am building this simple system for online voting, where people can vote but will have to pay for their vote cast.My current challenge is how to bined a selected candidate on a page and allowing voters to enter number of votes they went to cast for that candidate on the same page
I have tried using SingleObjectMixin but am having problem saving the form in database.
And also how can i prepopulate the select candidate to a model field name Nominee
model.py
class Award(models.Model):
STATUS_PUBLISHED = (
('Closed', 'Closed'),
('Opened', 'Opened'),
)
slug = models.SlugField(max_length=150)
name = models.CharField(max_length=100)
date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='award_images')
status = models.CharField(max_length=20, choices=STATUS_PUBLISHED, default='Closed')
def __str__(self):
return self.name
class Category(models.Model):
Award = models.ForeignKey(Award, on_delete=models.CASCADE)
category = models.CharField(max_length=100,)
slug = models.SlugField(max_length=150)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.category
class Nomination(models.Model):
Fullname = models.CharField(max_length=120)
Category = models.ForeignKey(Category, on_delete=models.CASCADE)
votes = models.IntegerField(default=0)
date = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=150)
image = models.ImageField(upload_to='nominations_images')
def __str__(self):
return self.Fullname
class VoteAmount(models.Model):
Nominee = models.ForeignKey(Nomination, on_delete=models.CASCADE)
votes_amount = models.IntegerField(default=0)
def __str__(self):
return self.votes_amount
views.py
from django.views.generic import ListView, DetailView, CreateView
from .models import Award, Category, Nomination, VoteAmount
from .forms import VoteAmountForm
from django.urls import reverse
from django.http import HttpResponseForbidden
from django.views.generic import FormView
from django.views.generic.detail import SingleObjectMixin
from django.views import View
class AwardView(ListView):
template_name = 'award.html'
context_object_name = 'award_list'
queryset = Award.objects.filter(status='Opened').order_by('-date')
class CategoryView(DetailView):
model = Award
template_name = 'category.html'
class NominationView(DetailView):
model = Category
template_name = 'nomination.html'
class VoteAmountView(DetailView):
model = Nomination
template_name = 'voteamount.html'
def get_context_data(self, **kwargs):
context = super(VoteAmountView, self).get_context_data(**kwargs)
context['form'] = VoteAmountForm()
return context
class AmountView(SingleObjectMixin, FormView):
template_name = 'voteamount.html'
form_class = VoteAmountForm
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
return super(AmountView, self).post(request, *args, **kwargs)
def get_success_url(self):
return reverse('results', kwargs={'pk': self.object.pk})
class AuthorDetail(View):
def get(self, request, *args, **kwargs):
view = VoteAmountView.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = AmountView.as_view()
return view(request, *args, **kwargs)
class PaymentView(DetailView):
model = VoteAmount
template_name = 'PaymentView.html'
form.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import VoteAmount
class VoteAmountForm(forms.ModelForm):
class Meta:
model = VoteAmount
fields = ('Nominee', 'votes_amount')
ImproperlyConfigured at /results/fiifi-quansa
AmountView is missing a QuerySet. Define AmountView.model, AmountView.queryset, or override AmountView.get_queryset().
all i went to do is show the selected condidate as a nominee field for model VoteAmount and enter my number of votes
As the error said:
AmountView is missing a QuerySet. Define AmountView.model, AmountView.queryset, or override AmountView.get_queryset().
Means, you are using SingleObjectMixin, you need to provide a queryset/model/ override get_queryset() method in the class. like this:
class AmountView(SingleObjectMixin, FormView):
template_name = 'voteamount.html'
form_class = VoteAmountForm
queryset = Nomination.objects.all()
Also, you need to override get_form_kwargs() method to load the the initial nominee data.
class AmountView(SingleObjectMixin, FormView):
template_name = 'voteamount.html'
form_class = VoteAmountForm
queryset = Nomination.objects.all()
def get_form_kwargs(self, *args, **kwargs):
form_kwargs = super().get_form_kwargs(*args, **kwargs)
form_kwargs['nominee'] = self.get_object()
return form_kwargs
And override VoteAmountForm as well to limit the choices:
class VoteAmountForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
nominee = kwargs.pop('nominee')
super().__init__(*args, **kwargs)
self.fields['Nominee'].queryset = Nominee.objects.filter(pk=nominee.pk) # <-- Please use snake_case when defining model field names(as per pep8 style guide)
self.initial['Nominee'] = nominee
class Meta:
model = VoteAmount
fields = ('Nominee', 'votes_amount')