Rename Fields of Model in Serializer and Form - Django - django

I want to change field names. In my model field name start with prefix timesheet. And when i am using api i have to use that timesheet prefix. I want to remove that prefix instead keep jobs, clock_in_date, clock_out_date.... How can i rename field names so that when i am send data from api body should contain names without timesheet prefix
class TimesheetSerializer(serializers.ModelSerializer):
timesheet_hours = TimesheetHourSerializer(many=True, read_only=True)
class Meta:
model = TimesheetEntry
fields = [
'id',
'timesheet_jobs',
'timesheet_clock_in_date',
'timesheet_clock_in_time',
'timesheet_clock_out_date',
'timesheet_clock_out_time',
'timesheet_note',
'timesheet_hours',
]
Models.py
class TimesheetEntry(models.Model):
timesheet_users = models.ForeignKey(User, on_delete=models.CASCADE,related_name='timesheet_users')
timesheet_jobs = models.ForeignKey(Jobs, on_delete=models.CASCADE,related_name='timesheet_jobs', blank=True, null=True)
timesheet_clock_in_date = models.DateField()
timesheet_clock_in_time = models.TimeField()
timesheet_clock_on = models.DateTimeField(auto_now_add=True)
timesheet_clock_in_by = models.ForeignKey(User, on_delete=models.CASCADE,related_name='timesheet_user_clock_in_by')
timesheet_clock_out_date = models.DateField(blank=True, null=True)
timesheet_clock_out_time = models.TimeField(blank=True, null=True)

class TimesheetSerializer(serializers.ModelSerializer):
timesheet_hours = TimesheetHourSerializer(many=True, read_only=True)
jobs = serializers.CharField(source='timesheet_jobs')
class Meta:
model = TimesheetEntry
fields = [
'id',
'jobs',
.......
]
you can simply use this. This would work for write operations also

Related

Getting the whole object of a related field in django

I have a model like this:
class Cart(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, null=True)
class Reception(models.Model):
PAYMENT_STATUS_PENDING = 'P'
PAYMENT_STATUS_COMPLETE = 'C'
PAYMENT_STATUS_FAILED = 'F'
PAYMENT_STATUS_CHOICES = [
(PAYMENT_STATUS_PENDING, 'Pending'),
(PAYMENT_STATUS_COMPLETE, 'Complete'),
(PAYMENT_STATUS_FAILED, 'Failed')
]
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, null=True)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
entry_date = models.DateField()
total_price = models.IntegerField()
payment_status = models.CharField(
max_length=1,
choices=PAYMENT_STATUS_CHOICES,
default=PAYMENT_STATUS_PENDING
)
My question is:
How can I get a particular Cart record from the Reception model?
I tried using this serializer:
class ReceptionSerializer(serializers.ModelSerializer):
class Meta:
model = Reception
fields = ['id', 'customer', 'entry_date', 'payment_status', 'cart']
but it only returns the id of a cart. I want to return the whole object of that specific cart.
How can I do that?
If you want to utilize nested serialization, one possible solution would be to define CartSerializer and override the cart field of the ReceptionSerializer class as follows
class CartSerializer(serializers.ModelSerializer):
class Meta:
model = Cart
fields = ['id', 'customer']
class ReceptionSerializer(serializers.ModelSerializer):
cart = CartSerializer(many=True)
class Meta:
model = Reception
fields = ['id', 'customer', 'entry_date', 'payment_status', 'cart']
However, please note that the cart field will become read-only this way.

Django Rest Framework - how to get only one field from related models set

I have following models:
from django.db import models
class City(models.Model):
name = models.CharField(max_length=30)
last_update = models.DateTimeField(null=True)
class BusStop(models.Model):
city = models.ForeignKey(City, on_delete=models.CASCADE)
name = models.CharField(max_length=200, blank=True, default='')
Now using Django Rest Framework, I would like to create serializer that will return City details along with the list of all BusStops in the city - but I want the list to be only strings with BusStop names, like this:
{
"id": 1
"name": "City"
"last_update": "2019-09-19T22:13:54.851363Z"
"bus_stops": [
"stop1",
"stop2",
"stop3"
]
}
What I've tried so far is following serializers:
from rest_framework import serializers
class BusStopSerializer(serializers.ModelSerializer):
class Meta:
model = BusStop
fields = ('name', )
class CityDetailsSerializer(serializers.ModelSerializer):
busstop_set = BusStopSerializer(many=True)
class Meta:
model = City
fields = ('id', 'name', 'last_update', 'busstop_set')
But this creates list of objects with 'name' in them. So, how can I create a list with only BusStop names (as strings) in it?
Instead of the extra BusStopSerializer you could use a StringRelatedField:
# models.py
class BusStop(models.Model):
city = models.ForeignKey(City, on_delete=models.CASCADE)
name = models.CharField(max_length=200, blank=True, default='')
def __str__(self):
return self.name
# serializers.py
class CityDetailsSerializer(serializers.ModelSerializer):
bus_stops = StringRelatedField(many=True)
class Meta:
model = City
fields = ('id', 'name', 'last_update', 'bus_stops')
StringRelatedField, as recommended by wfehr, will only work as long as the __str__ method of BusStop only returns the name. An alternative is to use SlugRelatedField which allows you to specify a particular field from the related model, and has no dependency on __str__.
bus_stops = SlugRelatedField(many=True, slug_field='name')

How to serialize nested model in Django-Rest

I have been trying to use with the a legacy database. I have created models file using inscpectdb but now I am not able to perform joins on the table.
I have two tables job_info and username_userid.
Here is my models.class file:
class UseridUsername(models.Model):
userid = models.IntegerField(blank=True, null=True)
username = models.CharField(max_length=100, blank=True, null=True)
class Meta:
managed = False
db_table = 'userid_username'
class LinuxJobTable(models.Model):
job_db_inx = models.AutoField(primary_key=True)
mod_time = models.IntegerField()
account = models.TextField(blank=True, null=True)
exit_code = models.IntegerField()
job_name = models.TextField()
id_job = models.IntegerField()
id_user = models.OneToOneField(UseridUsername , on_delete=models.CASCADE,db_column="id_user")
class Meta:
managed = False
db_table = 'linux_job_table'
Now how can I get all the values from LinuxJobTable and username from UseridUsername for the corresponding user.
Heren is my serializable class :
class UseridUsernameSerializer(serializers.ModelSerializer):
class Meta:
model = UseridUsername
fields = ('userid','username')
class UserSerializer(serializers.ModelSerializer):
class Meta:
username = UseridUsernameSerializer(many=False)
model = LinuxJobTable
fields = ('account','mod_time','username')
When I try to access it, it gives ' Field name username is not valid for model LinuxJobTable.' error.
The error is raising because UserSerializer search for a relates fields named username and it doesn't find a one. In your case the ralated field is named as id_user, So you have to mention it via source parameter.
So, Try this
class UserSerializer(serializers.ModelSerializer):
username = UseridUsernameSerializer(many=False, source='id_user')
class Meta:
model = LinuxJobTable
fields = ('account', 'mod_time', 'username')

How to serialize a self recursive many-to-many model using a through table in django rest_framework?

i am developing a rest API using django rest framework and i am stuck at a serializer the idea is to serialize a self recursive many to many model using a through table my code is:
model.py:
class Patient(models.Model):
class Meta:
db_table = 'patients'
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
id_card = models.CharField(max_length=45)
dob = models.DateField()
gender = EnumChoiceField(enum_class=Gender)
patientscol = models.CharField(max_length=45)
fk_user = models.ForeignKey(Users, related_name='user_patient', on_delete=models.CASCADE)
relative = models.ManyToManyField("self", through='PatientHasRelative')
class PatientHasRelative(models.Model):
class Meta:
db_table = 'patients_has_relatives'
fk_patient = models.ForeignKey(Patient, related_name='patient_has', on_delete=models.CASCADE)
fk_relative_patient = models.ForeignKey(Patient, related_name='patient_relative', on_delete=models.CASCADE)
relationship = EnumChoiceField(enum_class=Relationship)
my serializer.py is:
class PatientSerializer(serializers.ModelSerializer):
class Meta:
model = Patient
fields = ('__all__')
id = serializers.UUIDField(read_only=True)
id_card = serializers.CharField(required=True, max_length=45)
dob = serializers.DateField(required=True)
gender = EnumChoiceField(enum_class=Gender)
fk_user = serializers.PrimaryKeyRelatedField(required=True, queryset=Users.objects.all())
relative = PatientSerializer(read_only=True, required=True)#problem is here i cant use PatientSerializer here
class PatientHasRelativeSerializer(serializers.ModelSerializer):
class Meta:
model = PatientHasRelative
fields = ('__all__')
fk_patient = serializers.PrimaryKeyRelatedField(required=True, queryset=Patient.objects.all())
fk_relative_patient = serializers.PrimaryKeyRelatedField(required=True, queryset=Patient.objects.all())
relationship = EnumChoiceField(enum_class=Relationship)
a little help would be appreciated
To accomplish this you need to define related_name in the source model on the source field ie add
class Patient(models.Model):
relatives = models.ManyToManyField(
"self", through='PatientHasRelative', related_name='patients')
with this related_name you can easily access -- add/delete/set relatives/patients on either side of the relationships in the serializers
You can either do this using intermediary model
relative = Patient(**key_value_fields)
patient = Patient(**key_value_field)
PatientHasRelative.objects.create(
relative=relative, patient=patient, through_defaults=(relationship ='value',))
or you can do this
relative.patients.add(patient, through_defaults=relationship ='value')
or this
patient.relatives.add(relative, through_defaults=relationship ='value')
example retrieving
patient.relatives.all()

Django GenericTabularInline: (admin.E302) 'ct_field' references 'content_type', which is not a field

I am trying to get a model (Prereq) with Generic Foreign Keys to appear in MyModel's admin.
models.py:
class MyModel(models.Model):
name = models.CharField(max_length=50, unique=True)
#etc
class Prereq(models.Model):
parent_content_type = models.ForeignKey(ContentType, related_name='prereq_parent')
parent_object_id = models.PositiveIntegerField()
parent_object = GenericForeignKey("parent_content_type", "parent_object_id")
prereq_content_type = models.ForeignKey(ContentType, related_name='prereq_item')
prereq_object_id = models.PositiveIntegerField()
prereq_object = GenericForeignKey("prereq_content_type", "prereq_object_id")
prereq_invert = models.BooleanField(default=False, help_text = 'parent is available if user does NOT have this pre-requisite')
or_prereq_content_type = models.ForeignKey(ContentType, related_name='or_prereq_item', blank=True, null=True)
or_prereq_object_id = models.PositiveIntegerField(blank=True, null=True)
or_prereq_object = GenericForeignKey("or_prereq_content_type", "or_prereq_object_id")
or_prereq_invert = models.BooleanField(default=False, help_text = 'parent is available if user does NOT have this pre-requisite')`
Admin.py:
class PrereqInline(GenericTabularInline):
model = Prereq
fk_name = "prereq_parent" #tried "parent_object" also
class MyModelAdmin(admin.ModelAdmin):
list_display = ('name', ...etc)
inlines = [
PrereqInline,
]
admin.site.register(MyModel, MyModelAdmin)
How to I solve the error I am getting?
<class 'my_app.admin.PrereqInline'>: (admin.E302) 'ct_field' references 'content_type', which is not a field on 'my_app.Prereq'.
Figured it out:
GenericTabularInline required the addition of ct_field and ct_fk_field because those fields did not use the default names of content_type and object_id respectively
class PrereqInline(GenericTabularInline):
model = Prereq
ct_field = "parent_content_type"
ct_fk_field = "parent_object_id"
fk_name = "parent_object"