📜 ⬆️ ⬇️

Translation Django Documentation: Models. Part 3

image

Good day!

Another part of a series of my translations of the section on models from the Django documentation .
')
Translation Django Documentation: Models. Part 1
Translation Django Documentation: Models. Part 2

___ Meta Parameters
___ Model methods
_____ Override predefined methods
_____ Using SQL
___ Inheritance of models
_____ Abstract base classes
_______ Meta Inheritance
_______ Be careful with related_names


Translation Django Documentation: Models. Part 4 (Last)



Meta Parameters

You can add meta data to your model using the internal class Meta :
Copy Source | Copy HTML<br/> class Ox (models.Model):<br/> horn_length = models.IntegerField()<br/> <br/> class Meta :<br/> ordering = [ "horn_length" ]<br/> verbose_name_plural = "oxen" <br/>

The meta data in the model is “something that is not a field,” for example: sorting parameters ( ordering ), database table name ( db_table ), readable names of objects in a single ( verbose_name ) or plural ( verbose_name_plural ) number and so on. Meta data is optional, adding a Meta class to your model is completely optional.

A complete list of meta- parameters can be found in the help on model parameters .



Model methods

You can define methods in the model to add your own functionality to your objects. While the Manager methods are designed to work with data from the entire table, model methods are created for actions in a separate instance of the model.

This technique is useful for keeping the business logic of an application in one place - in a model.

For example, this model has several proprietary methods:
Copy Source | Copy HTML<br/> from django.contrib.localflavor.us.models import USStateField<br/> <br/> class Person (models.Model):<br/> first_name = models.CharField(max_length= 50 )<br/> last_name = models.CharField(max_length= 50 )<br/> birth_date = models.DateField()<br/> address = models.CharField(max_length= 100 )<br/> city = models.CharField(max_length= 50 )<br/> state = USStateField() # Yes, this is America-centric... <br/> <br/> def baby_boomer_status (self):<br/> "Returns the person's baby-boomer status." <br/> import datetime<br/> if datetime .date( 1945 , 8 , 1 ) <= self .birth_date <= datetime .date( 1964 , 12 , 31 ):<br/> return "Baby boomer" <br/> if self .birth_date < datetime .date( 1945 , 8 , 1 ):<br/> return "Pre-boomer" <br/> return "Post-boomer" <br/> <br/> def is_midwestern (self):<br/> "Returns True if this person is from the Midwest." <br/> return self .state in ( 'IL' , 'WI' , 'MI' , 'IN' , 'OH' , 'IA' , 'MO' )<br/> <br/> def _get_full_name (self):<br/> "Returns the person's full name." <br/> return '%s %s' % ( self .first_name, self .last_name)<br/> full_name = property ( _get_full_name ) <br/>

The final method in this example is a managed attribute ( property ). More details here .

The help for model instances contains a complete list of automatically added methods for each model . You can override most of them (see below). There are also a couple of methods that override in most cases:

__unicode __ ()

The "magic method" of the Python language, which returns the "representation" of any object in the unicode encoding. It is used when you want to display an instance of the model in the form of a simple, understandable line. For example, when working in an interactive console or in the administrator interface.

Redefinition of this method is required quite often, because the standard is not very useful.

get_absolute_url ()

This method tells Django an algorithm for calculating the URL for an object. It is used in the administrator interface, as well as every time you need to find out the URL of a certain object.

Each object that has a uniquely identifiable URL must contain this method.



Override predefined methods


There are several more model methods with which you can change the behavior of the database. In particular, it is often necessary to change the algorithm of the save () and delete () methods.

You can override these methods (as well as all the others in the model), and thereby change their behavior.

For example, the redefinition of built-in methods is used if you want some actions to be performed when saving an object (for more information about the parameters taken by the save () method, see the documentation ):
Copy Source | Copy HTML<br/> class Blog (models.Model):<br/> name = models.CharField(max_length= 100 )<br/> tagline = models.TextField()<br/> <br/> def save (self, force_insert=False, force_update=False):<br/> do_something()<br/> super ( Blog , self). save (force_insert, force_update) # The "real" save() method. <br/> do_something_else()

You can also prevent saving:
Copy Source | Copy HTML<br/> class Blog (models.Model):<br/> name = models.CharField(max_length= 100 )<br/> tagline = models.TextField()<br/> <br/> def save (self, force_isert=False, force_update=False):<br/> if self .name == "Yoko Ono's blog" :<br/> return # Yoko shall never have her own blog! <br/> else :<br/> super ( Blog , self). save (force_insert, force_update) # The "real" save() method. <br/>


It is important not to forget to call the method of the inherited class (in our example super (Blog, self) .save () ), to ensure that the data is saved to the database. If you forget to call this method, the database will remain untouched.



Using SQL


Another commonly used technique is to write your own SQL constructs in model methods or module methods. For more information about using raw SQL you can read the documentation .



Model inheritance

Added in Django version 1.0 : please read the release notes .

The principle of inheritance of models in Django is almost completely identical to the inheritance of classes in the Python language. The only decision you have to make is whether the inherited models will be a database table, or they will only be data keepers, and access to them will be possible only through derived models.

There are three types of inheritance in Django:
  1. Often, you need the base class to simply contain some information that you do not want to define in each derived model. Such a class will never be used as an independent unit, which means that the Abstract Base Classes will suit you best (as described below).
  2. If, when creating subclasses, you want each model to have its own table in the database, look towards Multi-tabular inheritance .
  3. Finally, if you want to change the behavior of a model at the Python level without changing its fields, use proxy models .



Abstract base classes


Abstract base classes are useful when you want to create several models with general information. Create a base class, put the parameter abstract = True in the Meta class, and this model will not be used when creating database tables. Instead, when it is used as the base for some model, its fields will be added to the derived class. If the field name in the base and derived class matches, Django will raise an exception.

Example:
Copy Source | Copy HTML<br/> class CommonInfo (models.Model):<br/> name = models.CharField(max_length= 100 )<br/> age = models.PositiveIntegerField()<br/> <br/> class Meta :<br/> abstract = True<br/> <br/> class Student ( CommonInfo ):<br/> home_group = models.CharField(max_length= 5 ) <br/>


The Student model will contain three fields: name, age, and home_group . Since the CommonInfo model is an abstract base class, it will not be used as a regular Django model: it will not generate a database table, have a manager , cannot save or create its instance directly.

In many cases, this type of inheritance will meet your requirements. This method allows you to "put out" the general information at the Python level, while at the database level, separate tables will be created for each derived class.



Meta Inheritance

When creating an abstract base class, Django makes the inner Meta class that you define in the base class available as an attribute. If a derived class Meta is not defined in the derived class, it will be inherited from the parent. However, if you wish, you can extend the base Meta class by using inheritance in the Meta classes. For example:
Copy Source | Copy HTML<br/> class CommonInfo (models.Model):<br/> ...<br/> class Meta :<br/> abstract = True<br/> ordering = [ 'name' ]<br/> <br/> class Student ( CommonInfo ):<br/> ...<br/> class Meta ( CommonInfo . Meta ):<br/> db_table = 'student_info' <br/>

Django makes only one adjustment in the Meta class of the abstract base class: before setting the Meta attribute, the abstract parameter is set to False . This is done so that derived classes do not automatically become abstract. Of course, you can create an abstract base class that inherits from another abstract base class. To do this, you just need to explicitly set abstract = True .

It does not make sense to add some attributes to the Meta class of the abstract base class. For example, adding the db_name parameter will mean that all derived classes that do not have their own Meta class will use the same database table. Almost certainly, this is not what you wanted.



Be careful with related_name

If you use the related_name attribute in the ForeignKey or ManyToManyField field , you must define a unique reverse name for each field. This usually results in a problem in abstract base classes, since all fields and their values ​​are added to each derived class.

To get around this problem, when using the related_name attribute in abstract base classes (and only in them), the string '% (class) s' should be part of the name. It will be replaced with the name of the lower-class derived class in which this field is used. Since classes have different names, each attribute will have a unique value. For example:
Copy Source | Copy HTML<br/> class Base (models.Model):<br/> m2m = models.ManyToManyField(OtherModel, related_name= "%(class)s_related" )<br/> <br/> class Meta :<br/> abstract = True<br/> <br/> class ChildA ( Base ):<br/> pass <br/> <br/> class ChildB ( Base ):<br/> pass <br/>

The reverse name ChildA.m2m will be childa_related , and for ChildB.m2m , childb_related . It’s up to you to use the % (class) s construct, but if you forget about it, Django will throw an exception when validating your models (or syncdb ).

If you did not define the related_name attribute for a field in an abstract base class, the reverse name will by default be the name of a lowercase derived class with the addition of the '_set' string, so that you explicitly define this field directly in the derived class. For example, for the text above, if the related_name attribute were omitted, the return names for the m2m fields would be childa_set for the ChildA class and childb_set in the case of the ChildB class.



That's all for today :) The next part will be the last in this section. I think, after its translation, create a survey - whether Habra needs these same translations or not. Will I continue to depend on its results. In the meantime, you need to complete the translation of what started)

to be continued
Any comments are welcome :)

Translation Django Documentation: Models. Part 1
Translation Django Documentation: Models. Part 2
Translation Django Documentation: Models. Part 4 (Last)

Source: https://habr.com/ru/post/75272/


All Articles