Reference ManyToMany Field in Django Model Method - python

I am attempting to reference the ManyToMany connection between Units and Add-Ons in my code to enable a method that provides the price, but I seem to be unable to reference the relationship in a Model method, can somebody point me in the right direction?
class Unit(models.Model):
class Meta:
permissions = (
('generate_unit_csv', 'can generate unit csv'),
)
unique_together = ['building', 'unit_number', 'property']
add_ons = models.ManyToManyField(
'properties.RentalAddOns', related_name='add_on_units')
...
def get_add_on_price(self):
total_price = 0
# there is no self.add_on_units or self.add_ons
for add_on in self.add_on_units:
total_price += add_on.price
return total_price
When I call the method I get an Attribute Error:
'Unit' object has no attribute 'add_on_units'
When I simple use self.add_ons I get:
'ManyRelatedManager' object is not iterable

As you've defined the field in this model, you need to refer to it as such. Also, you need to use the all() method on the resulting manager object to get all the related objects so that you can iterate over them:
self.add_ons.all()
And from the RentalAddOns model instance, you can refer all the Unit model instances as:
self.add_on_units.all()

Related

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.

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/

TypeError in models

I'm getting this error:
user = models.OneToOneField(User)
TypeError: init() missing 1 required positional argument: 'on_delete'
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserProfileInfo(models.Model):
# creating relationship
user = models.OneToOneField(User)
# additional attributes
portfolio = models.URLField(blank=True)
picture = models.ImageField(upload_to='profile_pics', blank=True)
def __str__(self):
return self.user.username
As the error indicates, you need to specify what should happen, given the object to which you refer is removed, by the on_delete= parameter [Django-doc]. For example:
class UserProfileInfo(models.Model):
# creating relationship
user = models.OneToOneField(User, on_delete=models.CASCADE)
# additional attributes
portfolio = models.URLField(blank=True)
picture = models.ImageField(upload_to='profile_pics', blank=True)
def __str__(self):
return self.user.username
The options here are:
CASCADE
Cascade deletes. Django emulates the behavior of the SQL constraint
ON DELETE CASCADE and also deletes the object containing the
ForeignKey.
Model.delete() isn't called on related models, but the pre_delete
and post_delete signals are sent for all deleted objects.
PROTECT
Prevent deletion of the referenced object by raising ProtectedError,
a subclass of django.db.IntegrityError.
SET_NULL
Set the ForeignKey null; this is only possible if null is True.
SET_DEFAULT
Set the ForeignKey to its default value; a default for the
ForeignKey must be set.
SET()
Set the ForeignKey to the value passed to SET(), or if a callable
is passed in, the result of calling it. In most cases, passing a
callable will be necessary to avoid executing queries at the time your
models.py is imported (...)
DO_NOTHING
Take no action. If your database backend enforces referential
integrity, this will cause an IntegrityError unless you manually add
an SQL ON DELETE constraint to the database field.
A similar question is answered here Getting TypeError: __init__() missing 1 required positional argument: 'on_delete' when trying to add parent table after child table with entries
Basically following should fix url problem
From Django 2.0 on_delete is required:
user = models.OneToOneField(User, on_delete=models.CASCADE)
put 'on_delete = models.CASCADE' in the constructor
what it does: when you will delete the user object as you have referenced it in the user field of your model. it will also delete the model object of UserProfileInfo for taht particular user.

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.

Cannot use a string in Django ManyToManyField through value

(Apologies if I'm missing some critical info to help diagnose this -- I'm new to Python and Django.)
Django complains when I try to use a string in my ManyToManyField through attribute:
File "/vagrant/flamingo_env/lib/python3.4/site-packages/django/db/models/fields/related.py", line 1366, in _check_relationship_model
for f in through._meta.fields:
AttributeError: 'str' object has no attribute '_meta'
Usage:
class Voter(models.Model):
# ...
addresses = models.ManyToManyField(Address, through='voter_addresses', through_fields=('voter_id', 'address_id'))
The error goes away if I create a Through model:
class VoterAddress(models.Model):
voter_id = models.ForeignKey(Voter)
address_id = models.ForeignKey(Address)
class Meta:
db_table = 'voter_addresses'
But of course then it complains that Voter hasn't been defined--and I can't simply change the order, or else VoterAddress won't have been defined either.
And in every single example I have seen the basic string version used. What's going on?
You need to fix the name passed to your through
addresses = models.ManyToManyField(Address, through='VoterAddress')
It has to be the exact name of the custom throughmodel
You will not be required to create a throughmodel if you do not pass the through argument. Django will create and manage one for you
To fix your ordering issue you can give a string value to the ForeignKey class.
class VoterAddress(models.Model):
voter_id = models.ForeignKey("Voter")
address_id = models.ForeignKey("Address")
class Meta:
db_table = 'voter_addresses'
This is a way to define foreignkeys to Models that haven't been defined in the file yet.
If you change this Django won't complain that Voter hasn't been defined.

Categories