I am trying to Update A Employee. I am able to update also. But the problem is coming a while updating when i am not sending data in body. It is giving error of Required Field.
This error is one of kind - where i was not sending excempt in json body
serializer2 {'excempt': [ErrorDetail(string='This field is required.', code='required')]}
Even i tried to put required=False and it is working but i am not understanding if we are passing instance of that EmployeeProfileSerializer(userprofile, data=request.data). Example userprofile but why it is still it is giving error. And how should i tackle it. I don't think this is the solution required=False?.
When i am not sending data in body then the previous data should be used but this is not happening instead it is giving error of required field
APIView
class EmployeeUpdateApiV2(APIView):
def post(self, request, *args, **kwrgs):
try:
accesstoken=AccessToken.objects.get(
token=self.request.META.get('HTTP_AUTHORIZATION').replace('Bearer ', '')
)
except ObjectDoesNotExist:
return Response (
{
"status" : False,
"error" : "Wrong Access Token",
"error_message":"You have provided wrong access token.",
}
)
user_id = request.data['user_id']
user = get_object_or_404(User, id=user_id)
print(user)
userprofile = get_object_or_404(UserProfile, user=user_id)
print(userprofile)
serializer1 = EmployeeRegisterSerializer(user, data=request.data)
serializer2 = EmployeeProfileSerializer(userprofile, data=request.data)
if serializer1.is_valid() and serializer2.is_valid():
serializer1.save()
serializer2.save()
print('Inside Valid')
return Response (
{
"status" : True,
"message":"Employee Updated Successfully.",
"api_name" : "EmployeeUpdateApiV2",
"result": serializer1.data,
"result1": serializer2.data,
}
)
print('Out Valid')
print('serializer1 ', serializer1.errors)
print('serializer2', serializer2.errors)
return Response(status=status.HTTP_404_NOT_FOUND)
Serializers.py
class EmployeeProfileSerializer(serializers.ModelSerializer):
employee_id = serializers.CharField(source='user_employee_id')
payroll_id = serializers.CharField(source='user_payroll_id')
hire_date = serializers.CharField(source='user_hire_date')
pay_rate = serializers.CharField(source='user_pay_rate')
salaried = serializers.CharField(source='user_salaried')
excempt = serializers.CharField(source='user_excempt')
groups = serializers.CharField(source='user_groups_id', required=False)
state = serializers.CharField(source='user_state')
city = serializers.CharField(source='user_city')
zipcode = serializers.CharField(source='user_zipcode')
status = serializers.CharField(source='user_status')
phone = serializers.CharField(source='user_phone')
class Meta:
model = UserProfile
fields = [
'employee_id',
'phone',
'payroll_id',
'hire_date',
'pay_rate',
'salaried',
'excempt',
'groups',
'state',
'city',
'zipcode',
'status',
]
class EmployeeRegisterSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['first_name','last_name', 'email',]
Userprofile Model
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
user_company = models.ForeignKey(Company, on_delete=models.CASCADE)
user_role = models.ForeignKey(ACLRoles, on_delete=models.CASCADE)
user_dob = models.DateField(null=True, blank=True)
user_phone = models.CharField(max_length=30, blank=True, null=True)
user_image = models.ImageField(upload_to='user_profiles/', default='default_user.png',blank=True, null=True)
user_created = models.DateTimeField(auto_now_add=True)
user_is_deleted = models.BooleanField(default=False)
user_deleted_at = models.DateTimeField(blank=True, null=True)
user_groups = models.ManyToManyField(Groups,related_name='user_groups')
MALE = 'Male'
FEMALE = 'Female'
GENDER_CHOICES = (
(MALE, 'Male'),
(FEMALE, 'Female'),
)
user_gender = models.CharField(
max_length=8,
choices=GENDER_CHOICES,
)
ACTIVE = 'Active'
INACTIVE = 'Inactive'
PENDING = 'Pending'
USER_ACTIVE_CHOICES = (
(ACTIVE, 'Active'),
(INACTIVE, 'Inactive'),
(PENDING, 'Pending'),
)
user_status = models.CharField(
max_length=8,
choices=USER_ACTIVE_CHOICES,
default=ACTIVE,
)
please add user in your Model Serializer field section
class EmployeeProfileSerializer(serializers.ModelSerializer):
employee_id = serializers.CharField(source='user_employee_id')
payroll_id = serializers.CharField(source='user_payroll_id')
hire_date = serializers.CharField(source='user_hire_date')
pay_rate = serializers.CharField(source='user_pay_rate')
salaried = serializers.CharField(source='user_salaried')
excempt = serializers.CharField(source='user_excempt')
groups = serializers.CharField(source='user_groups_id', required=False)
state = serializers.CharField(source='user_state')
city = serializers.CharField(source='user_city')
zipcode = serializers.CharField(source='user_zipcode')
status = serializers.CharField(source='user_status')
phone = serializers.CharField(source='user_phone')
class Meta:
model = UserProfile
fields = [
'employee_id',
'phone',
'payroll_id',
'hire_date',
'pay_rate',
'salaried',
'excempt',
'groups',
'state',
'city',
'zipcode',
'status',
'user',
]
Related
I am working with django viewsets and i want an extra field from the request for validation.
What i want is the extra field role_id which should be coming from the request. The role id if passed, i should convert the employee to user and assign the role_id to the user.
Even though i am sending the role_id from request but i am unable to get it in the create or update method. Can someone please help me to know how can i fetch extra field from response
serializer.py
class EmployeeModelSerializer(serializers.ModelSerializer):
"""Employee model serializer"""
address = EmployeeAddressModelSerializer(required=False)
detail = EmployeeDetailModelSerializer(required=False)
demographic = EmployeeDemographicModelSerializer(required=False)
contact = EmployeeContactModelSerializer(required=False)
nok = EmployeeNokModelSerializer(required=False)
visa = EmployeeVisaModelSerializer(required=False)
dbs = EmployeeDBSModelSerializer(required=False)
job_detail = EmployeeJobDetailModelSerializer(required=False)
preference = EmployeePreferenceModelSerializer(required=False)
skills = EmployeeSkillsModelSerializer(many=True, read_only=True)
user = UserModelSerializer(required=False)
serializersMap = {
"address": EmployeeAddressModelSerializer,
"detail": EmployeeDetailModelSerializer,
"demographic": EmployeeDemographicModelSerializer,
"contact": EmployeeContactModelSerializer,
"nok": EmployeeNokModelSerializer,
"visa": EmployeeVisaModelSerializer,
"dbs": EmployeeDBSModelSerializer,
"job_detail": EmployeeJobDetailModelSerializer,
"preference": EmployeePreferenceModelSerializer,
"user": UserModelSerializer,
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.context["gender"] = None
self.context["title"] = None
self.context["marital_status"] = None
self.context["employee_status"] = None
def internal_validate(self, data, field):
self.context[field] = data
if data == None:
return data
elif data.id:
return data.id
return data
def validate_gender(self, data):
return self.internal_validate(data, "gender")
def validate_title(self, data):
return self.internal_validate(data, "title")
def validate_marital_status(self, data):
return self.internal_validate(data, "marital_status")
def validate_employee_status(self, data):
return self.internal_validate(data, "employee_status")
user = serializers.SlugRelatedField(
read_only=True,
slug_field='username'
)
class Meta:
"""Meta class."""
model = Employee
fields = '__all__'
def get_fullname(self, obj):
return obj.first_name + " " + obj.last_name
def create(self, data):
data["address"] = self.saveForeign(data, "address")
data["detail"] = self.saveForeign(data, "detail")
data["demographic"] = self.saveForeign(data, "demographic")
data["contact"] = self.saveForeign(data, "contact")
data["nok"] = self.saveForeign(data, "nok")
data["visa"] = self.saveForeign(data, "visa")
data["dbs"] = self.saveForeign(data, "dbs")
data["job_detail"] = self.saveForeign(data, "job_detail")
data["preference"] = self.saveForeign(data, "preference")
data.pop("skills", None)
self.setContext(data)
employee = Employee.objects.create(**data)
return employee
def update(self, instance, data):
instance.address = self.updateForeign(instance.address, data, "address")
instance.detail = self.updateForeign(instance.detail, data, "detail")
instance.demographic = self.updateForeign(instance.demographic, data, "demographic")
instance.contact = self.updateForeign(instance.contact, data, "contact")
instance.nok = self.updateForeign(instance.nok, data, "nok")
instance.visa = self.updateForeign(instance.visa, data, "visa")
instance.dbs = self.updateForeign(instance.dbs, data, "dbs")
instance.job_detail = self.updateForeign(instance.job_detail, data, "job_detail")
instance.preference = self.updateForeign(instance.preference, data, "preference")
self.setContext(data)
return super(EmployeeModelSerializer, self).update(instance, data)
def saveForeign(self, data, name):
field = data.get(name)
data.pop(name, None)
if field is None:
return None
serializer = self.serializersMap.get(name)(data=field)
if serializer.is_valid(raise_exception=True):
return serializer.save()
def updateForeign(self, instance, data, name):
field = data.get(name)
data.pop(name, None)
if field is None:
return None
if not instance:
serializer = self.serializersMap.get(name)(data=field, context={})
if serializer.is_valid(raise_exception=True):
return serializer.save()
else:
serializer = self.serializersMap.get(name)(instance, data=field, context={})
if serializer.is_valid(raise_exception=True):
return serializer.update(instance, field)
def setContext(self, data):
if self.context["gender"] != None:
data["gender"] = self.context['gender']
if self.context["title"] != None:
data["title"] = self.context['title']
if self.context["marital_status"] != None:
data["marital_status"] = self.context['marital_status']
if self.context["employee_status"] != None:
data["employee_status"] = self.context['employee_status']
views.py
"""Employee view set"""
# authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,)
queryset = Employee.objects.filter(is_active=True).order_by('-modified')
serializer_class = EmployeeModelSerializer
filter_backends = (SearchFilter, OrderingFilter, DjangoFilterBackend)
filter_fields = [
"job_detail__employment_type_id",
"job_detail__employee_category_id",
"job_detail__job_title_id",
"skills__name__id"
]
ordering_fields = [
'modified',
'job_detail__branch__name',
'full_name',
'reference',
'employee_status__name',
'address__name'
]
search_fields = [
'full_name',
'last_name',
'address__zip_code',
'contact__mobile_number'
]
def destroy(self, request, pk=None):
employee = self.get_object()
employee.is_active = False
employee.save()
return Response({'message': 'deleted!'}, status=status.HTTP_200_OK)
models.py
class Employee(Person):
user = models.ForeignKey(
'users.User',
null=True,
on_delete=models.SET_NULL
)
employee_status = models.ForeignKey(
'core.Employee_Status',
null=True,
blank=True,
on_delete=models.SET_NULL
)
title = models.ForeignKey(
'core.Title',
null=True,
blank=True,
on_delete=models.SET_NULL
)
payroll_ref = models.CharField(
'Payroll -Reference',
max_length=25,
blank=True,
default=''
)
address = models.OneToOneField(
'employees.Employee_Address',
null=True,
on_delete=models.SET_NULL
)
contact = models.OneToOneField(
'employees.Employee_Contact',
null=True,
on_delete=models.SET_NULL
)
dbs = models.OneToOneField(
'employees.Employee_dbs',
null=True,
on_delete=models.SET_NULL
)
demographic = models.OneToOneField(
'employees.Employee_Demographic',
null=True,
on_delete=models.SET_NULL
)
detail = models.OneToOneField(
'employees.Employee_Detail',
null=True,
on_delete=models.SET_NULL
)
job_detail = models.OneToOneField(
'employees.Employee_Job_Detail',
null=True,
on_delete=models.SET_NULL
)
nok = models.OneToOneField(
'employees.Employee_NOK',
null=True,
on_delete=models.SET_NULL
)
preference = models.OneToOneField(
'employees.Employee_Preference',
null=True,
on_delete=models.SET_NULL
)
visa = models.OneToOneField(
'employees.Employee_Visa',
null=True,
on_delete=models.SET_NULL
)
skills = models.ManyToManyField(
'employees.Employee_Skill',
related_name='Employee',
)
class Meta:
verbose_name = 'Employee - Basic Info'
verbose_name_plural = 'Employees - Basic Info'
request parameter
{
"first_name": "first name",
"last_name": "last name",
"date_of_birth": "2017-02-12",
"is_active": true,
"role_id": "role_id_goes_here",
"address": {
"name": "address name",
"line_1": "line 1",
"city": "city",
"state": "state",
"country": "country",
"zip_code": "zip code"
},
"nok": {
"no": "123sad",
"full_name": "full name nok",
"mobile": 123456789,
"email": "jesus#iconos.mx",
"title": null
},
"title": null
}
I tried to create an update api for Orders but in the result of the postman, I am getting this error
KeyError at /api/updateorder/260 'id'
I have put the id field both in OrderUpdate Serializer and OrderItemUpdateSerializer as you can see below. Also, I have printed the validated_data.pop('order_items'). In the result of print, I get Orderdict which has no id field. I don't know why id is not showing.
My models:
class Order(models.Model):
ORDER_STATUS = (
('To_Ship', 'To Ship',),
('Shipped', 'Shipped',),
('Delivered', 'Delivered',),
('Cancelled', 'Cancelled',),
)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
order_status = models.CharField(max_length=50,choices=ORDER_STATUS,default='To_Ship')
ordered_date = models.DateTimeField(auto_now_add=True)
ordered = models.BooleanField(default=False)
#property
def total_price(self):
return sum([_.price for _ in self.order_items.all()])
class OrderItem(models.Model):
orderItem_ID = models.CharField(max_length=12, editable=False, default=id_generator)
order = models.ForeignKey(Order,on_delete=models.CASCADE, blank=True,null=True,related_name='order_items')
item = models.ForeignKey(Product, on_delete=models.CASCADE,blank=True, null=True)
order_variants = models.ForeignKey(Variants, on_delete=models.CASCADE,blank=True,null=True)
quantity = models.IntegerField(default=1)
ORDER_STATUS = (
('To_Ship', 'To Ship',),
('Shipped', 'Shipped',),
('Delivered', 'Delivered',),
('Cancelled', 'Cancelled',),
)
order_item_status = models.CharField(max_length=50,choices=ORDER_STATUS,default='To_Ship')
#property
def price(self):
total_item_price = self.quantity * self.order_variants.price
return total_item_price
My serializers:
class OrderItemUpdateSerializer(serializers.ModelSerializer):
id = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = OrderItem
fields = ['id','order','item','order_variants', 'quantity','order_item_status','price']
# depth = 1
class OrderUpdateSerializer(serializers.ModelSerializer):
order_items = OrderItemUpdateSerializer(many=True)
billing_details = BillingDetailsSerializer()
class Meta:
model = Order
fields = ['id','ordered','order_status','order_items','total_price','billing_details']
def update(self, instance, validated_data):
instance.order_status = validated_data.get('order_status')
instance.ordered = validated_data.get('ordered')
#billing_details_logic
billing_details_data = validated_data.pop('billing_details',None)
if billing_details_data is not None:
instance.billing_details.address = billing_details_data['address']
instance.billing_details.save()
#order_items_logic
instance.save()
#instance.order_items.clear()
order_items_data = validated_data.pop('order_items')
print(order_items_data)
for order_item_data in order_items_data:
oi, created = OrderItem.objects.update_or_create(
id = order_item_data['id'],
defaults={
'quantity' : order_item_data['quantity'],
'order_item_status': order_item_data['order_item_status'] #
}
)
instance.save()
return super().update(instance,validated_data)
My orderdict after print command.
[OrderedDict([('order', <Order: mylo#gmail.com>), ('item', <Product: AaaAAAAUpdatedpicturetest>), ('order_variants', <Variants: AgainTest>), ('quantity', 3), ('order_item_status', 'To_Ship'
)]), OrderedDict([('order', <Order: mylo#gmail.com>), ('item', <Product: Kiara Terrell>), ('order_variants', <Variants: OAXWadRTZ_12C>), ('quantity', 3), ('order_item_status', 'To_Ship')])]
As we can see, there is no id in the print result. What is the issue? Also, I am not sure if I can use the for loop in the above way for iterating over multiple OrderDict for updating the values.
DRF doc's say's i need to override serializers create and update methods to update and/or create nested data. But when i am trying to edit existing descriptions my code creates a new one. Is there a simple way to detect which descriptions was edit and update only it?
class TaskSerializer(ModelSerializer):
url = HyperlinkedIdentityField(
view_name='tasks:tasks-detail',
lookup_field='pk',
)
author = SlugField(source='author.username')
executor = SlugField(source='executor.username')
descriptions = DescriptionSerializer(many=True)
class Meta:
model = Task
fields = (
'pk',
'url',
'title',
'project',
'status',
'author',
'executor',
'descriptions'
)
def create(self, validated_data):
descriptions_data = validated_data.pop('descriptions', None)
author = validated_data.pop('author', None)
executor = validated_data.pop('executor', None)
try:
task_author = User.objects.get(username=author['username'])
task_executor = User.objects.get(username=executor['username'])
except User.DoesNotExist:
raise ValidationError(
_("Такого пользователя не сущетсвует!"))
task = Task.objects.create(author=task_author, executor=task_executor, **validated_data)
if descriptions_data:
for description in descriptions_data:
description, created = Description.objects.get_or_create(
text=description['text'],
task=task
)
task.descriptions.add(description)
return task
def update(self, instance, validated_data):
descriptions_data = validated_data.pop('descriptions', None)
instance.title = validated_data.get('title', instance.title)
instance.project = validated_data.get('project', instance.project)
instance.status = validated_data.get('status', instance.status)
author = validated_data.pop('author', None)
executor = validated_data.pop('executor', None)
try:
if author:
task_author = User.objects.get(username=author['username'])
instance.author = task_author
if executor:
task_executor = User.objects.get(username=executor['username'])
instance.executor = task_executor
except User.DoesNotExist:
raise ValidationError(
_("Такого пользователя не сущетсвует!"))
descriptions_list = []
if descriptions_data:
for description in descriptions_data:
description, created = Description.objects.get_or_create(
text=description["text"],
task=instance
)
descriptions_list.append(description)
instance.descriptions.set(descriptions_list)
instance.save()
return instance
class DescriptionSerializer(ModelSerializer):
class Meta:
model = Description
fields = (
'pk',
'text',
)
class Task(models.Model):
STATUS_CHOICES = (
(1, _("В процессе разработки")),
(2, _("В процессе тестирования")),
(3, _("На ревью")),
(4, _("Открыта")),
(5, _("Закрыта"))
)
title = models.CharField(_('Название'), max_length=60)
project = models.CharField(_('Название проекта'), max_length=60)
status = models.IntegerField(_('Статус'), choices=STATUS_CHOICES,
default=4)
author = models.ForeignKey(settings.AUTH_USER_MODEL,
max_length=60, on_delete=models.CASCADE,
related_name='author',
verbose_name=_('Автор'),
validators=[validate_user])
executor = models.ForeignKey(settings.AUTH_USER_MODEL,
max_length=60, on_delete=models.CASCADE,
related_name='executor',
verbose_name=_('Исполнитель'),
validators=[validate_user])
def __str__(self):
return self.title
def __unicode__(self):
return u'{}'.format(self.title)
class Meta:
verbose_name = _('Задача')
verbose_name_plural = _('Задачи')
class Description(models.Model):
task = models.ForeignKey(Task, on_delete=models.CASCADE,
related_name='descriptions')
text = models.TextField(_('Описание'))
def __str__(self):
return '#{}'.format(self.pk)
def __unicode__(self):
return u'#{}'.format(self.pk)
class Meta:
verbose_name = _('Описание')
verbose_name_plural = _('Описания')
Query :
I have a GET request which gives the data from the 2 models (single_tracklog_object in View). However, when I serialize this object instance using the serializers I am getting an empty data for devices as below.
{
"lat": "51.0038",
"lon": "8.0038",
"speed": 50,
"course": 5,
"device": {} # this needs to be having a value but is empty.
}
I am not understanding why its happening. Please guide me on this.
My Models :
class Tracklogs(models.Model):
tracklog_id = models.AutoField(primary_key=True)
device = models.ForeignKey(Tracking_devices, related_name='tracklogs')
lat = models.CharField(max_length=10, null=False)
lon = models.CharField(max_length=11, null=False)
.........
#timestamps
tracker_datetime = models.DateTimeField(blank=True, null=True)
class Meta:
get_latest_by = "tracker_datetime"
class Tracking_devices(models.Model):
device_id = models.AutoField(primary_key=True)
device_type = models.ForeignKey(Device_type)
user = models.ForeignKey(User, null=False)
name = models.CharField(max_length=100)
description = models.CharField(max_length=256, blank=True, null=True)
My View :
serializer_class = ShowLocationInfoSerializer
def get(self, request, *args, **kwargs):
# get the imei from the url
imei = self.kwargs['imei']
try:
single_tracklog_object = Tracklogs.objects.filter(device__imei = imei).values('lat', 'lon','speed','course','device','device__name').latest()
# Here its causing problem!!!
serializer = self.serializer_class(single_tracklog_object)
return Response(serializer.data)
except ObjectDoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
My Serializer:
class Tracking_DeviceSerializer(serializers.ModelSerializer):
name = serializers.CharField(read_only=True)
class Meta:
model = Tracking_devices
fields = ('name')
class ShowLocationInfoSerializer(serializers.ModelSerializer):
lat = serializers.CharField(read_only=True)
lon = serializers.CharField(read_only=True)
speed = serializers.IntegerField(read_only=True)
course = serializers.FloatField(read_only=True)
device = Tracking_DeviceSerializer()
class Meta:
model = Tracklogs
fields = ('lat', 'lon', 'tracker_datetime', 'speed', 'course', 'device' )
Thanks in advance.
I want to display a specific Value from a JSON-Field in Django Admin list_display.
models.py:
class Foo(models.Model):
client = models.ForeignKey(Client, verbose_name="Kunde")
description = models.CharField(verbose_name=u'Titel', max_length=100)
description_file = models.FileField(verbose_name="Vorschau", upload_to='postings', blank=True, help_text=u'Vorschau/Endfassung')
accepted_by_client = models.BooleanField(verbose_name="abgenommen", help_text=u"")
needs_correction = models.BooleanField(verbose_name=u"Korrektur nötig", help_text=u"")
active = models.BooleanField(verbose_name="Publiziert", help_text=u"")
ctime = models.DateTimeField(verbose_name="Angelegt am", blank=True, null=True)
valid_until = models.DateField(verbose_name=u"gültig bis", blank=True, null=True, default = lambda: datetime.datetime.now()+datetime.timedelta(days=28) )
valid_from = models.DateField(verbose_name=u"gültig ab", blank=True, default=datetime.datetime.now )
link = models.CharField(verbose_name="Formular", max_length=255, blank=True, help_text="generierter Link zum Formular")
admin_notes = models.TextField(u'Notizen für Mitarbeiter', blank=True, help_text=u"")
client_notes = models.TextField(verbose_name=u"Notizen für Kunde", blank=True, help_text=u"")
context = JsonField()
def __unicode__(self):
return self.client.company_name + ' : ' + str(self.id)
admin.py:
class FooAdmin(admin.ModelAdmin):
#list view
def apis(self, object):
data = Foo.context['bar']
return data
list_display = (
'id',
'client',
'description',
'active', 'ctime',
'valid_until',
'valid_from',
'clickable_preview_link',
'clickable_editor_link',
'apis'
)
admin.site.register(Foo, FooAdmin)
My Problem is, I can't access the single values from the JSON-Field "context". I'm only receiving a empty column.
How can I do this?
Thanks in advance!
class FooAdmin(admin.ModelAdmin):
#list view
def apis(self, object):
data = Foo.context['bar']
return data
list_display = (
'id',
'client',
'description',
'active', 'ctime',
'valid_until',
'valid_from',
'clickable_preview_link',
'clickable_editor_link',
'apis',
'json_data'
)
def json_data(self, obj):
for key, value in obj.context:
return "{0}: {1}".format(key, value)
return ''