How to retrieve entries from a many-to-many relationship - python

I have a application, that is used to manage assistant jobs. Therefore, the model is composed of 3 models: Person, Course, Application (typical many-to-many relation).
My models.py looks as follow:
class Person(AbstractUser):
...
class Course(models.Model):
year = models.charField(max_length=9)
term = ...
class Applications(models.Model):
applicant = models.ForeignKey(Person, on_delete=models.CASCADE, related_name="applicant")
course = models.ForeignKey(Course, on_delete=models.CASCADE)
status = models.CharField(max_length=255, default='Pending')
In the context of a form, I need to retrieve all the courses a person has been hired in order to populate a dropdown list.
It is easy to get all the applications of the currently logged in user having the status 'Hired':
Applications.objects.filter(applicant=user, status="Hired")
but I can't get a a queryset of all the related courses:
Applications.objects.filter(applicant=user, status="Hired").course_set
returns me an:
AttributeError: 'QuerySet' object has no attribute 'course_set'
As per Django documentation, this attribute should exist.
What am I doing wrong?

The reverse accessor course_set is available on an instance of Applications model, not on the queryset (which Applications.objects.filter returns).
For example, if you have an Applications instance named application, you can do:
application.course_set.all()
to get all the instances of Course that are related to application.
If you want to get the related Course instances from filtered Applicaitons:
Applications.objects.filter(
applicant=user, status="Hired"
).values_list(
'course', flat=True
).distinct()
This will return the primary keys of related Course instances.

Just use _set to access it.
Try with the docs first, to get the idea.
https://docs.djangoproject.com/en/3.0/ref/models/relations/

Related

how to get a column value of foreign key in the form of object?

There is 2 models Registration and RegistrationCompletedByUser, I want Registration queryset from RegistrationCompletedByUser with filters(user=request.user, registration__in=some_value, is_completed=True) over RegistrationCompletedByUser. Hence result should be like <QuerySet [<Registration: No name>, <Registration: p2>, <Registration: p-1>]>.
Now what I tried is
Registration.objects.prefetch_related('registrationcompletedbyuser_set') but filters() not working. Another way I tried is model Managers but don't pass parameters for custom filtering.
models.py
class Registration(models.Model):
name=models.CharField(max_length=255)
number=models.SmallIntegerField(null=True, blank=True)
class RegistrationCompletedByUser(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
registration= models.ForeignKey(Registration, on_delete=models.CASCADE)
points = models.SmallIntegerField(default=100)
is_completed = models.BooleanField(default=False)
If I understood this properly, you want to get all Registrations that related to a query instead of a single object.
qs_1 = RegistrationCompletedByUser.objects.filter(user=request.user, is_completed=True).values_list("registration__id", flat=True)
qs_2 = Registration.objects.filter(id__in=qs_1)
As I understood your question is related to django. So actually there is common way to get related query set from another. When you specify ForeignKey to another model actually django automatically creates 'Related Model' + '_set' relation.
I actually didn't get from you question what you are intended to do. In your situation there are many RegistrationCompletedByUser related to one Registration. So what you can do it's to receive all RegistrationCompletedByUser instances from Registration instance by related name for ForeignKey registration of RegistrationCompletedByUser which in your case registration_set. Actually better to specify in RegistrationCompletedByUser model related name as attribute like this:
models.ForeignKey(Registration, on_delete=models.CASCADE,
related_name='registrations')
And after this let's say you have instance of Registration reg1. So to receive queryset of RegistrationCompletedByUser:
reg1.registrations.all()
And you can use filter on it with attributes from Registration model.
And if you want to receive Registration from RegistrationCompletedByUser, again in your case it's just one Registration to many RegistrationCompletedByUser, so let's say we have reg_completed_1, to receive it's only one registration:
reg = reg_completed_1.registration

Set ManyToManyField with particular users from another model's ManyToMany Field

I am building a simple class group app in which I am trying to add particular users from another model's ManyToFieldField to a new model's ManyToFieldField.
class ClassGroup(models.Model):
admins = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='admins')
members = models.ManyToManyField(settings.AITH_USER_MODEL)
title = models.CharField(max_length=9999, default='')
class ClassGroupInvite(models.Model):
class_group = models.ForeignKey(ClassGroup, on_delete=models.CASCADE)
invite_receiver = models.ManyToManyField(class_group.admins.all())
invite_sender = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
As you can see that I am filtering (send request only to class group admins) in ClassGroupInvite with setting ManyToManyField with ClassGroup.admins
But when I try this then it is showing
ManyToManyField(<django.db.models.fields.related_descriptors.ManyToManyDescriptor object at 0x000001CE78793280>) is invalid. First parameter to ManyToManyField must be either a model, a model name, or the string 'self'
I also read the documentation about it, But I didn't find anything about defining it.
then I tried using ClassGroup.admins.all then it showed
AttributeError: 'ManyToManyDescriptor' object has no attribute 'all'
I have tried many times but it is still not working, Any help would be much Appreciated. Thank You in Advance.

Django: Find all one_to_one relations from queryset

I have a queryset of users, which are instances of the model User.
A second model called Patient has a OneToOneField named user:
user = OneToOneField('users.User', on_delete=CASCADE, related_name="patient",
blank=True, null=True)
The goal is to get a queryset of all patients from the queryset of users.
I thought that by using the related_name would be enough, meaning:
queryset_of_users=User.objects.filter(main_group='patients')
queryset_of_patients=queryset_of_users.patient
but it seems this is not it since I get the following error:
AttributeError: 'QuerySet' object has no attribute 'patient'
Any ideas?
Found it,
It works by making a second query:
queryset_of_patients=Patient.objects.filter(user__in=queryset_of_users)

Django: GenericForeignKey and unique_together

In the application I'm working on I'm trying to share access tokens within a company. Example: a local office can use the headquarter's tokens to post something on their Facebook page.
class AccessToken(models.Model):
"""Abstract class for Access tokens."""
owner = models.ForeignKey('publish.Publisher')
socialMediaChannel = models.IntegerField(
choices=socialMediaChannelList, null=False, blank=False
)
lastUpdate = models.DateField(auto_now=True)
class Meta:
abstract = True
Since Facebook, Twitter and other social media sites handle access tokens in their own way I made and abstract class AccessToken. Each site gets its own class e.g.
class FacebookAccessToken(AccessToken):
# class stuff
After doing some reading I found out that I must use a GenericForeignKey to point to classes that inherit AccessToken. I made the following class:
class ShareAccessToken(models.Model):
"""Share access tokens with other publishers."""
sharedWith = models.ForeignKey('publish.Publisher')
sharedBy = models.ForeignKey(User)
# for foreignkey to abstract model's children
contentType = models.ForeignKey(ContentType)
objectId = models.PositiveIntegerField()
contentObject = GenericForeignKey('contentType', 'objectId')
class Meta:
unique_together = (('contentObject', 'sharedWith'))
When I run the django test server I get the following error:
core.ShareAccessToken: (models.E016) 'unique_together' refers to field
'contentObject' which is not local to model 'ShareAccessToken'. HINT:
This issue may be caused by multi-table inheritance.
I don't understand why I get this error, first time using GenericForeignKey. What am I doing wrong?
If there is a smarter way to share the access tokens I would love to hear about it.
Your use of the generic foreign key in this situation is correct.
The error is coming from your unique_together declaration in your model. unique_together can only be used with columns that exist in the database. Since contentObject is not a real column, Django complains about the constraint.
Instead, you can do the following:
unique_together = (('contentType', 'contentId', 'sharedWidth'),)
This is equivalent to what you had defined in your question because contentObject is really just the combination of contentType and contentId behind the scenes.

Django Rest Framework not saving foreign key for a small number of requests

I am using Django Rest Framework to provide API to a mobile app. I have two models, Order and User. Order has a foreign key relation to User.
For about 1% or so of all my order objects, the User field is null. I've been testing this behavior using cURL.
If I do a cURL without a user object, it tells me "This field is required".
If done with a wrong user object, it tells me that the object does not exist. Both of these are the intended and expected behaviors.
I'm trying to figure out how it is possible for some of the Order objects to be saved without a user field. Is there something I'm not taking into account?
My views:
class OrderList (generics.ListCreateAPIView):
model = Order
serializer_class = OrderSerializer
And serializer:
class OrderSerializer (serializers.ModelSerializer):
user = serializers.SlugRelatedField(slug_field = 'user')
partial = True
class Meta:
model = Order
Models:
class User (models.Model):
uid = models.CharField(max_length =200, unique=True)
class Order (models.Model):
uid = models.ForeignKey (User, related_name = "orders", verbose_name = "User",blank=True, null=True)
You could use two different ModelSerializer classes, one for creation, that makes sure, that an Order object can't be created without a related User and one for updating orders, that passes required=False to the related field's constructor, so that you still can save existing orders that haven't a related User.
Try adding default=None to your models.ForeignKey declaration. You could also just create an anonymous user in the users table and when the user isn't specified it could set the anonymous user instead.

Categories