I created a model which can be inherited in other models
Parent Model
class Edit_Lane_Info(models.Model):
lane_info = models.OneToOneField(Edit_Lane, related_name='$(class)s', on_delete=models.CASCADE)
def delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
if self.lane_info:
self.lane_info.delete()
class Meta:
abstract = True
class Status (Edit_Lane_Info, models.Model): # parent class inherited
......
class Anpr(Edit_Lane_Info, models.Model): # parent class inherited
....
class Sensor_Details(Edit_Lane_Info, models.Model): # parent class inherited
.............
Now my question is how can I pass related_name in Edit_Lane_Info(parent model) uniquely. I used related_name='$(class)s, but not working
Edit_Lane model
class Edit_Lane(models.Model):
Anpr_Ip = models.GenericIPAddressField(default="NA")
Your related_name contains $ instead of %
To work around this problem, when you are using related_name, part of the name should contain the %(app_label)s or %(class)s
EDIT:
For the the inheritance, you don't need to inherit from models.Model in each following class:Status, Anpr, Sensor_Details since Edit_Lane_Info is already inherited from models.Model
You should have it that way
Edit_Lane_Info(models.Model)
class Status (Edit_Lane_Info):
class Anpr (Edit_Lane_Info):
class Sensor_Details (Edit_Lane_Info):
Related
I have two Django 3.0 models, one of which is a subclass of the other:
# models.py
class BaseCategory(models.Model):
class Meta:
verbose_name_plural = "categories"
class Category(BaseCategory):
# fields 'n' stuff
Only the Category model is registered in the Admin
# admin.py
#admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
# stuff here
In the Admin, the Category model is labeled "Categorys", despite the fact that it should have inherited the Meta inner class and its verbose_name_plural attribute from BaseCategory. In fact, if I copy the same code into the Category model,
# models.py
class Category(BaseCategory):
class Meta:
verbose_name_plural = "categories"
# fields 'n' stuff
the model is correctly labeled "Categories" in the Admin. This indicates that the Category class is not inheriting the Meta inner class of BaseCategory.
Why does a child class not inherit the Meta inner class? Is there another way for me to only specify verbose_name_plural once instead of copying the exact same code into every child of BaseCategory?
According to the Django Docs you need to declare the BaseCategory model abstract in order for its Meta class to be inherited.
class BaseCategory(models.Model):
class Meta:
abstract = True
verbose_name_plural = "categories"
The Category class will then automatically inherit the Meta class, except for the abstract attribute.
Note that if you want to make any changes to the Meta class in Category you need to subclass it explicitly:
class Category(BaseCategory):
class Meta(BaseCategory.Meta):
...
I have the following models:
class Address(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
....
class Meta:
abstract = True
class BillingAddress(Address):
is_default = models.BooleanField()
...
class Meta:
db_table = 'billing_address'
I'm trying to build a serializer for BillingAddress:
class AddressSerializer(serializers.ModelSerializer):
class Meta:
abstract = True
model = AddressModel
class BillingAddressSerializer(AddressSerializer):
def to_representation(self, obj):
return AddressSerializer(obj, context=self.context).to_representation(obj)
class Meta(AddressSerializer.Meta):
model = UserBillingAddress
fields = (
'id',
'is_default',
)
I keep getting:
ValueError: Cannot use ModelSerializer with Abstract Models.
How can I build my BillingAddressSerializer to reflect both classes?
An abstract model is a base class in which you define fields you want to include in all child models. Django doesn't create any database table for abstract models. A database table is created for each child model, including the fields inherited from the abstract class and the ones defined in the child model.
Since there is no "Address" table, so "AddressSerializer" would be invalid.
Hello I have two models
class A(models.Model):
slug = models.SlugField()
class Meta:
abstract = True
class B(A):
slug = models.CharField()
class Meta:
abstract = True
I get error AttributeError: Manager isn't available; B is abstract
How do can to redefine attribute in abstract class?
class A cannot be changedю
Abstract models don't have a manager on them because they don't map to a database table. They are used to define reusable mixins that you can compose into concrete models. To make B a concrete model remove the abstract flag and then it will have an objects attribute defined on its instances.
class A(models.Model):
slug = models.SlugField()
class Meta:
abstract = True
class B(A):
slug = models.CharField()
As an aside, as things stand with your models this is a pointless hierarchy because the slug field on B overrides the slug field that is being inherited from A and therefore there is currently zero shared custom functionality between the two definitions. You may as well just have B inherit from models.Model directly.
In my Django (1.6+) application, I have many Django models that point to (read only) DB views.
These models also contain foreign key relations.
Now if the Django application tries to delete the related fk-models, this will lead to DB errors ("Cannot delete from view") if I don't set cascade=DO_NOTHING on all foreign key fields.
Example:
class PersonView(models.Model):
person = models.ForeignKey(Person, db_column='fk_person', on_delete=DO_NOTHING)
class Meta:
db_table = 'view_persons'
managed = False
Since all my db-view-model-ForeignKey-fields should have cascade=DO_NOTHING by default, I'd like to create a DB-View model base class which will automatically set all foreign-key-fields to on_delete=DO_NOTHING, so I only need to care for inheriting from this model - otherwise it's easy to forget (and redundant) setting this attribute for all fields.
In the end I want to end up with a code like this:
class ViewModel(models.Model):
class Meta:
abstract = True
def __init__(self, *args, **kwargs):
super(ViewModel, self).__init__(*args, **kwargs)
# How to set all foreign-key fields' on_delete attribute to "DO_NOTHING"?
class PersonView(ViewModel):
# no need to set on_delete anymore
person = models.ForeignKey(Person, db_column='fk_person')
class Meta:
db_table = 'view_persons'
managed = False
How can I alter Django model attributes in my base class to set all foreign key fields to on_delete=DO_NOTHING?
Well, you can monkey-patch models.ForeignKey but the more preferred method is to simply subclass ForeignKey:
class MyForeignKey(models.ForeignKey):
def __init__(self, *args, **kwargs):
super(MyForeignKey, self).__init__(*args, **kwargs)
self.on_delete = models.DO_NOTHING
Then you can use MyForeignKey instead of ForeignKey in your models.
I have in my models.py
class Business(models.Model):
industry = models.models.ManyToManyField(Industry)
in forms.py
class BusinessForm(forms.ModelForm):
class Meta:
model = Business
When I render the form, the industry names appear in a multiple select box. What do I do to make the industry names in alphabetical order?
There are several ways:
You can override the queryset ordering on a per-form basis, set the ordering meta class option, or override the model manager queryset with an ordering method.
Override global model manager queryset
class IndustryManager(models.Manager):
def get_query_set(self):
return (
super(IndustryManager, self)
.get_query_set()
.order_by('name')
)
class Industry(models.Model):
name = models.CharField(max_length=128)
objects = IndustryManager()
Specify global meta option ordering
class Industry(models.Model):
name = models.CharField(max_length=128)
class Meta:
ordering = ['name']
Per form ordering
class MyForm(forms.ModelForm):
class Meta:
model = Business
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['industry'].queryset = Industry.objects.order_by('name')
There's also a shortcut called formfield_for_manytomany if you are dealing with the django admin.
I like this method:
class BusinessForm(forms.ModelForm):
class Meta:
model = Business
industry = forms.ModelMultipleChoiceField(
queryset=Industry.objects.order_by('name'))
I like it, since it does not alter the database model, and since it is declarative (less programming).