class Item(models.Model):
name = models.CharField(max_length=20)
class Meals(models.Model):
name = models.CharField(max_length=50)
ingredients = models.ManyToManyField(Item, through='MealRecipe')
class Menu(models.Model):
name = models.CharField(max_length=50)
meals = models.ManyToManyField(Meals,through='CompMenu')
class CompMenu(models.Model):
TYPE_COMP = (
('B', 'Breakfast'),
('L', 'Lunch'),
('D', 'Dinner')
)
menu = models.ForeignKey(Menu)
meal = models.ForeignKey(Meals)
type = models.CharField(max_length=1, choices=TYPE_COMP)
class MealRecipe(models.Model):
meal = models.ForeignKey(Meal)
item = models.ForeignKey(Item)
qty = models.IntegerField()
If i need to serialze queryset how can i do it, there is no documentation about it, i need a JSON with Item_id, Item_name, MealRecipe_qty. Do i have to serialze all models ? I need this to manipualte the recipe quantities on the front end based on the selected menu.
receipes = MealRecipe.objects.filter(meal__in=meals_of_menu)
for receipe in receipes:
name = receipe.item.name
qty = receipe.qty
OR
MealRecipe.objects.filter(meal__menu=some_menu_instance).distinct()
I cannot figure out how to pass the result o this query to the front end
For your requirements of Item_id, Item_name, MealRecipe_qty, you will need to serialize the MealRecipe model and the Item model.
Also give a related name to item in MealRecipe model
class MealRecipe(models.Model):
meal = models.ForeignKey(Meal)
item = models.ForeignKey(Item,related_name='qty')
qty = models.IntegerField()
And your serializers will be
class MealRecipeSerializer(serializers.ModelSerializer):
class Meta:
model = MealRecipe
fields = ('qty')
class ItemSerializer(serializers.ModelSerializer):
qty = MealRecipeSerializer()
class Meta:
model = Item
fields = ('id','name','qty')
Also if you are passing a queryset to a serializer do it as, MealRecipeSerializer(many=True)
Related
I have a problem with creating new ratings for cars.
When i try to send a post request from Postman in order to create/add a new rating for a specific car i get the error:
The `.create()` method does not support writable nested fields by default.
These are my models:
class Car(models.Model):
name = models.CharField(max_length=50)
symbol = models.CharField(max_length = 5)
def __str__(self):
return self.name
class Type(models.Model):
name = models.CharField(max_length = 50)
fuel = models.CharField(max_length = 1)##1 or 2 for fuel type
car = models.ManyToManyField(Car)
def __str__(self):
return self.name
class Rating(models.Model):
rating = models.IntegerField(validators=[
MaxValueValidator(10),
MinValueValidator(0)
])
car = models.ForeignKey(Car, on_delete=models.CASCADE)
type = models.ForeignKey(Type, on_delete=models.CASCADE)
def __int__(self):
return self.rating
My serializers:
class CarSerializer(serializers.ModelSerializer):
class Meta:
model = Car
fields = ('id','name')
class TypeSerializer(serializers.ModelSerializer):
car = CarSerializer(many=True)
class Meta:
model = Type
fields = ('id','name', 'fuel', 'car')
#depth=2
class RatingSerializer(serializers.ModelSerializer):
type = TypeSerializer()
class Meta:
model = Rating
fields = ('id','rating', 'car', 'type')
def create(self, validated_data):
type_data = validated_data.pop('type')
rating = Rating.objects.create(**validated_data)
for t_data in type_data:
Type.objects.create(rating=rating, **t_data)
return rating
When i try to do a post request to rating such as :
{"rating":5, "car": 2,"type":{"id":1,"name":"OffRoad","fuel":"1","car":[{"id":2,"name":"Ford"}] } }
I get:
The `.create()` method does not support writable nested fields by default.
Please help if you can, ive been trying to fix this all day. Thank you!
here's my models:
class Recruteur(models.Model):
entrepriseName = models.CharField(max_length=50)
emplacement = models.CharField(max_length=50)
class Offre(models.Model):
title = models.CharField(max_length=100, blank=True, default=0)
idRecruteur = models.ForeignKey(Recruteur,verbose_name = "idRecruteur", on_delete=models.CASCADE, default=None)
and here's my api.py:
class VilleViewSet(ModelViewSet):
queryset = Offre.objects.values('idRecruteur__emplacement').distinct()
serializer_class = VilleSerializer
serializers.py:
class EmplacementSerializer(serializers.ModelSerializer):
class Meta:
model = Recruteur
fields = ('emplacement',)
class VilleSerializer(serializers.ModelSerializer):
emplacements = EmplacementSerializer(source='idRecruteur', read_only=True)
class Meta:
model = Offre
fields = ( 'emplacements',)
i was expecting a result like this
but i got nothing instead ..
Any ideas why?
You get nothing, because there is no emplacements field in Offre model. I guess, what you want is to get serialized Recruteur record, that is referenced by idRecruteur field. Try this:
class VilleSerializer(serializers.ModelSerializer):
idRecruteur = EmplacementSerializer(read_only=True)
class Meta:
model = Offre
fields = ( 'idRecruteur',)
In Django views, I want to fetch all details(Workeraccount.location,Workeravail.date, Workerprofile.*) for any particular wid=1.
SQL Query:
select * from Workeraccount,Workeravail,Workerprofile where Workerprofile.wid=1 and Workerprofile.wid=Workeravail.wid and Workeraccount.wid=Workerprofile.wid;
The corresponding models are as follows:
class Workeraccount(models.Model):
wid = models.ForeignKey('Workerprofile', db_column='wid', unique=True)
location = models.ForeignKey(Location, db_column='location')
class Meta:
managed = False
db_table = 'workerAccount'
class Workeravail(models.Model):
wid = models.ForeignKey('Workerprofile', db_column='wid')
date = models.DateField()
class Meta:
managed = False
db_table = 'workerAvail'
class Workerprofile(models.Model):
wid = models.SmallIntegerField(primary_key=True)
fname = models.CharField(max_length=30)
mname = models.CharField(max_length=30, blank=True, null=True)
lname = models.CharField(max_length=30)
gender = models.CharField(max_length=1)
age = models.IntegerField()
class Meta:
managed = False
db_table = 'workerProfile'`
You can do this:
workprofile = Workerprofile.objects.filter(id=1).first()
all_worker_avails = workprofile.workeravail_set.all()
all_workeraccounts = workprofile.workeraccount_set.all()
As Workeraccount and Workeravail are related through Workerprofile, you can get one queryset easily - you will need two separate ones.
You can also do the following:
all_worker_avails = Workeravail.objects.filter(wid=workprofile)
...
Here is how you can do it with only one database call:
workprofile = Workerprofile.objects.get(pk=1)
.select_related('workeravail_set', 'workerprofile_set')
This will fetch all the data for you at once, which can then be used with:
workprofile.workerprofile_set.location #Gets the Workeraccount.location
workprofile.workeravail_set.date #Gets the Workeravail.date
workprofile.fname #Example of Workerprofile.*
As an aside, if you want a shorter way to reference the foreign objects than the "*_set" method, you can set a related_name like
class Workeraccount(models.Model):
wid = models.ForeignKey('Workerprofile', db_column='wid', unique=True, related_name='waccount')
...
And then replace workeraccount_set with waccount
I am using serializers.GeoFeatureModelSerializer to serialize Model. I have a queryset
that is creating Left Outer Join. I want to serialize related Model fields
Here is my Model
class LookupTiming(models.Model):
day = models.CharField(max_length=7)
time_1 = models.TimeField()
time_2 = models.TimeField()
class Meta:
db_table = u'lookup_timing'
class Streets(models.Model):
name = models.CharField(max_length=50)
geometry = models.GeometryField(null=True, blank=True)
objects = models.GeoManager()
class Meta:
db_table = u'streets'
def __unicode__(self):
return '%s' % self.name
class StreetTimings(models.Model):
street= models.ForeignKey(Streets)
lookuptiming = models.ForeignKey(LookupTiming)
class Meta:
db_table = u'street_timings'
queryset =
Streets.objects.filter(streettimings_lookuptiming_isnull=True)
Serializer Class
class StreetSerializer(gis_serializer.GeoFeatureModelSerializer):
class Meta:
model = Streets
geo_field = "geometry"
id_field = False
fields = ('id', 'streettimings__lookuptiming__day', other fields)
Updated
I want to show following fields on response
Streets (id)
LookupTiming (day)
I want output like this query simple is that
SELECT "streets"."id", "lookuptiming"."day" FROM "streets"
LEFT OUTER JOIN "streettimings" ON ( "streets"."id" = "streettimings"."street_id" )
LEFT OUTER JOIN "lookuptiming" ON ( "streettimings"."lookuptiming_id" = "lookuptiming"."id" )
How can i do this?
Thank you
i have the following models
class SchoolClass(models.Model):
id = models.AutoField(primary_key = True)
class_name = models.TextField()
level = models.IntegerField()
taught_by = models.ManyToManyField(User,related_name="teacher_teaching",through='TeachSubject')
attended_by = models.ManyToManyField(User,related_name='student_attending')
def __unicode__(self):
return self.class_name
class Meta:
db_table = 'classes'
class Relationship(models.Model):
rChoices = (
(1,'Mother'),
(2,'Father'),
(3,'Guardian'),
)
parent = models.ForeignKey(User,related_name='parent')
student = models.ForeignKey(User,related_name='child')
relationship = models.IntegerField(choices= rChoices)
#add in __unicode__ for admin name
class Meta:
unique_together = ('parent','student')
db_table = 'relationship
I have the the pk of the class, and I want to find out who are the parents of the students in the selected class.
My feeble attempt is:
selected_class = SchoolClass.objects.get(pk=class_id)
studs = selected_class.attended_by.all().select_related()
r = Relationship.objects.filter(student__in=students)
parents = [.parent for p in r]
Now, I am just curious if there is a shorter or more efficient way of doing this(i'm sure missed something in the docs) ?
This should work
parents = Relationship.objects.filter(student__schoolclass__id=class_id).values_list('parent', flat=True)
"To refer to a "reverse" relationship, just use the lowercase name of the model". (docs)