Can someone please explain why is meta class used in the following example.
Ex:
Class Employee (models.Model):
name = models.ForeignKey(name)
Gender = models.IntegerField()
class Meta:
ordering = ["Gender"]
Thanks.
Django models use the Meta class to contain extra information about the model that would not necessarily be appropriate to contain within the model class itself. Note that this is not the same as Python's metaclass; that is a completely different topic.
In this case it ordering or sorting the queries to this model by field "Gender"
Because author/programmer wants to sort results by value of Gender field.
In this case it defines the default field for ordering if you don't provide ORDER_BY in your query.
It is explained in Django Documentation for Models
https://docs.djangoproject.com/en/dev/topics/db/models/
Give your model metadata by using an inner class Meta, like:
Class Employee (models.Model):
....
class Meta:
ordering = ["attribute-X"]
Another useful option can be used in class Meta is verbose_name.
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)
My main model class looks like this:
class Article(models.Model):
title = models.CharField(max_length=120)
content = models.TextField()
authors = models.TextField(max_length=200)
year = models.IntegerField()
form = models.TextField(choices=FORMS)
language = models.TextField(choices=LANGUAGES)
region = models.TextField(choices=REGIONS)
tags = models.TextField()
def __str__(self):
return self.title
And, for my api to send backend data to front end, I have a serializers class that looks like this:
class ArticleSerializers(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'content', 'authors', 'year'...)
Clearly, the current way of writing fields as a bunch of hard-coded strings is very clumsy and prone to mistake (since I might change the fields in Article class but forget to update the fields in the serializer).
So my question is, how can I improve the style of fields?
Also, another side question, what is this type of coding rule / principle called, when you try to make one part of the code to be dependent on the other, so you need to change one part, instead of always having to remember changing both parts?
Thanks!
The documentation on specifying which fields to include [drf-doc] says:
You can also set the fields attribute to the special value '__all__' to indicate that all fields in the model should be used.
We thus can include all fields with:
class ArticleSerializers(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
If you want to exclude certain fields, you can work with an exclude option:
You can set the exclude attribute to a list of fields to be excluded from the serializer.
So if you want to exclude the tags for example, you can work with:
class ArticleSerializers(serializers.ModelSerializer):
class Meta:
model = Article
exclude = ['tags']
Clearly, the current way of writing fields as a bunch of hard-coded strings is very clumsy and prone to mistake
Normally the metaclass logic will raise an exception if it can not find that field when it constructs the class, so when you start the application. This thus means that typos will not result in any problems. The only thing that could go wrong is specifying another field that exists for the given model.
'''
from django.db import models
import uuid
class Book(models.Model):
name=models.CharField(max_length=100)
isbn=models.UUIDField(default=uuid.uuid4,
primary_key=True)
writer=models.CharField(max_length=100)
class Meta:
ordering=['name']
ordering='User MetaData'''
With class Meta you can give to your model metata such as database table name or ordering options. You can check it out in documentation
By using "verbose_name" in class Meta you can specify human-readable name for singular object. Documentation
By using 'ordering' in class Meta you can specify in which order you will get list of objects. By ['-field_name'] you specify descending order. By ['field_name'] you specify ascending order. You can make ordering by several fields: ordering = ['field1', 'field2']. Documentation
1.Model Meta is basically used to change the behavior of your model fields like changing order options,verbose_name and lot of other options. It’s completely optional to add Meta class in your model.
2.Verbose_name is a human-readable name for the field.
3.Ordering takes a list of string values, which are model fields. It's used to define the ordering of objects of a model. When the objects of this model are retrieved, they will be present in this ordering.
I have to models
class Parent(object):
text_field = models.TextField()
boolean_field = models.BooleanField()
class Child(Parent):
another_text_field = models.TextField()
With the following ModelAdmin
class ChildAdmin(admin.ModelAdmin):
pass
admin.site.register(Child, ChildAdmin)
I currently see all fields in the admin page, i.e. text_field, boolean_field, and another_text_field.
Question: How can I get a parent select field and exclude text_field and boolean_field (for latter I guess I can use exclude).
Current Solution: I add a Form and use its clean method to set the parent field. text_field and boolean_field can be excluded by addind it to the ModelAdmin's excluded variable.
simply overwrite fields
class Child(Parent):
another_text_field = models.TextField()
text_field = None
boolean_field = None
if you want to use inheritance in django models use abstract models please.
I am not sure if it is really necessary to use model inheritance. if not, you may consider using OneToOneField without model inheritance.
Example using OneToOneField:
models.py
class Parent(models.Model):
text_field = models.TextField()
boolean_field = models.BooleanField()
class Child(models.Model):
parent = models.OneToOneField(Parent,
on_delete=models.CASCADE,
primary_key=True)
child_field = models.TextField()
admin.py
#admin.register(Parent)
class ParentAdmin(admin.ModelAdmin):
pass
doing so you can see a drop down menu for picking Parent instance at child admin page. but meanwhile, you lose one 'benefit' of using inheritance, which is the availability of Parent field in Child
as mentioned in the docs,
All of the fields of Place will also be available in Restaurant,
although the data will reside in a different database table.
but there is a easy fix for that, just use something like Child.objects.filter(parent__text_field="something"). Query performance should be the same (I guess) since implementation in db are basically the same for these two approaches (both use separated table) (please correct if I am wrong)
Apart from from this and admin display behavior, I am not sure how these two approaches (your approach and this answer) are differed.
Suppose I want to have multiple kinds of articles, all reachable on site.com/news/article-slug
(so depending on article-slug, it can be a video article, a text article, an image slider article, ...)
I have these models:
class Article(models.Model):
class Meta:
abstract = True
slug = models.SlugField(max_length=60, unique=True)
class TextArticle(Article):
content = models.TextField()
class VideoArticle(Article):
video = models.ForeignKey(Video)
But the problem is that I can create a TextArticle and a VideoArticle with the same slug.
Is there an easy way to fix it so that if there's already a VideoArticle with a specific slug, no TextArticle can be added with the same slug (and vice versa)?
If there's no easy fix:
should I go for custom form validation with database querying?
should I not make the base class abstract?
any other ideas?
Thanks in advance!
It sounds like you don't actually want an abstract class, but rather for the Article class to be the table for which all subclasses reference:
https://docs.djangoproject.com/en/1.10/topics/db/models/#multi-table-inheritance