Dynamically add to the model's Meta class? - django

Normally, you specify a table name for your model by putting in the model class:
class MyModel(models.Model):
class Meta:
db_table = 'desired_tablename'
I want to add the table names for all my models dynamically at the end of models.py.
Can this be done in Django? If yes, how?

Yes, this can be done simply like this:
MyModel._meta.db_table = 'desired_tablename'

Related

You cannot alter to or from m2m fields or add or remove through =onmn2m fields

What is this error:
You cannot alter to or from m2m fields or add or remove through=on m2m fields
Class post(models.Model):
Title=models.CharField(max_length=50)
Class cat_child(midels.Model):
name=models.CharField(max_length=50)
post=models.ManyToManyField(Post)
cat_parent=models.ForeignKey('Cat_Parent',on_delete=models.CASCADE)
Class cat_parent(models.Model):
name=models.CharField(max_length=50)
Why is that?
Django by default creates an intermediate table, but if you want to specify one manually you must do through through ManyToManyField (referring to the intermediate table)
class Category(models.Model):
Name=models.CharField(max_length=50)
post=models.ManyToMany(Post, through='PostCat')
and Then specify the intermediate table as it did.
The only change would be to add the through = 'PostCat' in ManyToMany where PosCat is the intermediate table referenced.
You can find more in the documentation, but basically that is the solution:
https://docs.djangoproject.com/en/2.1/topics/db/models/

Django: add index to meta field

I have the following model:
from model_utils.models import TimeStampedModel
class MyModel(TimeStampedModel):
....
name = models.CharField(max_length=100)
....
This model is based on Django Utils (https://django-model-utils.readthedocs.org/en/latest/models.html#timestampedmodel) which adds created and modified fields to my model.
What I need know is way to add a db_index to the modified field of my model. But I can't modify the TimeStampedModel file because it is part of an external dependency.
Do you know any easy solution for this kind of issue?
Thank you.
Yes you can using model Meta.
if you don't need to inherit meta from the TimeStampedModel just use this:
class Meta:
...
otherwise you need to explicitly tell django to look into the parent's meta first like this:
class Meta(TimeStampedModel.Meta):
this might be a hackish solution but maybe you can try using index_together to make django create an index for your model:
like this:
class Meta(TimeStampedModel.Meta):
index_together = [
["modified",],
]
try it out and tell me if it worked
EDIT:
Another solution coming from: How to override the default value of a Model Field from an Abstract Base Class:
try adding this to your MyModel class
MyModel._meta.get_field('modified').db_index = True

Access and manipulate The Value of class Meta attributes

Is it possible to change the value of an attribute of a class Meta: for example I have a model like:-
class Mymodel(models.Model):
class Meta:
ordering = ['-some_order']
for example I want to change the value of display to some value using a view. How do I access the class Meta attributes so that I can manupulate the values?
You can't change them. They're processed by the metaclass when the model is first defined: they're not changeable. Although I can't imagine why you'd want to.
You can read them via Mymodel._meta, if you really want.

How to store a reference to model type in another model instance

So this is a little exercise in the meta meta.. I want to be able to store model reference as a row in a table associated with another model. Something like this:
class Widget(models.Model):
related = models.Model() # data model associated with this widget
identifier = models.CharField(max_length=500) # human-friendly descriptor
This doesn't validate.. I've found an acceptable workaround, but I'm wondering if there's a more proper/graceful way of doing this.
Thanks, django wizards!
If I understand your question correctly then GenericForeignKey is what you need. Have you looked at it?
If you just want to hold the actual model of another object, you can simply use a foreignkey to a content type:
from django.contrib.contenttypes.models import ContentType
class Widget(models.Model):
related = models.ForeignKey(ContentType)
identifier = models.CharField(max_length=500) # human-friendly descriptor

modeling extra table information with django's contenttypes

I've just started using Django's contenttypes framework (and it's pretty awesome). I have an Area object that has many specialised Block objects - I've modeled it as below.
class Area(models.Model):
...
class SomeBlock(models.Model):
...
class AreaBlock(models.Model):
area = models.ForeignKey(Area)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
block_object = generic.GenericForeignKey('content_type', 'object_id')
This works very well. Now I want to register these specialised blocks in their own table along with extra 'global' information about it.
class BlockRegistrar(models.Model):
...
My problem is joining SomeBlock to it's global information in the BlockRegistrar model. A foreignkey in the block table would be obvious, but it wouldn't ever change and I can't figure out how to use django's ContentType table to do these joins.
Any help?
So AreaBlock.block_object is a GenericForeignKey to one of several possible SomeXXBlock models?
Do you mean every SomeXXBlock record has a corresponding BlockRegistrar record?
The easiest way to do that would be with model inheritance:
class BlockRegistrar(models.Model):
# 'global' fields common to all SomeXXBlock models
...
class SomeBlock(BlockRegistrar):
...
class SomeOtherBlock(BlockRegistrar):
...
Behind the scenes Django automatically creates a OneToOneField linking the SomeXXBlock instance to it's corresponding BlockRegistrar. In Django this is called 'multi-table inheritance'. From your question it sounds like this may be what you want.
If you never need to access a BlockRegistrar object directly, but just want the global fields to be available on all the SomeXXBlock 'child' models then you could use an Abstract base model:
class BlockRegistrar(models.Model):
# 'global' fields common to all SomeXXBlock models
...
class Meta:
abstract = True
class SomeBlock(BlockRegistrar):
...
class SomeOtherBlock(BlockRegistrar):
...
In this case the BlockRegistrar model does not exist as a table in the db and there is no magic OneToOneField added to the SomeXXBlock models.