serializer.DictField does not save to database - django

I have this model:
class x(model.Models):
name = models.CharField(max_length=50, unique=True)
y = models.ManyToManyField(Y, related_name='y', db_table='x_y',
blank=False,null=False)
and this serializer:
class Serializer(DynamicFieldsModelSerializer):
class Meta:
model = models.x
fields = '__all__'
when I post data to this model I need to set this fields:
'name':['some name'],'y':['1','2']
this will make a row in database x with:
id | name
1 | some name
and two row in database x_y with:
id| x_id | y_id
1 | 1 | 1
2 | 1 | 2
the problem is that front end dose not send me 'name' and 'y' ,but send me 'name' and 'y[]', so in order to get data I needed to add this to my serializer class:
y= serializers.DictField(child=serializers.IntegerField(min_value=0, max_value=2))
but the result is that no data will save in x_y table.I dont know how to solve this

One issue that stands out to me is that you're using a DictField to handle a list of integers.
Presuming the integers are actually the primary key of your Y model, have you tried using y = PrimaryKeyRelatedField(many=True)? This seems like what you would be after.

Related

How to get count of subjects taken by each student?

I've two models 'Students' and 'Enrollments'.
The schema for these is as below:
class Students(models.Model):
id = models.AutoField(primary_key=True, unique=True)
name = models.CharField()
class Enrollments(models.Model):
enroll_id = models.AutoField(primary_key=True, unique=True)
student_id = models.ForeignKey(Students, on_delete=models.CASCADE)
subjects = models.charField()
I'm trying to achieve the result of following SQL query in Django Rest Framework, for getting number of subjects enrolled by students (individually).
select
s.id, s.name, count(e.subjects) as count
from Students as s
left outer join Enrollments as e
on e.student_id_id = s.id
group by s.id, s.name, e.subjects
order by count asc;
This query returns result like:
---------------------------
| id | name | count |
---------------------------
| 1 | a | 1 |
| 2 | b | 0 |
| 3 | c | 2 |
---------------------------
Can anyone please help me acheive this kind of result.
Note: I need 0 count students details also.
What you can do is when you are creating a serializer, you can add a serializer method field which will get the count for you.
Add this at the top of your serializer:
count = serializers.SerializerMethodField('get_count')
Then add a function inside your serializer like this:
def get_count(self, obj):
try:
return Enrollments.objects.filter(student_id=obj.id).count()
except:
return None
Finally, add 'count' to your field list. You can then add as many fields as you want. I hope this will get you your desired result. Also don't forget to use "select_related" in the ORM inside your view to reduce the amount of queries.

Django filter objects based on the value of a field of the last data in another model

There are 2 models
class A(models.Model):
name = models.TextField()
class B(models.Model):
a = models.ForeignKey(A)
status = models.BooleanField(default=False)
Now I want to filter objects of class A based on the last data in class B status.
if there are 2 datas of Model B
id | a | status
1 | a | True
2 | abc | False
3 | a | False
4 | abc | True
So if I want to filter objects of Model A which are having status False.
In this case it will give me
a.
If I wanted to filter objects of Model A which are having status True.
In this case it should return me
abc.
I want to write a query something like
A.objects.filter(b__status__last=True)
Is it possible to do using filters?
I think you could use annotate effectively here.
A.objects.annotate(latest_b=Max("b__created_at")).filter(b__status=True).latest('latest_b')
Here, we're annotating each object of A to have a latest_by field and then fetching the latest object after filtering by the status of b. This should work properly.
Please try:
from django.db.models import Max, F
A.objects.annotate(latest=Max('b__id')).filter(b__id=F('latest'),b__status=True)

How to fetch custom column which does not exist in database table?

How can I implement followig SQL QUERY in django rest framework
`SELECT `id` , `name_hi` as hi , `name_en` as en , false as `checked` FROM `tab_name`
where checked does not exist in the database table i.e. it is not a column .
id | hi | en | checked
1 | xx | xx | 0
2 | hi2| en2| 0
3 | hi3| en3| 0
I am using Django Rest framework.
How can I rename these fields also include checked
So far I have tried in serializer
class TabSerializer(serializers.ModelSerializer):
hi = serializers.CharField(source='name_en')
en = serializers.CharField(source='name_en')
class Meta:
model = Tab
fields =('id','name_en','name_hi')
It just return id name_en and name_hi irrespective of hi ,en and checked.
You set it in serializer for column alias
For column table alias
class TabSerializer(serializers.ModelSerializer):
hi = serializers.CharField(source='name_hi')
en = serializers.CharField(source='name_en')
class Meta:
model = TabFaultOption
fields =('id','hi','en')
Now for column which does not exist in the database you need to change in the related model
model.py
class Tab(models.Model):
id = models.IntegerField()
name_hi = models.CharField(max_length=1000)
name_en = models.CharField(max_length=1000)
checked=False
class Meta:
managed = False
db_table = 'tab'
Now in serializer include the checked column
class TabSerializer(serializers.ModelSerializer):
hi = serializers.CharField(source='name_en')
en = serializers.CharField(source='name_en')
checked= false
class Meta:
model = Tab
fields =('id','hi','en','checked')

Django join on multiple foreign fields (left join)

I'm using django 1.10 and have the following two models
class Post(models.Model):
title = models.CharField(max_length=500)
text = models.TextField()
class UserPost(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
approved = models.BooleanField(default=False)
How do I get a list of all the posts including the 'approved' property for the logged in user if exists? So instead of multiple queries, it would be one left join query, pseudo-code:
select * from posts as p
left join user_posts as up
on up.post_id = p.post_id
and up.user_id = 2
Output
post_id | title | text | user_id | approved
1 | 'abc' | 'abc' | 2 | true
2 | 'xyz' | 'xyz' | null | null
3 | 'foo' | 'bar' | 2 | true
I created the models this way because the 'approved' property belongs to the user. Every user can approve/reject a post. The same post could be approved and rejected by other users. Should the models be setup differently?
Thanks
Update:
I'm trying to create a webpage to display all available posts and highlight the ones that the current user approved. I could just list all posts and then for each post check if the 'UserPost' table has a value, if yes get the approved property else ignore. But that means if I have 100 posts I'm making 100 + 1 calls to the db. Is it possible to do 1 call using ORM? If this is not possible, should the models be setup differently?
Then I think you need something like this:
Post.objects.all().annotate(
approved=models.Case(
models.When(userpost_set__user_id=2,
then=models.F('userpost__approved')),
default=models.Value(False),
output_field=models.BooleanField()
)
)

django accessing raw many to many created table fields

Model:
class Subjects (models.Model):
name = models.CharField(max_length=100)
places = models.CharField(max_length=100)
class Student (models.Model):
name = models.CharField(max_length=40)
lastname = models.CharField(max_length=80)
subjects = models.ManyToManyField(Subjects, blank=True)
Django creates appname_student_subjects when I use model above.
appname_student_subjects table looks for example, like this:
id | student_id | subjects_id
-----------------------------------------
1 | 1 | 10
2 | 4 | 11
3 | 4 | 19
4 | 5 | 10
...
~1000
How can I access subjects_id field and count how many times subjects_id exists in the table above (and then do something with it). For example: If subject with id 10 exists two times the template displays 2. I know that I should use "len" with result but i don't know how to access subject_id field.
With foreign keys I'm doing it like this in a for loop:
results_all = Students.objects.filter(subject_id='10')
result = len(results_all)
and I pass result to the template and display it within a for loop but it's not a foreign key so it's not working.
You can access the through table directly.
num = (Students.subjects # M2M Manager
.through # subjects_students through table
.objects # through table manager
.filter(student_id=10) # your query against through table
.count())