Count number of students in a school in Django - python

class School(models.Model):
name = models.CharField()
city = models.CharField()
street = models.CharField()
class Student(models.Model):
school_id = models.ForeignKey(School, on_delete=models.CASCADE)
first_name = models.CharField()
last_name = models.CharField()
I want to join two classes School and Student and get the number of students in these school, So I wrote this code in my serializers. but I got no resulte of number of students, only the two classes joined. Can someone help me?
serializers.py
from django.db.models import Count
class SchoolSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = School
fields = ['name']
class StudentSerializer(serializers.HyperlinkedModelSerializer):
school = SchoolSerializer()
school.objects.annotate(num_of_students=Count('student'))
class Meta:
model = Student
fields = ['first_name', 'last_name', 'school']
views.py
In my views I wrote the following code:
class StudentViewSet(viewsets.ModelViewSet):
serializer_class = StudentSerializer
queryset = Student.objects.all()

in your models.py add two method:
class School(models.Model):
name = models.CharField(max_length=100, null=False, blank=False)
city = models.CharField(max_length=100, null=False, blank=False)
street = models.CharField(max_length=100, null=False, blank=False)
def count_of_students(self):
return Student.objects.filter(school_id=self).count()
def students_in_school(self):
return list(Student.objects.filter(school_id=self))
def __str__(self):
return f"{self.city}->{self.street}->{self.name}"
class Student(models.Model):
school_id = models.ForeignKey(School, on_delete=models.CASCADE)
first_name = models.CharField(max_length=100, null=False, blank=False)
last_name = models.CharField(max_length=100, null=False, blank=False)
def __str__(self):
return f"{self.first_name} {self.last_name}"
and in your serializers.py
class StudentSerializer(serializers.Serializer):
first_name = serializers.CharField(max_length=100)
last_name = serializers.CharField(max_length=100)
class SchoolSerializer(serializers.Serializer):
count_of_students = serializers.IntegerField()
name = serializers.CharField(max_length=100)
students_in_school = StudentSerializer(many=True)
and in your views.py:
def get_school(request, id):
school = School.objects.get(pk=id)
serilizer = SchoolSerializer(school)
json = rest_framework.renderers.JSONRenderer().render(serilizer.data)
from django.http import HttpResponse
return HttpResponse(json, content_type='application/json')
and in your urls.py
path('schools/<int:id>',get_school)
as example data you can call enter link description here
and here is sample output:
{
"count_of_students":9,
"name":"S1",
"students_in_school":[
{
"first_name":"surname_1",
"last_name":"surname_{i}"
},
{
"first_name":"surname_2",
"last_name":"surname_{i}"
},
{
"first_name":"surname_3",
"last_name":"surname_{i}"
},
{
"first_name":"surname_4",
"last_name":"surname_{i}"
},
{
"first_name":"surname_5",
"last_name":"surname_{i}"
},
{
"first_name":"surname_6",
"last_name":"surname_{i}"
},
{
"first_name":"surname_7",
"last_name":"surname_{i}"
},
{
"first_name":"surname_8",
"last_name":"surname_{i}"
},
{
"first_name":"surname_9",
"last_name":"surname_{i}"
}
]
}

Related

Django(DRF) Null field in client address

I'm trying to save client details .
below is models.py:
class Address(models.Model):
street_address_line_1 = models.CharField(max_length=50)
street_address_line_2 = models.CharField(max_length=50)
city = models.CharField(max_length=50)
state = models.CharField(max_length=50)
zip = models.IntegerField()
country = models.CharField(max_length=50)
class Client(models.Model):
primary_contact_first_name = models.CharField(max_length=50)
primary_contact_last_name = models.CharField(max_length=50)
primary_contact_email = models.CharField(max_length=50, unique=True)
primary_contact_phone_number = models.CharField(max_length=50, unique=True)
primary_contact_phone_type = models.CharField(max_length=50)
secondary_contact_first_name = models.CharField(max_length=50)
secondary_contact_last_name = models.CharField(max_length=50)
secondary_contact_email = models.CharField(max_length=50, unique=True)
secondary_contact_phone_number = models.CharField(max_length=50, unique=True)
secondary_contact_phone_type = models.CharField(max_length=50)
client_address = models.ForeignKey(Address,related_name="client_address",on_delete=models.CASCADE, null=True, blank=False)
def __str__(self):
return self.primary_contact_email
and views.py:
#api_view(["POST"])
def createClientView(request):
if request.method == "POST":
serializer = ClientSerializer(data=request.data, many=False)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_200_OK)
error = Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
return error
and serializers.py:
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = [
"street_address_line_1",
"street_address_line_2",
"city",
"state",
"zip",
"country",
]
class ClientSerializer(serializers.ModelSerializer):
address = AddressSerializer(source="addresss",read_only=True)
class Meta:
model = Client
fields = [
"primary_contact_first_name",
"primary_contact_last_name",
"primary_contact_email",
"primary_contact_phone_number",
"primary_contact_phone_type",
"secondary_contact_first_name",
"secondary_contact_last_name",
"secondary_contact_email",
"secondary_contact_phone_number",
"secondary_contact_phone_type",
"address",
]
def create(self,validated_data):
address_data=validated_data.pop("address")
client=Client.objects.create(**validated_data)
Address.objects.create(client=client,**address_data)
return client
example data to post:
{
"primary_contact_first_name": "iliyas",
"primary_contact_last_name": "shaik",
"primary_contact_email": "a#a.com",
"primary_contact_phone_number": "9185213654",
"primary_contact_phone_type": "HOme",
"secondary_contact_first_name": "meraa",
"secondary_contact_last_name": "shaik",
"secondary_contact_email": "z#z.com",
"secondary_contact_phone_number": "8963251470",
"secondary_contact_phone_type": "Mobile",
"address": {
"street_address_line_1": "NTR NAGAR",
"street_address_line_2": "CHOWRASTA",
"city": "KURNOOL",
"state": "ANDHRA",
"zip": 51896352,
"country": "INDIA"
}
}
client_address_id is null when the post request data is serialized and clientaddress_id is foriegn key which should be id of row present in address model table but here no data is being saved ,the address model table is empty.How could I do this?
You need to override create the method of ClientSerializer
class ClientSerializer(serializers.ModelSerializer):
address = AddressSerializer(source="addresss")
class Meta:
model = Client
fields = [
"primary_contact_first_name",
"primary_contact_last_name",
"primary_contact_email",
"primary_contact_phone_number",
"primary_contact_phone_type",
"secondary_contact_first_name",
"secondary_contact_last_name",
"secondary_contact_email",
"secondary_contact_phone_number",
"secondary_contact_phone_type",
"address",
]
def create(self, validated_data):
address_data = validated_data['address']
# Create address instance
address = Address.objects.create(...)
# Create client instance
client = Client.objects.create(...)
return client

DRF display nested JSON

I have my DRF app. In my case, one wallet can have many entries such as income or expense. When I call my endpoint (viewset) I get data in this format:
[
{
"id": "d458196e-49f1-42db-8bc2-ee1dba438953",
"owner": 1,
"viewable": [],
"entry": []
}
]
How can I get the content of "entry" variable?.
class Category(models.Model):
name = models.CharField(max_length=20, unique=True)
def __str__(self):
return self.name
class BudgetEntry(models.Model):
STATE= [
('income','income'),
('expenses','expenses'),
]
amount = models.IntegerField()
entry_type = models.CharField(max_length=15, choices=STATE, null=True)
entry_category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL)
class WalletInstance(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='owner', on_delete=models.CASCADE)
viewable = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='can_view', blank=True)
entry = models.ManyToManyField(BudgetEntry, related_name='BudgetEntry', blank=True)
Serializers.py:
class BudgetEntrySerializer(serializers.ModelSerializer):
class Meta:
model = BudgetEntry
fields = '__all__'
class WalletInstanceSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.id')
class Meta:
model = WalletInstance
fields = '__all__'
Views.py:
class WalletViewset(viewsets.ModelViewSet):
permission_classes = [IsAuthenticated]
serializer_class = WalletInstanceSerializer
def get_queryset(self):
user_id = self.request.user.id
available = WalletInstance.objects.filter(
Q(owner=user_id)
)
return available
Change your serializer like this:
class WalletInstanceSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.id')
entry = BudgetEntrySerializer(many=True, read_only=True)
class Meta:
model = WalletInstance
fields = '__all__'

Django : Add JSON POST data into the database

I'm trying to make an API for a butcher.
With this API and the website that I will build by the next, the client will be able to make his order remotly.
Here is my probleme.
With the order form, the client send me JSON data like here :
{
"user": 8,
"orderDay": "2020-06-24",
"deliveryDay": "2020-06-30",
"deliveryAddress": "Place des FĂȘtes",
"comment": "",
"orderDetail":
[
{
"product": 2,
"byProduct": 2,
"quantity": 43
},
{
"product": 3,
"byProduct": 3,
"quantity": 5
}
]
}
These data must be saved in the database.
These are the models that I use : models.py
class order(models.Model):
user = models.ForeignKey(memberArea, on_delete=models.CASCADE)
comment = models.TextField(null=True, blank=True)
orderDay = models.DateTimeField(auto_now_add=True)
deliveryDay = models.DateField()
deliveryAddress = models.CharField(max_length=255)
state = models.CharField(max_length=255)
price = models.TextField(null=True, blank=True)
response = models.TextField(null=True, blank=True)
class orderDetail(models.Model):
order = models.ForeignKey(order, on_delete=models.CASCADE)
product = models.ForeignKey(product, on_delete=models.CASCADE)
byProduct = models.ForeignKey(byProduct, on_delete=models.CASCADE)
quantity = models.CharField(max_length=255)
class product(models.Model):
name = models.CharField(max_length=255)
prix_uni = models.TextField(null=True, blank=True)
prix_kg = models.TextField(null=True, blank=True)
dispo = models.BooleanField(null=True, blank=True)
category = models.ForeignKey(category, on_delete=models.CASCADE)
redu = models.TextField(null=True, blank=True)
class byProduct(models.Model):
product = models.ForeignKey(product, on_delete = models.CASCADE)
name = models.CharField(max_length=255)
I make a serializer file like this serializer.py
class orderDetailSerializer(serializers.ModelSerializer):
order = serializers.PrimaryKeyRelatedField(many=False, queryset = order.objects.all())
class Meta:
model = orderDetail
fields = '__all__'
class OrderSerializer(serializers.ModelSerializer):
orderDetail = orderDetailSerializer(many=True)
class Meta:
model = order
fields = ['user', 'comment', 'deliveryAddress', 'deliveryDay', 'orderDetail']
def create(self, validated_data):
order_detail_data = validated_data.pop('orderDetail')
new_order = order.objects.create(**validated_data)
new_order.save()
for product in order_detail_data:
order_detail = orderDetail.objects.create(order=new_order, **product)
new_order.orderDetail.add(order_detail.id)
return new_order
And this is my view : views.py:
#Make an order
#api_view(['POST'])
def order(request, format=None):
if request.method == 'POST':
serializer = OrderSerializer(data=request.data)
data = {}
if serializer.is_valid():
serializer.save()
data['response'] = "Your order went well"
return Response(data)
return Response(serializer.errors)
When I try to run my code, it tells me that the order data is missing :
{
"orderDetail": [
{
"order": [
"This field is required."
]
},
{
"order": [
"This field is required."
]
}
]
}
I don't know how to add this because the order_id that I need is created at the same time that the orderDetail.
Thank's by advance for helping me.
you should make order field readonly in orderDetailSerializer:
class orderDetailSerializer(serializers.ModelSerializer):
class Meta:
model = orderDetail
fields = '__all__'
read_only_fields = ('order',)

How to join models in django serializers?

I'm trying to join two models, but I got the wrong result. How to do it right?
My models:
class MoocherPage(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=False)
name = models.CharField(max_length=48, unique=True, blank=False, null=False)
bio = models.TextField(blank=False, null=False)
class MoocherResource(models.Model):
url = models.URLField(blank=False, null=False)
moocher = models.ForeignKey(MoocherPage, on_delete=models.CASCADE)
And serializers:
class MoocherResourceSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
URL_FIELD_NAME = 'url'
model = MoocherResource
fields = ('url', )
class MoocherPageSerializer(serializers.ModelSerializer):
resources = MoocherResourceSerializer(many=True, read_only=True)
class Meta:
model = MoocherPage
fields = ('name', 'bio', 'resources')
depth = 1
I expected
{
"name": "KissofLove",
"bio": "I'm the kiss of love and I collect money for all lovers of the world.",
"resources": ["https://stackoverflow.com/users/KissofLove"]
}
But the resources was not included.
When I change read_only=True to False in the nested serializer an error appears.
AttributeError: Original exception text was: 'MoocherPage' object has no attribute 'resources'.
Your models
class MoocherPage(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=False)
name = models.CharField(max_length=48, unique=True, blank=False, null=False)
bio = models.TextField(blank=False, null=False)
class MoocherResource(models.Model):
url = models.URLField(blank=False, null=False)
moocher = models.ForeignKey(MoocherPage, on_delete=models.CASCADE)
and your serializers,
from rest_framework.serializers import *
class ResourceListingField(RelatedField):
def to_representation(self, value):
return value.url
class MoocherPageSerializer(ModelSerializer):
resources = ResourceListingField(many=True, source='moocherresource_set', read_only=True)
class Meta:
model = MoocherPage
fields = ['name', 'bio', 'resources']
This returns the desired
{
"name": "KissOfLove",
"bio": "I'm the kiss of love and I collect money for all lovers of the world.",
"resources": ["https://stackoverflow.com/users/KissofLove"]
}
response.
Check out Custom relational fields

Error: expected pk value, received list for foreignkey field

I cannot save multiple values for the Foreignkey field when adding instances to the database. I don't understand exactly what the problem is: in my code or in the format of the JSON object being passed.
models.py
class VendorContacts(models.Model):
contact_id = models.AutoField(primary_key=True)
vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE)
contact_name = models.CharField(max_length=45, blank=True)
phone = models.CharField(max_length=45, blank=True)
email = models.CharField(max_length=80, blank=True, unique=True)
class Meta:
db_table = 'vendor_contacts'
class VendorModuleNames(models.Model):
vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE, primary_key=True)
module = models.ForeignKey(Modules, models.DO_NOTHING)
timestamp = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'vendor_module_names'
unique_together = (('vendor', 'module'),)
class Vendors(models.Model):
COUNTRY_CHOICES = tuple(COUNTRIES)
vendorid = models.AutoField(primary_key=True)
vendor_name = models.CharField(max_length=45, unique=True)
country = models.CharField(max_length=45, choices=COUNTRY_CHOICES)
nda = models.DateField(blank=True, null=True)
user_id = models.ForeignKey('c_users.CustomUser', on_delete=models.PROTECT)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'vendors'
unique_together = (('vendorid', 'timestamp'),)
serializers.py
class VendorsSerializer(serializers.ModelSerializer):
class Meta:
model = Vendors
fields = ('vendor_name',
'country',
'nda',
'parent_vendor',)
class VendorContactSerializer(serializers.ModelSerializer):
class Meta:
model = VendorContacts
fields = (
'contact_name',
'phone',
'email',)
class VendorModulSerializer(serializers.ModelSerializer):
class Meta:
model = VendorModuleNames
fields = ('module',)
views.py
class VendorsCreateView(APIView):
"""Create new vendor instances from form"""
serializer_class = (VendorsSerializer)
def post(self, request, *args, **kwargs):
vendor_serializer = VendorsSerializer(data=request.data)
vendor_contact_serializer = VendorContactSerializer(data=request.data)
vendor_modules_serializer = VendorModulSerializer(data=request.data)
try:
vendor_serializer.is_valid(raise_exception=True) \
and vendor_contact_serializer.is_valid(raise_exception=True) \
and vendor_modules_serializer.is_valid(raise_exception=True) \
vendor = vendor_serializer.save(user_id=request.user)
vendor_contact_serializer.save(vendor=vendor)
vendor_modules_serializer.save(module= maybe something here?????, vendor=vendor)
except ValidationError:
return Response({"errors": (vendor_serializer.errors,
vendor_contact_serializer.errors,
vendor_modules_serializer.errors
)},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response(request.data, status=status.HTTP_200_OK)
JSON body
{
"vendor_name": "Awrazofgsxsdsxjwszsslsasdjegdzasas",
"country": "Canada",
"module": [
1,
2
],
"NDA date": "",
"contact_name": "Tim",
"email": "teaszt#tesstd.gmail",
"phone": "+3464784594940",
"parent_vendor": "23"
}
When I send JSON, I get the response
{
"module": [
"Incorrect type. Expected pk value, received list."
]
}
Looks like I'm finally confused about multiple saving
Your ForeignKey should be set on the related class Modules.

Categories