I have the following entities:
from django.db import models
class Foo(models.Model):
pass
class Bar(models.Model):
pass
class FooBar(models.Model):
pwned_foo = # Foobar contains one Foo object
bars = # Collection of Bar objects
How do I express the relation between Foo, Bar and FooBar in the FooBar class?
I think you want a OneToOneField and a ForeignKey like this:
from django.db import models
class Foo(models.Model):
pass
class Bar(models.Model):
foobar = models.ForeignKey(FooBar, related_name='bars')
class FooBar(models.Model):
pwned_foo = models.OneToOneField(Foo)
bars = # Collection of Bar objects
# you can access bars via the reverse relationship like
# myfoobar.bars
This assumes you want a 1-N relation with bars. If you want an N-N relation, then use a ManyToManyField.
If you really need to keep Bar clean of any relationship (can you explain why?) you could try something like ArrayField with the caveats that this only works on postgresql, and you would need to reimplement relationships in querysets, etc... And I suspect performance would suffer too...
from django.db import models
class Foo(models.Model):
pass
class Bar(models.Model):
pass
class FooBar(models.Model):
pwned_foo = models.OneToOneField(Foo, on_delete=models.CASCADE)
bars = models.ForeignKey(Bar, on_delete=models.CASCADE)
Related
I have a Place model with subclasses Restaurant and Bar. I attached InheritanceManager from django-model-utils to Place to use the select_subclasses() method to get instances of the subclass.
from model_utils.managers import InheritanceManager
class Place(models.Model):
# ...
objects = InheritanceManager()
class Restaurant(Place):
# ...
class Bar(Place):
# ...
Everything worked fine. But now I want to set the order of the model Place with django-ordered-model. This package also uses a manager:
...
objects = OrderedModelManager()
...
How to combine them?
I have two models, with ManyToMany relationships:
App1:
class Foo:
fld = models.CharField(null=True, blank=True)
App2:
class Bar:
foos = models.ManyToManyField(Foo, blank=True)
Now, on the admin view of Bar, I'd like to present foos. I cannot simply list foos as a ManyToMany field, I get an error message.
So I try to do:
class BarFooInline(admin.TabularInline):
model = Bar_foos
class BarAdmin(admin.ModelAdmin):
model = Bar
inlines = [BarFooInline, ]
admin.site.register(Bar, BarAdmin)
I got the name Bar_foos by look into the Meta of Bar. Bar.foos.through yields that as a proper models.Bar_foos. But since I didn't explicitly name the through, it's not really in the models.py, so I cannot import that. What should I do?
I don't want to create a through now, because I already have a whole bunch of association information in the table, and I have a feeling that wouldn't be magically data migrated into the newly named association entity's table (https://mounirmesselmeni.github.io/2013/07/28/migrate-django-manytomany-field-to-manytomany-through-with-south/).
Also, I cannot move the ManyToMany field from App2 to App1.
class BarFooInline(admin.TabularInine):
models = Bar.foos.through
class BarAdmin(admin.ModelAdmin):
model = Bar
inlines = [BarFooInline]
exclude = ['foos']
Working with many-to-many models.
Consider these pseudo classes:
class Foo(models.Model):
pass
class Bar(models.Model):
foo = models.ForeignKey(Foo)
I would like to filter via Foo's manager effectively to get a QuerySet that only holds Foo objects with atleast 2 Bar objects pointing towards it.
Use aggregation with Count:
from django.db.models import Count
Foo.objects.annotate(bar_count=Count('bar')).filter(bar_count__gte=2)
All,
I have a set related models:
class Foo(models.Model):
fooName = models.CharField()
bars = models.ManyToManyField("Bar")
class Bar(models.Model):
barName = models.CharField()
When I create a new one, I would like for it to have a default set of data. This is pretty easy to do for normal fields. But I'm not sure what to do for relationship fields. Let's pretend that I want every foo to be initialized with the name "I am a foo" and a set of three bars, each with specific names (say, "I am bar one," "I am bar two," and "I am bar three.").
def Initialize(self)
self.fooName = "I am a foo"
self.bars = ?!?
I'm just not sure how to go about this. Any suggestions?
You may not use a many to many relation on a model instance that doesn't have a primary key.
Save the model, to enable m2m relations
Save your other model, to enable m2m relations on the other side as well
Use .add(), for example yourmodel.bars.add(othermodel)
If you want to set default, initial data, you should use fixtures.
You can do this using django's signals. Every time an instance of your Foo model is created, also create the other information you require:
class Foo(models.Model):
...
from django.db.models.signals import post_save
from signals import create_initial_data
post_save.connect(create_initial_data, sender=Foo)
and in a file called signals.py:
from models import Bar
def create_initial_data(sender, instance, created, raw):
if created and sender == 'Foo':
bar_1 = Bar(...)
bar_2 = Bar(...)
...
bar_1.save()
bar_2.save()
...
instance.bars.add(bar_1, bar_2, ...)
instance.save()
i wanted to place the foo/view code below into a property under the Foo model object, but the debug message says 'bar' cannot be found. Why does it work in the views.py, but not work when i place it in models.py( i did remember to import Bar)?
thanks!
foo/models.py
class Foo(models.Model):
title = models.CharField(_(u'Title'), max_length=600)
bar/models.py
class Bar(models.Model):
foo = models.ManyToManyField(Foo)
eg_id = models.PositiveIntegerField(_(u'Example ID'), default=0)
foo/views.py
from django.db.models import Count
qs = Foo.objects.filter(
bar__eg_id__in=id_list
).annotate(
bar_count=Count('bar')
).order_by('bar_count')
Your Bar class probably hasn't been defined yet in models.py - Try moving it above Foo.