i' ve 2 model which needs to refer to each other in a way, but of course the second is not read when the first tries to reach it. How could i somehow preimport the models? I also tried from the init, but didn' t really work.
Thanks.
example:
class Follow(models.model):
auto_data = models.ForeignKey(Autodata)
class Autodata(models.model):
follow = models.ForeignKey(Follow)
You can pass strings into ForeignKey so they are not evaluated till runtime:
class A(models.Model):
b = models.ForeignKey('B')
class B(models.Model):
a = models.ForeignKey('A')
Related
I know I can change table name per model using db_table attribute, as explained in the doc.
However, what if I want to do it globally? Let's say, I want all my table to be like:
db_table = f"table_{{model_name}}"
Is there any setting for this?
Otherwise, I guess I could use a mixin to be inherited from. However, the whole purpose of doing this is to NOT think of table naming when any developer will add a new model.
After reading this issue, It seems maintainers didn't even consider to add this feature as they did not understand the need, which is pretty clear to me :/
Any idea? Thanks.
The default database table naming goes like db_table = f"{app_label}_{model_name}" and you can rewrite them As hedde-van-der-heide suggested, by creating an abstract base model and subclassing them on your models, like
from django.db import models
class BaseModel(models.Model):
class Meta:
abstract = True
db_table = f"table_{model_name}"
class NewModel(BaseModel):
name = models.CharField(max_length=128)
def __str__(self):
return str(self.name)
I would like to change the DB table names on Django1.9. I know we can change the standard issue with "db_table".
Class Foo_Bar:
class Meta:
db_table = "foo_bar"
But I need to write that in every single class and it is tiresome.
I want Django creates a table whose name is lower-cased class name automatically.
But I have no idea how to do.
I even tried to use
self.__class__.name__.lower()
but, I didn't know how Meta works well.
Any advice is helpful.
Thank you.
A very hack-ish method but this code will give you the outer (since you want to get Foo_Bar, not Meta) class name:
import traceback
Class Foo_Bar:
...
class Meta:
db_table = traceback.extract_stack()[-2][2].lower()
I simplify my code structure, which contains two models:
# created by third part app, not Django one
# but we share same DB, so i have access to this one
class A(models.Model):
title = models.TextField()
# other fields ...
class Meta:
manage = False
class B(models.Model):
model_a = models.OneToOneField(A, related_name='+')
# other fields, to extend model A functionality
Is this a good way to extend third part app model A with my additional fields and methods? Now i have problem to sync this models true one-to-one field. Since I don't have access to trigger model A creation.
In ideal world i should have CarA and CarB. And CarB = CarA relation should be created if CarB exists.
I base this idea on Django 1.5 user extension. Is this clear enough? Or should i do something else?
You could use a property to create the B instance on access if it doesn't exist yet, ie,
class A(models.Model):
title = models.TextField()
# other fields ...
class Meta:
manage = False
#property
def b(self):
if not hasattr(self, "__bcache"):
self.__bcache, created = B.objects.get_or_create(model_a = self)
return self.__bcache
It seems like you're new to both Python and Django so let's explain quickly...
First, the "#property" part: it's a decorator that turns the following function into a computed attribute - IOW you use it as an attribute (myA.b.whatever), and under the hood it turns it into a method call (myA.b().whatever). It's not strictly required here, we would have used an explicit getter (the same method named get_a()) but it's cleaner that way.
Then our method implementation: obviously we don't want to hit the database each time someone looks up A.b, so
first we check if an attribute named __bcache ("b" "cache") is set on the current instance.
if not, we call B.objects.get_or_create(a_model=self) which will either retrieve the existing B instance for this A instance or create one if none exists yet and we store this B instance as self.__bcache so next call will retrieve it directly from __bcache instead of hitting the database.
and finally we return self.__bcache that is now garanteed to exists and point to the related B instance.
I have some problem with order of defining models in django,so i want some thing like this :
class Album(models.Model):
mainTrack = models.OneToOneField(Track)
class Track(models.Model):
albumID = models.ForeignKey(Album)
and in this way when i want run makemigration command,django give this error:
Track is not defined
there is exist any way to solve that??
As you already noticed this line
mainTrack = models.OneToOneField(Track)
references Track but obviously Track is not defined at this time.
Solution:
Reference to the Track model using a string:
mainTrack = models.OneToOneField('Track')
This is also mentioned in the docs:
If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model object itself.
You should add related_name="track" to your ForeignKey call.
class Album(models.Model):
mainTrack = models.OneToOneField(Track)
class Track(models.Model):
albumID = models.ForeignKey('Album', related_name="track")
I have two classes in order:
class A(models):
...
class B(models):
a = models.ManyToManyField(A)
Now I have to change my model to one below:
class A(models):
b = models.ManyToManyField(B)
class B(models):
...
I have to use south migrations. I wanted to create new many to many field in class A, migrate data and delete field from class B. The problem is that both are in same model. So when I put many to many into A class it cannot be seen. Because B declaration is below A. How to solve this problem?
At least SQLAlchemy allows you to use a string instead of a class. Try if django-orm allows that, too.
a = models.ManyToManyField('A')
# ...
b = models.ManyToManyField('B')
Update: According to Django/Python Circular model reference that's exactly the way to go.