110👍
You need to get the User
object and then add it to emails_for_help
field. You can’t add an object to ManyToManyField
when creating an instance. Have a look at the doc.
class Set_user(FormView):
template_name="pkm_templates/set_up_user.html"
form_class = Set_User_Form
success_url = '/thanks/'
def form_valid(self, form):
org = form.cleaned_data.get('organization')
emails = form.cleaned_data.get("share_email_with")
users = User.objects.filter(email__in=emails)
instance = Setupuser.objects.create(organization=org)
for user in users:
instance.emails_for_help.add(user)
return redirect("/")
Another way of doing this is to use .set()
.
class Set_user(FormView):
template_name="pkm_templates/set_up_user.html"
form_class = Set_User_Form
success_url = '/thanks/'
def form_valid(self, form):
org = form.cleaned_data.get('organization')
emails = form.cleaned_data.get("share_email_with")
users = User.objects.filter(email__in=emails)
instance = Setupuser.objects.create(organization=org)
instance.emails_for_help.set(users)
return redirect("/")
Or you can simply use .add()
to add arbitrary number of objects.
class Set_user(FormView):
template_name="pkm_templates/set_up_user.html"
form_class = Set_User_Form
success_url = '/thanks/'
def form_valid(self, form):
org = form.cleaned_data.get('organization')
emails = form.cleaned_data.get("share_email_with")
users = User.objects.filter(email__in=emails)
instance = Setupuser.objects.create(organization=org)
instance.emails_for_help.add(*users)
return redirect("/")
15👍
I tried all the above solutions and it doesn’t work on Django 3.0 . So, I did my own research and came up with the solution.
The solution is gonna be pretty simple. My answer is in general.
Let us say there exists a form-field specialFieldName
which is defined as a ManyToManyField
in models.py
.
Why did that error occur?
The options of this field which the user entered through the ‘django form’ are stored as a Queryset. In this scenario, we simply cannot assign this queryset to a ManyToManyField
attribute during the creation of the object based on this queryset. This is the reason you are getting the above error.
So, we first create the object based on all the information we have got from the django-form, except the specialFieldName
and then we use add() method to add all the elements of this queryset to the object we just created.
So, we need to iterate over this queryset.
returnedQueryset = form.cleaned_data.get('specialFieldName')
dummyObject = ObjectModel.objects.create(..using all the info except specialFieldname..)
for member in returnedQueryset:
dummyObject.add(member)
Unfortunately, the loop doesn’t iterate over all the members of the returnedQueryset (Read Why?). Thus, the above thing doesn’t work. We gotta get a bit more advanced and use iterator() method instead.
for member in returnedQueryset.iterator():
dummyObject.add(member)
Now it works fine.
(P.S. This was my first answer on Stackoverflow. Gratitude for all my mentors ;-))
- [Django]-Django Sitemaps and "normal" views
- [Django]-Django: TemplateDoesNotExist (rest_framework/api.html)
- [Django]-Django's SuspiciousOperation Invalid HTTP_HOST header
1👍
Try this code because i had the same problem while using ManyToManyField
.
class Set_user(FormView):
template_name="pkm_templates/set_up_user.html"
form_class = Set_User_Form
success_url = '/thanks/'
def form_valid(self, form):
org = form.cleaned_data.get('organization')
instance = Setupuser(organization=org,emails_for_help=emails)
instance.save()
instance.email.add(request.user.email)
instance.save()
return redirect("/")
- [Django]-Django – query filter on manytomany is empty
- [Django]-Django Installed Apps Location
- [Django]-How to use subquery in django?
0👍
I was getting the same error Direct assignment to the forward side of a many-to-many set is prohibited. Use plan_options.set() instead
, when upgrading from an older Django version to Django 2.2 LTS.
However when I used .set()
I got SyntaxError: can't assign to function call
.
For me the issue was fixed by adding _set
:
existing_plan.plan_options_set = [x.pk for x in old_plan.plan_options.all()]
- [Django]-How to print BASE_DIR from settings.py from django app in terminal?
- [Django]-ImproperlyConfigured: You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings
- [Django]-Ignoring Django Migrations in pyproject.toml file for Black formatter
0👍
I might not be adding much, but I got this error while working on unit tests for a rest api with no forms at all, so I wanted to provide an example of how I fixed it in this scenario. I’m working with Django 4.1.7 and Django Rest Framework 3.14.0.
This is a Pokemon cards project, so there’s a PokemonType model (that represents types as "fire", "water", "grass", etc. and their resistances and weaknesses):
class PokemonType(models.Model):
name = models.CharField(max_length=100, blank=False)
strong_vs = models.ManyToManyField('self', symmetrical=False, related_name="strong_versus")
weak_vs = models.ManyToManyField('self', symmetrical=False, related_name="weak_versus")
resistant_to = models.ManyToManyField('self', symmetrical=False, related_name="resists")
vulnerable_to = models.ManyToManyField('self', symmetrical=False, related_name="vulnerable")
I wanted to write a simple test that verifies a PokemonType can be created, but this test causes the Direct assignment to the forward side of a many-to-many set is prohibited
error:
class PokemonTypeModelTests(TestCase):
def test_create_pokemontype(self):
pokemon_type = PokemonType.objects.create(
name = 'type 1',
strong_vs = [],
weak_vs = [2],
resistant_to = [3, 4],
vulnerable_to = [2, 5]
)
pokemon_type_from_db = PokemonType.objects.get(id=pokemon_type.id)
self.assertEqual(pokemon_type_from_db.name, 'type 1')
One could think that creating the object and then adding the relationships like this might help:
pokemon_type = PokemonType.objects.create(name='type 1')
pokemon_type.resistant_to.set([3, 4])
but this raises error django.db.utils.IntegrityError: The row in table 'api_pokemontype_resistant_to' with primary key '1' has an invalid foreign key: api_pokemontype_resistant_to.to_pokemontype_id contains a value '3' that does not have a corresponding value in api_pokemontype.id.
This happens because the PokemonType objects with ids 3 and 4 don’t exist yet (keep in mind that Django creates a special database for the purpose of testing). The many-to-many relationship is actually implemented as a separate table in the database, and Django needs the objects to actually exist in the database before being able to add relationships between them.
That’s why a solution in this case was to first create all the objects, add them to the database and then use set()
to create the many-to-many relationships:
def test_create_pokemontype(self):
# this is the "main" object:
pokemon_type = PokemonType.objects.create(name='type 1')
# these are only created for the relationship fields:
type2 = PokemonType.objects.create(name='type 2')
type3 = PokemonType.objects.create(name='type 3')
type4 = PokemonType.objects.create(name='type 4')
type5 = PokemonType.objects.create(name='type 5')
# now we can "set" these objects in each ManyToManyField:
pokemon_type.strong_vs.set([])
pokemon_type.weak_vs.set([type2])
pokemon_type.resistant_to.set([type3, type4])
pokemon_type.vulnerable_to.set([type2, type5])
# and perform assertions with them:
pokemon_type_from_db = PokemonType.objects.get(id=pokemon_type.id)
self.assertEqual(pokemon_type_from_db.name, 'type 1')
self.assertEqual(set(pokemon_type_from_db.strong_vs.all()), set())
self.assertEqual(set(pokemon_type_from_db.weak_vs.all()), {type2})
self.assertEqual(set(pokemon_type_from_db.resistant_to.all()), {type3, type4})
self.assertEqual(set(pokemon_type_from_db.vulnerable_to.all()), {type2, type5})
- [Django]-Django-celery: No result backend configured
- [Django]-Django admin: How to display the field marked as "editable=False" in the model?
- [Django]-Django {% if forloop.first %} question