I have been using django and used class Meta: a lot of times, actually what is the use of it?
for example , In django models
class Accounts(models.Model):
---some code here---
class Meta:
ordering = [-1]
In django forms
class AccountForm(forms.ModelForm):
---some code here---
class Meta:
fields = '__all__'
class Meta is basically the inner class. In Django, the use of the Meta class is simply to provide metadata to the ModelForm or the Model class. It is different from the metaclass of a Class in Python.
class Meta is used to change the behavior of the models such ordering, verbose_name etc. Though it is optional to be included in your models.
Related
I have an abstract mixin class that adds a Django model field to any concrete class that inherits from it.
At class initialisation - when makemigrations is run - I'd like the inheriting class to define whether an inherited field is required or optional via the blank= True or False property.
I've tried various Meta and __new__ approaches, but can't figure out how the abstract mixin class can get the information from the inheriting class.
Here's a naive attempt:
from django.db import models
class DescriptionMixin(models.Model):
class Meta:
abstract = True
description = models.TetxField(
# how to get value here?
blank=inheriting_class.description_required
)
class OptionalDescription(DescriptionMixin, SomeOtherClass):
class Meta:
verbose_name = 'Optional description'
description_required = False
class RequiredDescription(DescriptionMixin, SomeOtherClass):
class Meta:
verbose_name = 'Required description'
description_required = True
Thanks in advance for any help offered.
You can't do this at the database level. makemigrations doesn't actually initialise your models to create the migration files.
But since you're trying to enforce this on a TextField, which cannot be enforced at the database level anyway (blank is only used when validating a model through the full_clean() method), you could just override the clean() method on the DescriptionMixin, checking the value of self.blank and raising a ValidationError appropriately.
Solved using this (it's actually Wagtail on top of Django):
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)
self._meta.get_field('description').blank = not getattr(self, 'description_required', False)
I'm trying to create a reusable app where I define some abstract models, and some concrete versions of those models that the user can use if they don't want to inherit the models themselves. If the user does want to create their own subclasses then I don't want Django to create these concrete models.
This is the solution I have at the moment:
myapp/abstract.py
class AbstractModel1:
class Meta:
abstract = True
field1 = models.CharField(max_length=255)
class AbstractModel2:
class Meta:
abstract = True
field1 = models.CharField(max_length=255)
field2 = models.ForeignKey(getattr(settings, 'ABSTRACTMODEL1_OVERRIDE', 'myapp.ConcreteModel1'))
myapp/models.py
if not hasattr(settings, 'ABSTRACTMODEL1_OVERRIDE'):
class ConcreteModel1(AbstractModel1):
pass
if not hasattr(settings, 'ABSTRACTMODEL2_OVERRIDE'):
class ConcreteModel2(AbstractModel2):
pass
Then in the user's app, they can either use the concrete models as provided, or if not then they can create their own subclasses of the model like so:
userapp/models.py
class CustomModel1(AbstractModel1):
extrafield1 = models.CharField(max_length=255)
userapp/settings.py
ABSTRACTMODEL1_OVERRIDE = "userapp.CustomModel1"
Is this the best way to achieve this? Am I setting myself up for difficulties when trying to migrate changes in the subclassed models? What if the user wants to use the provided concrete classes first then migrate to a custom class?
models.py:
class Car():
producer = models.ForeignKey(Producer, blank=True, null=True,)
color = models.CharField()
car_model = models.CharField()
doors = models.CharField()
serializers.py:
class CarSerializer(ModelSerializer):
class Meta:
model = Car
fields = Car._meta.get_all_field_names()
So, here I want to use all fields. But I have an error:
Field name producer_id is not valid for model Car.
How to fix that?
Thanks!
According to the Django REST Framework's Documentation on ModelSerializers:
By default, all the model fields on the class will be mapped to a corresponding serializer fields.
This is different than Django's ModelForms, which requires you to specify the special attribute '__all__' to utilize all model fields. Therefore, all that is necessary is to declare the model.
class CarSerializer(ModelSerializer):
class Meta:
model = Car
Update (for versions >= 3.5)
The behaviour described above was deprecated in version 3.3, and forbidden since version 3.5.
It is now mandatory to use the special attribute '__all__' to use all fields in the Django REST Framework, same as Django Forms:
Failing to set either fields or exclude raised a pending deprecation warning in version 3.3 and raised a deprecation warning in 3.4. Its usage is now mandatory.
So now it must be:
class CarSerializer(ModelSerializer):
class Meta:
model = Car
fields = '__all__'
You could use fields = '__all__' to get all your fields or you could specify if you want a limited number of fields to be returned. See documentation.
But this returns the id value for the foreign key field i.e. producer in your case. To get all the fields for producer, you need to create a serializer class for that too. See here.
So your updated serializers.py should be:
class ProducerSerializer(ModelSerializer):
class Meta:
model = Producer
class CarSerializer(ModelSerializer):
producer= ProducerSerializer(read_only=True)
class Meta:
model = Car
fields = ('producer', 'color', 'car_model', 'doors', )
if you want all fields to be included in the serializer you can use fields = '__all__':
class CarSerializer(serializer.ModelSerializer):
class Meta:
fields = '__all__'
model = Car
But this approach is not recommended. We should always explicitly specify all fields. This is because it gives us control over fields displayed. If we don't want a field's data to be displayed, we can avoid that.
class CarSerializer(serializer.ModelSerializer):
class Meta:
fields = ['name', 'color', 'company', 'price', ]
model = Car
I am having the following model class hierarchy:
from django.db import models
class Entity(models.Model):
createTS = models.DateTimeField(auto_now=False, auto_now_add=True)
class Meta:
abstract = True
class Car(Entity):
pass
class Meta:
abstract = True
class Boat(Entity):
pass
class Amphibious(Boat,Car):
pass
Unfortunately, this does not work with Django:
shop.Amphibious.createTS: (models.E006) The field 'createTS' clashes with the field 'createTS' from model 'shop.boat'.
Even if I declare Boat abstract, it doesn't help:
shop.Amphibious.createTS: (models.E006) The field 'createTS' clashes with the field 'createTS' from model 'shop.amphibious'.
Is it possible to have a model class hierarchy with multiple inheritance and a common base class (models.Model subclass) that declares some fields?
Use this and see if it helps. If you are trying to include the timestamp to the models then just create a base model which includes only the timestamp.
from django.db import models
class Base(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Boat(Base):
boat_fields_here = models.OnlyBoatFields()
class Amphibious(Boat):
# The boat fields will already be added so now just add
# the car fields and that will make this model Amphibious
car_fields_here = models.OnlyCarFields()
I hope this helps. I see that it has been 5 months since you posted this question. If you have already found a better solution then please share it with us, will help us a lot for learning. :)
In my Django app, I am using a model (let's call it Mymodel), and a form :
class Mymodel(models.Model):
firstField(...)
secondField(...)
class MymodelAddform(ModelForm):
def clean_firstField(self):
#stuff
def clean_secondField(self):
#stuff again
def clean(self):
#performs stuff with all the fields
class Meta:
model = Mymodel
Now I want to add another form, MymodelEditform, based on Mymodel again, using only secondField, and only secondField validation
Two options I've considered (both do not work as I wrote them) :
class MymodelEditform(ModelForm):
class Meta:
model = Mymodel
fields = ['secondField']
Here the problem is that clean_secondField is not called unless I re-define it, and I would like to avoid having clean_secondField call another method defined elsewhere (though, if it is the only option, so be it)
class MymodelEditform(MymodelAddform):
class Meta:
model = Mymodel
fields = ['secondField']
Here the problem is that the clean() validation is called, and since I'm only using a subset of the fields, it fails.
The question is pretty obvious : how can I make it work as intended?
I haven't done this, but you can try this.
Create a simple class with clean methods.
As below
class MymodelformCleaner(ModelForm):
def clean_firstField(self):
#stuff
def clean_secondField(self):
#stuff again
Inherit your model forms from this class
Your model forms will just define the fields, while clean methods come from another class
class MymodelAddform(ModelForm, MymodelformCleaner):
class Meta:
model = Mymodel
class MymodelEditform(ModelForm, MymodelformCleaner):
class Meta:
model = Mymodel
fields = ['secondField']
An obvious solution would be to define clean_secondField in MymodelEditform and make MyModelAddForm inherit from MymodelEditForm, but it might not work as expected. Another solution would be to make both forms inherit from a common base form defining clean_secondField.
Or you could just explicitely exclude the field in the form's Meta (cf https://code.djangoproject.com/ticket/12901)