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

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).

Related

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

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.

Storing list of objects in Django model

Is there a way in Django to have multiple objects stored and manageable (in Django admin) inside another object?
Example, I have two models: Items and RMA. The RMA may have multiple Items inside of it. Each Item is unique in the sense that it is an inventoried part, so I can't just reference the same item multiple times with foreignKey (though maybe I'm misunderstanding its use/implementation).
So for now, I have an Item model:
class Item(models.Model):
serial_number = models.CharField(max_length=200)
name = models.CharField(max_length=200)
part_number = models.CharField(max_length=200)
location = models.CharField(max_length=200)
def __unicode__(self):
return self.name
And an RMA model:
class RMA(models.Model):
number = models.AutoField(primary_key=True)
items = ?????
Ultimately I'd like to be able to maintain use of the Django admin functionality to add/remove items from an RMA if necessary, so I've been staying away from serializing a list and then deserializing on display. Any help would be much appreciated.
You're modeling a has-many relationship.
This would be modeled with a Foreign Key on Item to RMA:
class Item(models.Model):
serial_number = models.CharField(max_length=200)
name = models.CharField(max_length=200)
part_number = models.CharField(max_length=200)
location = models.CharField(max_length=200)
rma = models.ForeignKey(RMA)
def __unicode__(self):
return self.name
To make it accessible in the admin of RMA you need djangos InlineAdmin functionality.
You can find examples in the django tutorial part2.
You are effectively describing a Many-To-One relation and to do this you are going to have to add the ForeignKey reference to the Item model, not to the RMA model.
You can also add a related_name to give the RMA model an attribute that you can call.
For example:
class Item(models.Model):
rma = models.ForeignKey(RMA,related_name="items")
serial_number = models.CharField(max_length=200)
# etc...
To manage the creation of these, you'll need an InlineModelAdmin form, so your admin.py file will need to look like this:
from django.contrib import admin
class ItemInline(admin.TabularInline):
model = Item
class RMAAdmin(admin.ModelAdmin):
inlines = [
ItemInline,
]

Django many to many admin with custom through object

lets assume that I have such a model:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
class Meta:
db_table = mysql_membership
So my in-the-middle table is chosen (and manually created) by me. And now I would like to create the admin with inline formset in for Group objects. Just like this:
class MembershipInline(admin.TabularInline):
model = Membership
extra = 1
class GroupAdmin(admin.ModelAdmin):
inlines = (MembershipInline,)
admin.site.register(Group, GroupAdmin)
The problem is, that when I try to get edit form for a given Group, I get this error:
Exception Type: OperationalError
Exception Value:
(1054, "Unknown column 'mysql_membership.id' in 'field list'")
This is understandable to me because the primary key in this mysql_membership table is a set of columns (instead of one simple primary_key column):
PRIMARY KEY (person, group, invite_reason)
I want you to know, that I CAN'T edit the database schema. How can I enable formset for many-to-many field based on custom "through" table/model? Please help.
btw. I was using example from:
https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#working-with-many-to-many-intermediary-models

Update intermediate model object using generic view in django

How can i update the existing object of intermediate model using generic view?
class Person(models.Model):
name = models.CharField(max_length=128)
def __unicode__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __unicode__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Currently i'm using generic views concept to update object, but I'm facing problem hoe to update field which exist in intermediate model?
If i generate modelform for Group class, then how can i update the associated field (intermediate model field) using generic view concept?
In above i want to update invite reason field
Thanks in advance
I think there are some missing views in generic or class-based views (which I highly recommend you if your are not already using them), and other people thinks in the same way...
Take a look at django-extra-views project, it implements those missing views.

django form with select fields

I have the following models
class Group(models.Model):
name = models.CharField(max_length=32, unique=True)
class Subgroup(models.Model):
name = models.CharField(max_length=32, unique=True)
group = models.ForeignKey(Group)
class Keywords(models.Model):
name = models.CharField(max_length=32, unique=True)
subgroup = models.ForeignKey(Subgroup)
For each Subgroup I need to manage a list of keywords.
I'm trying to use django forms to automatically display a list (select box) where if I add or remove values to that list and then issue a form.save that it automatically updates the models and data.
How exactly can I do this? Are my models designed properly to allow this?
I think you can create form with MultipleChoiceField:
class MyForm(forms.Form):
to_select = forms.MultipleChoiceField(widget=forms.CheckboxInput, choices=[])
In this case you have to override form`s save method.
Did you try to create model form for subgroup class?
class MyForm(forms.ModelForm):
class Meta():
model=Subgroup

Categories

Resources