select_related Issue - python

Here are my models:
class Brand(models.Model):
name = models.CharField(max_length=30)
order = models.SmallIntegerField()
class FeatureGroup(models.Model):
name = models.CharField(max_length=30)
class Feature(models.Model):
name = models.CharField(max_length=30, blank=True)
order = models.SmallIntegerField()
group = models.ForeignKey(FeatureGroup)
class FeatureDetail(models.Model):
description = models.TextField()
feature = models.ForeignKey(Feature)
class Phone(models.Model):
name = models.CharField(max_length=30)
brand = models.ForeignKey(Brand)
features = models.ManyToManyField(FeatureDetail)
I an trying to get features and feature details of the current phone and loop over data pairs but unable to do so.
I tried this and it only works for getting the brand:
p = get_object_or_404(Phone.objects.select_related('brand', 'feature__featuredetail'), id=id)
And when doing:
print p.featuredetail_set.all()
I get and this error:
Django Version: 1.4.3
Exception Type: AttributeError
Exception Value:
'Phone' object has no attribute 'featuredetail_set'
What's wrong?

You can't use a class name as a parameter to select_related. The parameter must be a string of your model field.
In your case, it should be 'features__feature'
Another problem is that select_related cannot follow many-to-many relationship. That's why prefetch_related comes.
Therefore, your queryset would be:
Phone.objects.select_related('brand').prefetch_related('features__feature')
Note that prefetch_related creates an additional query and does the joining in Python.

Your relation is called features, not featuredetail_set.
Note this has nothing to do with select_related, which does nothing in this case (it only works on forward ForeignKeys, anyway).

Related

Django: Confusion with accessing database model's foreign key data

This is my first time working with Django and while working I have encountered with a confusion to create a particular statement in views that leads to my desired output. I have created a model 'Parents' which has data of a specific student (Foreign Key), and I am confused to access that student id for further process like working with Attendance, or Results of that specific student. Below are necessary codes and my trial to fetch data.
Models.py
class Students(models.Model):
id = models.AutoField(primary_key=True)
admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
gender = models.CharField(max_length=50)
address = models.TextField()
course_id = models.ForeignKey(Courses, on_delete=models.DO_NOTHING, default=1)
session_year_id = models.ForeignKey(SessionYearModel, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = models.Manager()
def __str__(self):
return self.admin.first_name + " " + self.admin.last_name
class Parents(models.Model):
id = models.AutoField(primary_key=True)
admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
gender = models.CharField(max_length=50)
**student = models.ForeignKey(Students, on_delete=models.CASCADE)**
relation = models.CharField(max_length=255)
address = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = models.Manager()
def __str__(self):
return self.admin.first_name + " " + self.admin.last_name
Here I have two models, Students model has all information regarding student and the other model is Parent model which has parent information with its specific student id.
Below is the views file code where I am trying to fetch student id of currently logged in parent,
def HOME(request):
stud_data = Parents.objects.filter(student__id = request.user.id)
print(stud_data)
return None
At the time of page reload, I am able to get an empty QuerySet[] as it is not able to find the id.
Kindly help me finding the solution to this problem, so that I can continue thinking about the development.
Thanks :)
As you mentioned here, you are looking for Student data for currently logged in Parent. Hence you can look for Student data directly from Parent object. Like this:
stud_object = request.user.parent.student
This relation works because Parent has a OneToOne relation with CustomUser (I assume Authentication's custom User model), hence you should get Parent object from request.user.parent (reverse relation for OneToOne). Also, student field is a ForeignKey of Parent model.
Addionally, I think the relation between Parent and Student should be ManyToMany, because a Student can have multiple parents and one parent can have multiple students (or children).
There are two possibilities:
The View code that you have attached should be returning stud_data not None, but I am assuming that you know this and this current state of the code is just for debugging purposes.
The request.user.id contains a value that doesn't belong to any student's ID in the database. As you are using filter, it's not going to complain about it and just return you an empty QuerySet. I'd suggest using the get() filter here which raises the DoesNotExist exception and would help in debugging as well.
def home(request):
stud_data = Parents.objects.get(student__id = request.user.id)
return stud_data
Hope it helps!
Best of luck with your new journey!

Django: How do you compare a QuerySet with fields on a ForeignKey object's property?

I am trying to query a model against a field on a ForeignKey object's property.
I have the following models:
class Song(models.Model):
name = models.CharField(max_length=20)
limit = models.IntegerField()
class Recording(models.Model):
song = models.ForeignKey(Song, on_delete=models.CASCADE)
status = models.CharField(
max_length=1,
choices=STATUS_CHOICES,
default=OPEN
)
I would like to query Songs that have Recordings with status OPEN with a count of more than 'limit' (the field on Song). Looking over the django aggregation docs I tried something along the lines of:
# View
get(self):
songs_count = Count('recording', filter=Q(recording__status='O'))
songs = Song.objects.annotate(songs_count=songs_count)
results = songs.filter(songs_count__gt=< each song.limit... >)
Can someone point the way on how to build this query?
I greatly appreciate any and all feedback.
You can work with an F object [Django-doc] to refer to a field, so:
from django.db.models import F, Q
Songs.objects.annotate(
songs_count=Count('recording', filter=Q(recording__status='O'))
).filter(songs_count__gt=F('limit'))

Django Rest Framework relation Attribute error

I'm fighting to find my way into DRF and can't get related data into my endpoint.
models.py
class ChapterMark(models.Model):
title = models.CharField(max_length=100, null=True)
episode = models.ForeignKey(Episode, on_delete=models.CASCADE)
start_time = models.CharField(max_length=20)
class Episode(models.Model):
title = models.CharField(max_length=100, blank=False)
show = models.ForeignKey(Show, on_delete=models.PROTECT)
serializers.py
class ChapterMarkSerializer(serializers.ModelSerializer):
class Meta:
model = ChapterMark
exclude = ('')
class EpisodeSerializer(serializers.ModelSerializer):
chapters = ChapterMarkSerializer(source='id')
class Meta:
model = Episode
depth = 1
The error I'm getting is
Got AttributeError when attempting to get a value for field
start_time on serializer ChapterMarkSerializer. The serializer
field might be named incorrectly and not match any attribute or key on
the int instance. Original exception text was: 'int' object has no
attribute 'start_time'.
My guess is that the relation via source='id' just doesn't work but everything I found so far is pointing back to doing it that way.
There's a many to one relationship between chapters and episodes (so each episode has many chapters). I'm sure I'm just missing an important part.
To get reverse relation object use chaptermark_set as source of chapters field, also dont forget to add many=True since episode can have miltiple chapters:
class EpisodeSerializer(serializers.ModelSerializer):
chapters = ChapterMarkSerializer(source='chaptermark_set', many=True)
class Meta:
model = Episode
depth = 1

Django - Follow a backward ForeignKey and then a ForeignKey (query)

I use Django 1.9 and Python 2.7.
My app has four models. Each "trip" is made of several "steps" chosen by the visitor, which relate to "places", which may have several related "Picture".
class Trip(models.Model):
title = models.CharField(max_length=140, blank=True)
class Step(models.Model):
theplace = models.ForeignKey(ThePlace)
trip = models.ForeignKey(Trip)
class ThePlace(models.Model):
name = models.CharField(max_length=200)
class Picture(models.Model):
file = models.ImageField(upload_to="pictures")
slug = models.SlugField(max_length=100, blank=True)
theplace = models.ForeignKey(ThePlace, null=True, blank=True)
I would like to retrieve all "Picture" objects which are related to a specific Trip, using an existing "selectedtrip" queryset:
selectedtrip = Trip.objects.filter(author=request.user)[0]
pictures = selectedtrip.step_set.all().theplace.picture_set.all()
Django displays the following error:
"AttributeError: 'QuerySet' object has no attribute 'theplace'"
Any idea why ?
Because all() returns a queryset, which is a collection of items; theplace is an attribute on an individual Step, not on the collection.
The way to do this type of query is to start from the class you want to retrieve, and follow the relationships within the query using the double-underscore syntax. So:
Picture.objects.filter(theplace__step__trip=selectedtrip)

django having multiple one many to many relations that references same model

i have a model that is having multiple many to many relation to another model it is as follows:
class Match(models.Model):
"""Model docstring"""
Match_Id = models.AutoField(primary_key=True)
Team_one = models.ManyToManyField('Team',related_name='Team one',symmetrical=False,)
Team_two = models.ManyToManyField('Team',related_name='Team two',symmetrical=False,)
stadium = models.CharField(max_length=255, blank=True)
Start_time = models.DateTimeField(auto_now_add=False, auto_now=False, blank=True, null=True)
Rafree = models.CharField(max_length=255, blank=True)
Judge = models.CharField(max_length=255, blank=True)
winner = models.ForeignKey('Team', related_name='winner',to_field='Team_Name')
updated = models.DateTimeField('update date', auto_now=True )
created = models.DateTimeField('creation date', auto_now_add=True )
what is the best way to implement model like this ?. all though django does not throw any errors when passing the model sql once syncdb is excuted it throws up errors saying there is no unique constraint matching given keys
Are you sure Team_one and Team_two should be ManyToMany fields? Surely, a match only has a single team on each side - in which case these should both be ForeignKeys.
Using spaces in related_name attribute makes me uneasy, but I think the real problem is connected to the use of to_field attribute on the winner field. As far as I know you can set database relations only to unique fields. It doesn't really make sense to relate to another object using a field that may not be unique.
I'm not sure what do you want to achieve by connecting through this particular field. You usually connect models using primary key fields. This still allows you to access any other field on the related object.

Categories

Resources