Django rest nested serializer not displaying fields - django

I have a model Workflow and WorkflowLevel. Each workflow has many WOrkflow levels .Im trying to use nested serializer :
class WorkflowLevelSerializer
(serializers.ModelSerializer):
class Meta:
model = WorkflowLevel
fields = '__all__'
class
WorkflowSerializer
(serializers.ModelSerializer):
levels = WorkflowLevelSerializer(many=True)
class Meta:
model = Workflow
fields = ('id', 'name', 'description',
'tenant', 'levels')
models.py:
class Workflow(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=32, default=None, null=True)
description = models.CharField(max_length=100, default=None, null=True)
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, default=None,
null=False)
class Meta:
unique_together = ('name', 'tenant',)
class WorkflowLevel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE,
default=None, null=False)
level = models.IntegerField(default=None, null=False)
operation = models.CharField(max_length=32, default=None, null=False)
class Meta:
unique_together = ('workflow', 'level',)
The levels field is not displaying in the workflow listAPI view .
Getting error:
Got AttributeError when attempting to get a value
for field `levels` on serializer
`WorkflowSerializer`.
The serializer field might be named incorrectly
and not match any attribute or key on the
`Workflow` instance.
Original exception text was: 'Workflow' object
has no attribute 'levels'.

You can define related_name in the Model like this:
workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE, related_name="levels", default=None, null=False)
I am using related_name='levels', so that in Serializer, it will use that reverse relationship name to fetch WorkflowLevel data from db.

Related

How to include ManyToMany Fields in DjangoRestFramework?

class EntityServiceSerializer(serializers.ModelSerializer):
class Meta:
model = Service
fields = '__all__'
class EntityCreateSerializer(serializers.ModelSerializer):
entity_service = EntityServiceSerializerThrough(read_only=True, source='serviceschedule_set', many=True)
class Meta:
model = Entity
fields = '__all__'
Model looks like this
class Entity(models.Model):
entity_service = models.ManyToManyField(Service, through='ServiceSchedule')
class ServiceSchedule(models.Model):
service = models.ForeignKey(Service, on_delete=models.CASCADE)
entity = models.ForeignKey(Entity, on_delete=models.CASCADE)
class Service(models.Model):
service_name = models.CharField(max_length=256, null=True)
slug = models.SlugField(max_length=128, unique=True, null=False, editable=False)
created_at = models.DateTimeField(editable=False, default=timezone.now)
updated_at = models.DateTimeField(default=timezone.now)
animal = models.ForeignKey(Animal, on_delete=models.CASCADE, default=None)
I have these serializers (there are more fields in entity model, but they're irrelevant since the only problem i have is with the Many2Many)
The thing is, when i put in body "entity_service": [1,2] in the response i still get = []. Even though i have in my database Services with pk 1,2,3,4.
Do you know how can i make it work?
Try it without a source as the field name is the same as the model field name
class EntityCreateSerializer(serializers.ModelSerializer):
entity_service = EntityServiceSerializerThrough(read_only=True, many=True)
class Meta:
model = Entity
fields = '__all__'

Serialize and create one-to-one relation with parent_link true in django and django rest framework

How to save the object with one-to-one relation and having parent_link=True using serializer. Below are my models and serializer having some fields from the actual model that I wanted to implement. I am not able to save the 'user' relation in the database. It is throwing the integrity error.
class Audit(models.Model):
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
updated_at = models.DateTimeField(auto_now=True, null=True)
class Meta:
abstract = True
class User(Audit):
class Meta:
db_table = 'user'
email = models.EmailField(unique=True)
password = models.TextField()
is_active = models.BooleanField(default=False)
class UserProfile(User):
class Meta:
db_table = 'user_profile'
user = models.OneToOneField(User, on_delete=models.CASCADE, parent_link=True,
primary_key=True)
address = models.TextField(null=True)
dob = models.DateField()
language = models.CharField(max_length=50, null=True)
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ['user', 'address', 'dob', 'language']
And the requested data looks like this.
{
"email": "abc#pqr.com",
"password": "1234",
"dob": "2021-12-11",
"language" : "English"
}
You can pass user when saving serializer :
serializer.save(user=<USER>)
Note that if you want to create user when creating user profile, you should override create() method in your serializer, first create your user, then create user profile, and pass created user to it

Serializing specific fields from another model

I was trying to serialize policy_length, coverage_amount from Policy model and use it in a serializer that was using Insuree model.
I'm using Policy and Insuree models:
Policy model
class Policy(TimeStampedModel):
policy_length = models.FloatField(max_length=2, blank=True, null=True)
coverage_amount = models.FloatField(max_length=256, blank=True, null=True)
Insuree model
class Insuree(TimeStampedModel):
user = models.OneToOneField(
'User', related_name='insuree', null=False, on_delete=models.CASCADE,
primary_key=True)
coverage_amount = models.ForeignKey(Policy, on_delete=models.CASCADE, max_length=256, blank=True, null=True)
policy_length = models.ForeignKey(Policy, on_delete=models.CASCADE, max_length=2, blank=True, null=True)
class PolicySelectionSerializer(serializers.ModelSerializer):
class Meta:
model = Insuree
fields = ('age', 'gender', 'disposable_income') #Current fields
fields = ('age','gender',disposable_income', 'policy_length', 'coverage_amount') #The field I need and want to do
You may use Nested Serializer.
PolicySerializer(ModelSerializer)
class Meta:
model = Policy
fields = ( 'policy_length', 'coverage_amount')
InsureeSerializer(ModelSerializer)
class Meta:
policy = PolicySerializer(many = True)
model = Insuree
fields = ('age', 'gender', 'disposable_income', 'policy',)

django select only specific fields from many to many field in serializer

My models:
class RequisiteItem(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
enrollable = models.ForeignKey(Enrollable, on_delete=models.CASCADE)
created_by = models.ForeignKey(ElsUser, on_delete=models.CASCADE)
completed_within_days = models.IntegerField()
date_completed_by = models.DateTimeField(default=now, editable=False)
class Requisite(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(default=None, blank=True, null=True, max_length=255)
description = models.CharField(default=None, blank=True, null=True, max_length=255)
items = models.ManyToManyField(RequisiteItem, blank=True)
enrolments = models.ManyToManyField(Enrollee, blank=True)
created_by = models.ForeignKey(ElsUser, on_delete=models.CASCADE, related_name="requisites", default=None)
timestamp = models.DateTimeField(default=now, editable=False)
#property
def created_by_user(self):
return self.created_by.username
Serializer class:
class RequisiteSerializer(serializers.ModelSerializer):
created_by = serializers.CharField(source='created_by_user')
class Meta:
model = Requisite
fields = ('id', 'name', 'description', 'items', 'enrolments', 'created_by', 'timestamp')
read_only_fields = ['id']
depth = 1
I have enrolments ,created by,requisite items which are foreign keys and manytomany fields etc .In my list API i want only specific fileds from the foreign key to be displayed. For example in the created by field, Elsuser is a custom user inheriting from AbstractUser . I want only the username and email fields from this model and not the entire fields. Similar case for the manyto many fields . How do i implement this?
You can create a serializer to get only the required fields. Example:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('') #the fields you require to display
Then change your serializer as:
class RequisiteSerializer(serializers.ModelSerializer):
created_by = UserSerializer()
class Meta:
model = Requisite
fields = ('id', 'name', 'description', 'items', 'enrolments', 'created_by', 'timestamp')
read_only_fields = ['id']
depth = 1

access to another model fields with foreign key in django admin

I have a contact us class in django model,that using "user_id" foreign key,in admin.py file,i want using userprofile data with user_id key,such as "name" filed,in userprofile model "user_id" is foreign_key too,how can do it?
in models.py :
class Ticket(models.Model):
user_id = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, editable=False, verbose_name="user")
replier_id = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name="replier")
guest_name = models.CharField(max_length=50, blank=True, null=True, editable=False)
guest_email = models.CharField(max_length=255, blank=True, null=True, editable=False)
user_phone = models.CharField(max_length=13, blank=True, null=True, editable=False)
subject = models.CharField(max_length=255, blank=True, null=True, editable=False)
message = models.TextField(editable=False)
reply = models.TextField(blank=True, null=True)
date = models.DateTimeField(auto_now=True, editable=False)
reply_date = models.DateTimeField(blank=True, null=True)
user_ip = models.GenericIPAddressField(editable=False)
in admin.py
class ContactUsAdmin(admin.ModelAdmin):
actions = None
fields = ('user_name', 'user_email', 'subject', 'date', 'message', 'user_phone', 'reply')
list_display = ('user_name', 'user_email', 'subject', 'date', 'is_replied')
list_filter = ('date',)
search_fields = ['user_id__first_name', 'user_id__email', 'guest_name', 'guest_email', 'subject', 'message']
readonly_fields = ('user_name', 'user_email', 'subject', 'date', 'message', 'user_phone', 'reply_date')
i want show name from UserProfile class in admin.py fields
By the question title of your query. I am giving an incentive how to do that in django:
class Album(models.Model):
AlbumName = models.CharField(max_length=250)
AlbumSinger = models.CharField(max_length=250)
AlbumGenre = models.CharField(max_length=250)
AlbumImage = models.FileField(null=True)
SingerImage = models.FileField(null=True)
class Musics(models.Model):
album = models.ForeignKey(Album, related_name='music')
MusicName = models.CharField(max_length=250)
MusicLength = models.CharField(max_length=250)
MusicFile = models.FileField(null=True)
Using foreignkey album in Musics. you can access to all the music according to their album. And to access them in admin, just import class name and do the following:
admin.site.register(Album)
admin.site.register(Musics)
I hope it will clear your confusion.
finally i resolve it,when in userprofile model,user_id has "profile" related_name,in every where,with user_id foreign key we have all related field from every model that user_id is foreign key in it
you can see those with using dir("you user_id instance").
so,with user_id.profile.name i get the profile name of user,without any importing or change!