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

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.

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

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

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/

Django 1.11 One-to-Many relationship no related set

So I have two models:
class UserData(models.Model):
""" Holds basic user data. """
id = models.IntegerField(primary_key=True, editable=False) # id is taken from data.
class ConsumptionTimePoint(models.Model):
""" Individual consumption time points with a One-to-Many relationship with UserData """
user_data = models.ForeignKey(UserData, on_delete=models.CASCADE)
And when I try and test them by creating them both, and their relationship in a test:
def test_basic_model_creation(self):
user_data_object = UserData.objects.create(id=1)
user_data_object.save()
consumption_time_point_object = ConsumptionTimePoint.objects.create(user_data=user_data_object)
consumption_time_point_object.save()
self.assertIsNotNone(consumption_time_point_object.user_data)
self.assertEquals(1, len(user_data_object.consumption_time_point_set.all()))
I get the following error:
AttributeError: 'UserData' object has no attribute 'consumption_time_point_set'
But from my understanding that's the correct way to get the set. Have I misnamed something? Or is this a testing issue?
To get the related queryset the class name is lowercased and _set is appended. Try consumptiontimepoint_set
You can also set the reverse relation name manually by using the related_name parameter.

Strange: why Django related many-to-many lookup works this way (but not like in docs)?

The Django docs describe how to query reverse m2m fields:
https://docs.djangoproject.com/en/1.8/topics/db/queries/#many-to-many-relationships
According to this answer we should use related_name as the first argument in the query.
But I'm having trouble making this work. (I'm using Django 1.8.5). Here are my example models:
class Nlpneutralfeature(models.Model):
neutral_feature = models.CharField(u'found word', max_length=255, default='')
class Userproject(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="project", verbose_name=("owner"))
monitoring_words = models.ManyToManyField(Nlpneutralfeature, null=True, blank=True, related_name="monitoringwords")
name = models.CharField(u'Название проекта', unique=True, max_length=255)
So, to get all Nlpneutralfeature rows that belong to Userproject where Userproject.name == '48', I need to do:
Nlpneutralfeature.objects.filter(userproject__monitoringwords__name='48')
But this does not work. The error I get is: Cannot resolve keyword *'userproject'* into field.
So, Django cannot understand that 'userproject' is lowercased model name Userproject.
Now, this is working:
Nlpneutralfeature.objects.filter(monitoringwords__name='48')
How does Django know that monitoringwords is related_name? No error is strange to me, sicne there is no monitoringwords field in the Nlpneutralfeature model!
Note the phrasing in the Django docs:
The name to user for the relation from the related object back to this one. It's also the default value for related_query_name (the name to use for the reverse filter name from the target model).
In your example, the "target model" is Nlpneutralfeature. When you set related_name = 'monitoringwords' on the ManyToManyField Userproject.monitoringwords, it tells Django to use that related_name to refer from Nlpneutralfeature model objects back to the corresponding Userproject model objects.
Correspondingly, if you had declared Userproject.monitoringwords with related_name = 'foo', the way to query for all Nlpneautralfeatures belonging to project 48 would be: Nlpneautralfeature.objects.filter(foo__name='48').
the related_name here is so you can get your Userproject models related to an Nlpneutralfeature model.
eg:
nf = Nlpneutralfeature.objects.get(neutral_feature="XXX")
# From here you can get all Userprojects related to this nf like this:
userProjects = nf.monitoringwords.all()
if you didn't declared a related_name then you had to do it like this:
nf = Nlpneutralfeature.objects.get(neutral_feature="XXX")
# From here you can get all Userprojects related to this nf like this:
userProjects = nf.Userproject_set.all()
i think you understaned this property by inverse.. in my opinion i thing you should declare it here like this: related_name="user_projects"
in summary, related_name is to use when you want to get the current models(where you declare your M2M relationship) from the related model.

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.

Categories