Creating view with foreign key model django restframework - python

I'm fairly new with the django restframework.
I am trying to create a serializer and a view for a model that has a foreignKey.
Models.py
class Job(models.Model):
"""A Job used to create a job posting"""
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
description = models.TextField()
job_type = models.CharField(max_length=12, choices=JOB_TYPE_CHOICES, default='Full-Time')
city = models.CharField(max_length=255)
state = models.CharField(max_length=255)
created_date = models.DateField(auto_now=False, auto_now_add=True)
salary = models.CharField(max_length=255)
position = models.CharField(max_length=255)
employer = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.description[:50]
class Applicant(models.Model):
"""A applicant that can apply to a job"""
job = models.ForeignKey(Job, on_delete=models.CASCADE)
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField(max_length=254)
phone_number = PhoneNumberField()
resume = models.FileField(upload_to=resume_file_path, validators=[validate_file_extension])
def __str__(self):
return self.first_name
The idea is that Applicant will be able to apply to Job.
I can't seem to figure out how to get the Job id when a Applicant is applying to job.
serializers.py
class JobSerializer(serializers.ModelSerializer):
"""Serializer for tag objects"""
class Meta:
model = Job
fields = ('id', 'description', 'job_type', 'city', 'state', 'salary', 'position', 'employer', 'created_date', 'is_active')
read_only_fields = ('id',)
def create(self, validated_data):
"""Create a job posting with user and return it"""
return Job.objects.create(**validated_data)
class ApplyJobSerializer(serializers.ModelSerializer):
"""Serializer for applying to jobs"""
class Meta:
model = Applicant
fields = ('id', 'first_name', 'last_name', 'email', 'phone_number', 'resume')
read_only_fields = ('id',)
views.py
class ApplyJobView(generics.CreateAPIView):
"""Allows applicants to apply for jobs"""
serializer_class = serializers.ApplyJobSerializer
Below is an image of my http://localhost:8000/api/jobPosting/apply/ url
I don't know how i can bring in the Jobs as in option to my view so I can obtain the id field.
I get the following error when POST
null value in column "job_id" violates not-null constraint

You are not passing job field in serializer fields. Try this:
class ApplyJobSerializer(serializers.ModelSerializer):
"""Serializer for applying to jobs"""
class Meta:
model = Applicant
fields = ('id', 'first_name', 'last_name', 'email', 'phone_number', 'resume', 'job')
read_only_fields = ('id',)

Related

Contacts matching query does not exist in django rest framework

I am trying to update Contact model fields while creating the new fields of UpdateInfo model and add them to the existing model.
But I am getting this error
contacts.models.Contacts.DoesNotExist: Contacts matching query does not exist.
I know the contact object with the id 19 exists because I can see it when I try the get contacts API.
I am sending data like this.
My models:
class Contacts(models.Model):
full_name = models.CharField(max_length=100, blank=True)
.........
def __str__(self):
return self.full_name
class Meta:
verbose_name_plural = 'Potential Clients'
class UpdateInfo(models.Model):
contacts = models.ForeignKey(Contacts,on_delete=models.CASCADE, related_name='update_info')
updated_at = models.DateTimeField(auto_now=True)
modified_by = models.CharField(max_length=100, blank=True)
def __str__(self):
return f"Last modified by {self.modified_by} at {self.updated_at}"
My views:
class EditContactView(RetrieveUpdateDestroyAPIView):
permission_classes = [IsAuthenticated]
queryset = Contacts.objects.all()
serializer_class = ContactsUpdateSeializer
My serializers:
class UpdateInfoSerializer(serializers.ModelSerializer):
contacts= serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = UpdateInfo
fields = ['id','contacts','updated_at','modified_by']
class ContactsUpdateSeializer(serializers.ModelSerializer):
update_info = UpdateInfoSerializer(many=True)
id = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = Contacts
fields = ['id', 'full_name', 'lead_source', 'email', 'phone', 'contact_owner',
'contact_status', 'company_name', 'job_position', 'tasks',
'notes', 'email_list', 'created_by', 'created_at', 'update_info']
def update(self, instance, validated_data):
update_data = validated_data.pop('update_info')
id = validated_data.get('id')
contacts = Contacts.objects.get(id=id)
#contacts.save()
#contact_only_update_logic
instance.full_name = validated_data.get('full_name')
instance.lead_source = validated_data.get('lead_source')
instance.email = validated_data.get('email')
instance.phone = validated_data.get('phone')
instance.contact_owner = validated_data.get('contact_owner')
instance.contact_status = validated_data.get('contact_status')
instance.company_name = validated_data.get('company_name')
instance.job_position = validated_data.get('job_position')
instance.tasks = validated_data.get('tasks')
instance.notes = validated_data.get('notes')
instance.email_list = validated_data.get('email_list')
instance.save()
#add_update_info_logic
for update_data in update_data:
abc = UpdateInfo.objects.create(contacts=contacts,**update_data)
instance.update_info.add(abc)
instance.save()
return instance
You have to change your serializer
class ContactsUpdateSeializer(serializers.ModelSerializer):
update_info = UpdateInfoSerializer(many=True)
class Meta:
model = Contacts
fields = ['id', 'full_name', 'lead_source', 'email', 'phone', 'contact_owner',
'contact_status', 'company_name', 'job_position', 'tasks',
'notes', 'email_list', 'created_by', 'created_at', 'update_info']
def update(self, instance, validated_data):
update_data = validated_data.pop('update_info')
instance = super(ContactsUpdateSeializer, self).update(instance, validated_data)
for update_datum in update_data:
abc = UpdateInfo.objects.create(contacts=instance,**update_datum)
return instance
PrimaryKeyRelatedField is used for foreign key purpose and there we have to define queryset also.
Don't need to add the updateinfo in contact, it is already done throgh django.
Moreover, it would be better if you use bulk_create instead of running save each time if you there is no signals exists for that.
You can do it as:-
UpdateInfo.objects.bulk_create([UpdateInfo(contacts=instance,**update_datum) for update_datum in update_data])

Got AttributeError when attempting to get a value for field `phone_number` on serializer

AttributeError:Got AttributeError when attempting to get a value for field phone_number on serializer ListBusCompanyStaffSerializer.
Bascially I have two models User and BusCompanyStaff, User consists of phone_number field BusCompanyStaff consists of following models fields
class BusCompanyStaff(BaseModel):
user = models.OneToOneField(
BusCompanyUser,
on_delete=models.CASCADE
)
position = models.ForeignKey(
StaffPosition,
on_delete=models.SET_NULL,
null=True,
related_name='position'
)
created_by = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='created_by'
)
staff_of = models.ForeignKey(
BusCompany,
on_delete=models.CASCADE
)
I basically wants to list particular BusCompanyStaff from BusCompany so here is my serializer I tried till now
class ListBusCompanyStaffSerializer(serializers.ModelSerializer):
position = serializers.CharField()
class Meta:
model = BusCompanyStaff
fields = (
'id',
'phone_number',
'position',
'email',
)
there is defintely Error as BusCompanyStaff dont consist of phone_number field but requirement is to put User phone number and email
Here is my rest of code in views.py and usecases.py
#usecases.py
class ListBusCompanyStaffUseCase(BaseUseCase):
def __init__(self, bus_company: BusCompany):
self._bus_company = bus_company
def execute(self):
self._factory()
return self._bus_company_staffs
def _factory(self):
self._bus_company_staffs = BusCompanyStaff.objects.filter(staff_of=self._bus_company)
#views.py
class ListBusCompanyStaffView(generics.ListAPIView):
serializer_class = bus_company_user_serializers.ListBusCompanyStaffSerializer
def get_bus_company(self):
return GetBusCompanyUseCase(
bus_company_id=self.kwargs.get('bus_company_id')
).execute()
def get_queryset(self):
return ListBusCompanyStaffUseCase(
bus_company=self.get_bus_company()
).execute()
how can I serialize in this format
id ,
phone_number ,
position,
email,
You can do it this way:
class ListBusCompanyStaffSerializer(serializers.ModelSerializer):
...
phone_number = serializers.CharField(source='user.phone_number')
class Meta:
model = BusCompanyStaff
fields = (
...
'phone_number',
)

Unable to save relationship between two objects with Django Rest Framework

I am building a Django/React App to allow users to submit orders that need to go from A to B. The user initially saves the addresses in the database and then he/she selects it in the order form. When they submit I attempt to create a relationship in the database, I'm using Django Rest Framework serializers to create the Order object in the database.
Unfortunately, I'm unable to successfully save the items as I'm not properly linking the addresses to the order. Im getting the following error:
destinationAddress: ["Invalid value."]
originAddress: ["Invalid value."]
Models
class Order(models.Model):
originAddress = models.ForeignKey(Address, related_name="originAddress", null=True, on_delete=models.CASCADE)
destinationAddress = models.ForeignKey(Address, related_name="destinationAddress", null=True, on_delete=models.CASCADE)
packages = models.CharField("Packages", max_length=1024)
class Address(models.Model):
address_code = models.CharField(max_length=250)
contact = models.CharField("Contact", max_length=1024)
phone = models.CharField("Phone", max_length=20)
company = models.CharField("Company", max_length=250)
addressLine1 = models.CharField("Address line 1", max_length=1024)
addressLine2 = models.CharField("Address line 2", max_length=1024, blank=True)
postalCode = models.CharField("Postal Code", max_length=12)
city = models.CharField("City", max_length=1024)
state = models.CharField("State", max_length=250)
Serializers
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = '__all__'
class OrderSerializer(serializers.ModelSerializer):
originAddress = serializers.SlugRelatedField(
queryset=Address.objects.all(),
slug_field='pk'
)
destinationAddress = serializers.SlugRelatedField(
queryset=Address.objects.all(),
slug_field='pk'
)
class Meta:
model = Order
fields = ('id', 'packages', 'destinationAddress', 'originAddress')
ViewSets
class OrderViewSet(viewsets.ModelViewSet):
queryset = Order.objects.all()
permission_classes = [
permissions.AllowAny
]
serializer_class = OrderSerializer
class AddressViewSet(viewsets.ModelViewSet):
queryset = Address.objects.all()
permission_classes = [
permissions.AllowAny
]
serializer_class = AddressSerializer
Any ideas? Thanks
Solved it by replacing SlugRelatedField to PrimaryKeyRelatedField
class OrderSerializer(serializers.ModelSerializer):
originAddress = serializers.PrimaryKeyRelatedField(
queryset=Address.objects.all(), allow_null=True, required=False
)
destinationAddress = serializers.PrimaryKeyRelatedField(
queryset=Address.objects.all(), allow_null=True, required=False
)
class Meta:
model = Order
fields = ('id', 'packages', 'destinationAddress', 'originAddress')

Django REST Framework ModelSerializer read_only_fields not working

I have the following ListCreateAPIView
class TodoAPI(generics.ListCreateAPIView):
permission_classes = (IsAuthenticated, )
serializer_class = TodoSerializer
def get_queryset(self):
user = self.request.user
return Todo.objects.filter(user=user)
And in my serializers.py, I have
class TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'description',
'completed', 'created_at')
read_only_fields = ('id', )
But the problem is when I POST data into the form, I get the following error:
IntegrityError at /todo/
NOT NULL constraint failed: todo_todo.user_id
models.py
class Todo(models.Model):
user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
title = models.TextField(max_length=50)
description = models.TextField(max_length=200, blank=True, null=True)
completed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
The problem is not with id field, but with user field. This field is not nullable in DB and since is required. You can just pass current user as defalt, for this use CurrentUserDefault:
class TodoSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Todo
fields = ('id', 'title', 'description',
'completed', 'created_at', 'user')

Django Rest Framework - nested objects not being generated properly

I am trying to implement simple api in Django Rest Framework.
I have following models in models.py:
class Entry(BaseModel):
company_name = models.CharField(max_length=256, null=True, blank=True)
first_name = models.CharField(null=True, default=None, max_length=32)
last_name = models.CharField(null=True, default=None, max_length=32)
code = models.CharField(null=True, default=None, max_length=12)
class Meta:
db_table = 'entry'
class Admin(admin.ModelAdmin):
list_display = ('company_name', 'code')
list_display_links = ('company_name', )
ordering = ('-created',)
class EntryContactData(BaseModel):
entry = models.ForeignKey(Entry, related_name='contact')
email = models.CharField(max_length=256, null=True, blank=True)
website = models.CharField(max_length=64, null=True, blank=True)
phone = models.CharField(max_length=64, null=True, blank=True)
My API serializers.py:
from django.contrib.auth.models import User, Group
from rest_framework import serializers
from core.models import Entry, EntryContactData
class EntryContactSerializer(serializers.ModelSerializer):
class Meta:
model = EntryContactData
fields = ('uuid', 'email', 'website', 'phone')
class EntrySerializer(serializers.ModelSerializer):
contact = EntryContactSerializer(many=False, read_only=True)
class Meta:
model = Entry
fields = ('uuid', 'company_name', 'first_name', 'last_name', 'contact')
And my API views:
from core.models import Entry
from .serializers import EntrySerializer
class EntryViewSet(viewsets.ViewSet):
"""
A simple ViewSet for listing or retrieving users.
"""
queryset = Entry.objects.all()
def retrieve(self, request, pk=None):
queryset = Entry.objects.all()
entry = get_object_or_404(queryset, code=pk)
serializer = EntrySerializer(entry, context={'request': request})
return Response(serializer.data)
When I want to retrieve single entry its contact field is empty:
{
"uuid": "e6818508-a172-44e1-b927-3c087d2f9773",
"company_name": "COMPANY NAME",
"first_name": "FIRSTNAME",
"last_name": "LASTTNAME",
"contact": {}
}
So it doesn't contain any of fields defined in EntryContactSerializer
What am I doing wrong? How can I force it to return all fields included in serializer? Thank you guys.
Try setting many=True in EntrySerializer, and provide a source attribute to the serializer,
class EntrySerializer(serializers.ModelSerializer):
contact = EntryContactSerializer(source='contact', many=True, read_only=True)
class Meta:
model = Entry
fields = ('uuid', 'company_name', 'first_name', 'last_name', 'contact')

Categories