Get '_set' for a many-to-many relationship with a through - python

I've got a user model like this:
class Person(AbstractUser):
id = models.AutoField(primary_key=True)
...(additional attributes taken out for brevity)...
kids = models.ManyToManyField(
'Person', through='Relationship', related_name='parents')
and a Relationship model that looks like this:
class Relationship(models.Model):
parent_id = models.IntegerField()
kid_id = models.IntegerField()
class Meta:
unique_together = ('parent_id', 'kid_id')
I'm trying to figure out the best way to get a set of the kids related to a particular parent (who would be the ones logged in).
I've got something like this:
user = Person.objects.get(id=request.user.id)
print(user.relationship_set.all())
But that gives me an error 'Person' object has no attribute 'relationship_set'
How best would I accomplish this?

I ended up going a slightly different route and using this filter:
Person.objects.filter(id__in=[ r.kid_id for r in Relationship.objects.filter( parent_id=person_id ) ]

Related

Factory_boy not creating RelatedFactory in Trait

I've got a Purchase model and a PurchaseInfo model. PurchaseInfo has a foreign key to Purchase. I'm trying to modify an existing Factory for Purchase that will create PurchaseInfo at the same time using RelatedFactory since it's a reverse foreign key relationship. The only thing is that I wanted to use a Taint so that I could control the value of fields within PurchaseInfo. Normally when I create a Purchase like p = PurchaseFactory() the PurchaseInfo is created with null fields inside of it. If I create a Purchase like p = PurchaseFactory(info=True), so I can get the field modifications via the Taint, the PurchaseInfo is not created at all.
I have a feeling that putting the RelatedFactory in a Taint is not the way to go. What is the correct way to do this?
Models:
class Purchase(Model):
...
class PurchaseInfo(Model):
purchase = models.ForeignKey(Purchase, on_delete=models.CASCADE, unique=True, db_index=True)
lock = DateTimeField(null=True)
lock_by = ForeignKey(...
class PurchaseInfoFactory(DjangoModelFactory):
class Meta:
model = PurchaseInfoField
lock = None
lock_by = None
class PurchaseFactory(DjangoModelFactory):
class Meta:
model = Purchase
info = RelatedFactory(PurchaseInfoFactory,
factory_related_name='purchase')
class Params:
info = Trait(internalfield=RelatedFactory(PurchaseInfoFactory,
factory_related_name='purchase',
lock=timezone.now() - relativedelta(months=1),
lock_by=SubFactory(UserFactory, user_id=1)))
I don't like my solution, but here's what I did. I derived a secondary factory with an alternate RelatedFactory. That works.
class PurchaseFactory(DjangoModelFactory):
class Meta:
model = Purchase
info = RelatedFactory(PurchaseInfoFactory,
factory_related_name='purchase')
class InfoPurchaseFactory(DjangoModelFactory):
class Meta:
model = Purchase
info = Trait(internalfield=RelatedFactory(PurchaseInfoFactory,
factory_related_name='purchase',
lock=timezone.now() - relativedelta(months=1),
lock_by=SubFactory(UserFactory, user_id=1)))

Not able to access related model data using foreign key in Django

models.py
class products(models.Model):
name = models.CharField(max_length=100)
sku = models.CharField(max_length=50)
vendor = models.CharField(max_length=50)
brand = models.CharField(max_length=50)
price = models.FloatField()
product_status = models.BooleanField()
quantity = models.IntegerField()
def __str__(self):
return self.name
# categories
class categories(models.Model):
category_name = models.CharField(max_length=50)
parent_id = models.IntegerField()
# product categories
class product_categories(models.Model):
product = models.ForeignKey(products, on_delete=models.CASCADE)
category = models.ForeignKey(categories, on_delete=models.CASCADE)
def __str__(self):
return self.category
I can access 'category' table data(inside django shell) using
data = products.objects.all()
data.values('product_categories__category__category_name')
output: <QuerySet [{'product_categories__category__category_name': 'xxxx'}}]>
If I put this(inside django shell)
data.product_categories.category
output: 'QuerySet' object has no attribute 'product_categories'
How do I get a queryset(can be passed to html) which includes data from "categories" table along with the data of "products" table
There are a couple of issues happening here. First, data is a queryset, which is kind of like a list of objects, even though here there's just one object in the list. What you want is to get an attribute off of the item in the list, so you need something like a data.first() to get to that object before you start dotting into its attributes.
Secondly, the way Django handles reverse FK relationships requires that you refer to the FK by the standard name of, in your case, product_categories_set, OR you set your own related_name attribute on the FK. Something like:
# product categories
class product_categories(models.Model):
product = models.ForeignKey(products, on_delete=models.CASCADE, related_name='product_categories')
category = models.ForeignKey(categories, on_delete=models.CASCADE, related_name='product_categories')
def __str__(self):
return self.category
so that you can refer to your product_categories model from both the product and categories using just data.product_categories.
Thirdly, when accessing a reverse FK relationship, just like in point (1) above, you will get a related manager, from which you can get a queryset of items. Thus, to get the category name, you need to indicate which item you want the category name for. Assuming it's just the first item for everything, it would look something like:
data = products.objects.all()
product_category = data.product_categories.all()
category_name = product_category.category.category_name
Of course once you have more data, you'll not always want to just pick the first item, so you'll need to add filtering logic into the query to make sure you get the item you're looking for.
ETA, I do agree with the comment by Jorge above - a MTM would make this a bit simpler and would, in essence, create your product_categories table for you.

Django ORM lookup syntax

I have a model Fruit, and fruit has orchards.
class Fruit():
orchards = models.ManyToManyField('Orchard', blank=True)
Each orchard belongs to a farm:
class Orchard():
farm = models.ForeignKey('Farm', verbose_name='Farm', null=True, blank=True, on_delete=models.PROTECT)
Every fruit is a seedling
class Seedling():
fruit = models.ForeignKey('Fruit', editable=False, on_delete=models.CASCADE)
Here is my attempt:
queryset = Seedling.objects.all().filter(fruit__orchards__in__farm=farm_id)
This gets me an error django.core.exceptions.FieldError: Related Field got invalid lookup: in
Anyone able to clear up my query? Much appreciated
You filter with:
queryset = Seedling.objects.filter(fruit__orchards__farm=farm_id)
so without the __in lookup [Django]. If you filter over a one-to-many relation, or a many-to-many relation, you filter existentially over one of the related elements.

Reduce the headache on database when using ModelChoiceField

please I need your help how to reduce the database call when using ModelChoiceField as it requires a queryset and I have to use it three times separately with a model that is recursively foreign key on itself, the code is below:
ModelForm code in the init function
self.fields['category'] = forms.ModelChoiceField(queryset=queryset)
self.fields['super_category'] = forms.ModelChoiceField(queryset=)
self.fields['product_type'] = forms.ModelChoiceField(queryset=)
the model class:
class Category(ProjectBaseModel, AuditLogMixin):
parent_id = models.ForeignKey('self', related_name='children', blank=True, null=True, on_delete=models.CASCADE,verbose_name=_('Parent'))
what i tried to do is collect all ids of the desired categories in array and make only one filter queryset with them like the following:
category = auction.category
super_category = category.parent_id
product_type = super_category.parent_id
ids= [category.id,super_category.id,product_type.id]
queryset = Category.objects.filter(id__in=ids)
How to proceed with that solution

Not sure I understand dependancy between 2 django models

I am struggling to understand django models relationship.
I have this arborescence:
A train have cars, and those cars are divided into parts. Then those parts all contains different references.
Like, for exemple, all the trains have the 6 cars, and the cars 6 parts. Each part have x reference to be associated.
I would like to use all of them in a template later on, where the user can select the train, the car and the part he worked on, then generate a table from his selections with only the references associated to the parts he selected.
It should update the train and the car (I'm trying to update a stock of elements for a company)
I dont really understand which model field give to each of them. After checking the doc, Ive done something like this but i am not convinced:
class Train(Car):
train = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Car(Part):
car = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Part(Reference):
part = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
class Meta:
abstract = True
class Reference(models.Model):
reference = models.CharField(max_length=200)
id = models.CharField(primary_key='True', max_length=100)
selected = models.BooleanField()
def __str__(self):
return self.reference
Can someone please help me understand this so I can do well ? Thanks!!
1-)if you add abstract = True in your Model Meta class, your class doesn't created on database as a table. If you store data for any class, you mustn't define abstract = True.
2-)For relations, you can use models.ForeignKey . If you add a class into brackets of another class, it names: inheritance.(You can think like parent-child relation). In database management, we can use foreignkey for one-to-many relationship.
3-)In Django ORM, id field automatically generated. So you don't need to define id field.
If I understand correctly, also you want to store parts of user's selected.
So, your model can be like that:
class Train(models.Model):
name = models.CharField(max_length=200) # I think you want to save name of train
class Car(models.Model):
train = models.ForeignKey(Train,on_delete=models.Cascade)
name = models.CharField(max_length=200)
class Part(models.Model):
car = models.ForeignKey(Car,on_delete=models.Cascade)
name = models.CharField(max_length=200)
class Reference(models.Model):
part = models.ForeignKey(Part,on_delete=models.Cascade)
name = models.CharField(max_length=200)
def __str__(self):
return self.reference
#addtional table for storing user's references
class UserReference(models.Model):
user = models.ForeignKey(User,on_delete=models.Cascade)
reference = models.ForeignKey(Reference,on_delete=models.Cascade)
name = models.CharField(max_length=200)
With this definitions, you can store user's definition on UserReference table. And with Django Orm, you can access train object from UserReferenceObject.
#user_reference: UserReference object like that result of UserReference.objects.first()
user_reference.reference.part.car.train.name

Categories