"<ClaimDocument: test>" needs to have a value for field "id" - python

After adding ManyToMany field to ClaimDocument I'm getting this error:
"<ClaimDocument: test>" needs to have a value for field "id" before this many-to-many relationship can be used. But I have no test field in my ClaimDocument model. Here are my codes:
models.py:
class Document(models.Model):
created_date = models.DateTimeField(default=timezone.now)
added_by = CurrentUserField()
assigned = models.ManyToManyField(CustomUser, related_name='assigned', blank=True, null=True)
forms.py:
class CreateClaimDocumentForm(ModelForm):
def save(self, commit=False):
document = super(CreateClaimDocumentForm, self).save(commit=False)
ClaimDocument.objects.create(
assigned = document.assigned,
...

Example from the Django documentation: Many-to-many relationships
Note that if you are using an intermediate
model for a many-to-many relationship, some of the related manager’s
methods are disabled, so some of these examples won’t work with such
models.
As the error states, you need to have a value in the field id before this m2m relationship can be used. ID is an inherent field of all models that acts a primary-key. So simply create your document models first and then assign the m2m - CustomUser.

Related

Django: Question regarding queries over a junction table/intermediary model

My question concerns the many-to-many section of the django models docs:
It is mentioned there that by using an intermediary model it is possible to query on the intermediary model's attributes like so:
Person.objects.filter(
group__name='The Beatles',
membership__date_joined__gt=date(1961,1,1))
However for the other many-to-many model (Group) a similar query results in a FieldError:
# which groups have a person name containing 'Paul'?
Group.objects.filter(person__name__contains="Paul")
Yet queries that reference the junction table explicity do work:
Person.objects.filter(membership__group__name__contains="The Beatles")
Group.objects.filter(membership__person__name__contains="Paul")
Shouldn't Group therefore have access to Person via the junction model?
Models:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
"The model that defines the ManyToManyField uses the attribute name of
that field itself, whereas the “reverse” model uses the lowercased
model name of the original model, plus '_set' (just like reverse
one-to-many relationships)." (docs: Many-to-many relationships)
So instead of
Group.objects.filter(person__name__contains="Paul")
the correct query is
Group.objects.filter(members__name__contains="Paul")
since the related model is accessible via the name of the field attribute (not the model).

Django: How to follow ForeignKey in unique_together constraint?

I have three Django Models:
a Property Model, most importantly having a slug field;
a Collection Model; and
a PropertyCollectionRelationship Model.
The last model models a ManyToMany relationship between the other two and is used as an explicit through of a ManyToManyField.
from django.db import models
class Property(models.Model):
slug = models.SlugField()
collections = models.ManyToManyField('Collection', blank=True, through='PropertyCollectionRelationship')
# ... other unimportant stuff omitted ...
class Collection(models.Model):
pass
# ... lots of stuff omitted ...
class PropertyCollectionRelationship(models.Model):
prop = models.ForeignKey(Property, on_delete=models.CASCADE)
coll = models.ForeignKey(Collection, on_delete=models.CASCADE)
I would like to add a uniqueness constraint which ensures that each collection has at most one property with any given slug. I tried to express this via a unique_together option in the Model Meta:
class PropertyCollectionRelationship(models.Model):
class Meta:
unique_together = [['coll', 'prop__slug']]
prop = models.ForeignKey(Property, on_delete=models.CASCADE)
coll = models.ForeignKey(Collection, on_delete=models.CASCADE)
This resulted in the following System Check Error:
SystemCheckError: System check identified some issues:
ERRORS:
myapp.PropertyCollectionRelationship: (models.E012) 'unique_together' refers to the nonexistent field 'prop__slug'.
How, if at all, can I achieve such a constraint?
Edit: As suggested below I could set unique=True on the slug field, however my use case requires different properties with the same slug to coexist.

Foreign key choosable when create the model instance

I have two models:
class Amodel(models.Model):
name = models.CharField(max_length=8)
desc = models.CharField(max_length=256)
class Bmodel(models.Model):
name = models.CharField(max_length=8)
desc = models.CharField(max_length=256)
now I have another model:
class Cmodel(models.Model):
name = models.CharField(max_length=8)
f_model = models.ForeignKey(to='there I want to dynamic refers to Amodle or Bmodel when create the Cmodel instance')
I want the Cmodel's f_model is choosable when Create the Cmodel instance, whether this is possible?
This feature called generic relations. Here is the official documentation link generic-relations
By definition of foreign key you can not assign foreign key to one field with choices of model
A FOREIGN KEY is a key used to link two tables together.
A FOREIGN KEY is a field (or collection of fields) in one table that refers to the PRIMARY KEY in another table.
Instead you can proceed to create two fields as below:
class Cmodel(models.Model):
name = models.CharField(max_length=8)
f_a_model = models.ForeignKey(Amodel, blank=True, null=True, on_delete=models.CASCADE)
f_b_model = models.ForeignKey(Bmodel, blank=True, null=True, on_delete=models.CASCADE)
This way you can create two fields and you can keep it as null.
So If you wish to proceed for Cmodel instance with foreign key of a model you can add it to field f_a_model and keep f_b_model null and vice versa
You may follow example of using generic-relations from this link and the doc.
When you use generic relations you need to write your own custom field and method for serializer or form or anywhere you wish to user it.

ModelForm won't validate because missing value, but model field has null=True

I have a problem where my ModelForm is trying to assign '' to a field (it saves fine if I actually provide the primary key of the Product, but it's not a compulsory field, and won't save if the field is left blank). I take it that the ORM it's trying to set that field to ''but:
Shouldn't '' be coerced to None, and;
Why isn't the model form trying to set that field to None in the first place instead of
''?
models.py
class Question(models.model):
fk_product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True, related_name="product_question")
forms.py
class QuestionForm(forms.ModelForm):
fk_product=forms.ChoiceField(required=False)
class Meta:
model = Question
fields = ['fk_product',]
The error:
Cannot assign "''": "Question.fk_product" must be a "Product"
instance.
The view code that produces the error:
QuestionModelFormset = modelformset_factory(Question,
form=QuestionForm,
extra=1)
question_formset = QuestionModelFormset(
data=request.POST,
files=request.FILES,
queryset=Question.objects.all())
if not question_formset.is_valid(): #error occurs on this line
Try adding blank=True too.
null=True means that this field is allowed to be NULL in database.
blank=True means it can be submitted without a value in forms. Otherwise it must have value.

How do I reference different model types from one field in Django?

I have a model representing a Log Entry. This is created anytime there is a modification to the DB.
I would like to include a foreign key field which refers to the model object that was changed in the Log Entry.
Is such a thing possible?
For example:
Log Entry 1
---> Modified Object Field = User Object
But now instead of User being modified, Blog was modified...
Log Entry 2
---> Modified Object Field = Blog Object
Take a look at GenericForeignKey:
A normal ForeignKey can only “point to” one other model [...] The contenttypes application
provides a special field type (GenericForeignKey) which works around
this and allows the relationship to be with any model.
This is possible using generic relations and the GenericForeignKey
https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#generic-relations
Keep in mind it becomes more involved to filter across the generic foreign key ( you need to get the foreignkey content types first)
You can use as Nigel Tufnel says a GenericForeignKey but I think you are looking for something like the Django's admin log, if you take around the Django's code you can see that it uses a ForeignKey to ContentType and a message:
class LogEntry(models.Model):
action_time = models.DateTimeField(_('action time'), auto_now=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
content_type = models.ForeignKey(ContentType, blank=True, null=True)
object_id = models.TextField(_('object id'), blank=True, null=True)
object_repr = models.CharField(_('object repr'), max_length=200)
action_flag = models.PositiveSmallIntegerField(_('action flag'))
change_message = models.TextField(_('change message'), blank=True)

Categories

Resources