Translation of Django Documentation: Models. Part 2

    image

    Good day!

    This topic is a continuation of the translation of the Django documentation , to be precise - the section on models .

    Translation of Django Documentation: Models. Part 1

    _____ Relationships between models
    _______ Many-to-
    many relationships _______ Many-to-many
    relationships _______ Many-to-many
    relationships _______ One-to-one relationships
    _____ Models and files
    _____ Restrictions on field names
    _____ Native field types

    Translation of Django Documentation: Models. Part 3
    Translation of Django Documentation: Models. Part 4 (Last)



    Relations between models


    Obviously, the main advantage of relational databases is the ability to define relationships between tables. Django provides the ability to identify the three most common types of relationships: many-to-one, many-to-many, and one-to-one relationships.



    Many-to-One

    Relationship A ForeignKey is used to define this type of relationship . Its use is no different from the use of other types of fields: just add the appropriate attribute to your model.

    When creating a field using ForeignKey , the method of the same name should be passed one positional argument: the class that your model will reference.

    For example, if a car ( Car ) has a manufacturer (Manufacturer ) (the manufacturer creates a large number of machines, but each machine has only one manufacturer), the following definition is used:
    Copy Source | Copy HTML
    class Manufacturer(models.Model):
        # ...
     
    class Car(models.Model):
        manufacturer = models.ForeignKey(Manufacturer)
        # ... 

    You can also create recursive relationships (an object with a many-to-one relationship that refers to itself) and relationships with an undefined model ; more details here .

    As a field name of type ForeignKey ( manufacturer in the example above), we recommend using the name of the model that your class refers to in lower case. This is an optional requirement, and you can name the field whatever you want. For instance:
    Copy Source | Copy HTML
    class Car(models.Model):
        company_that_makes_it = models.ForeignKey(Manufacturer)
        # ... 


    image
    You can find a more detailed example here - many-to-one relationship: example

    Fields of type ForeignKey can also have a number of additional arguments, which are discussed in the description of the fields of models . These optional parameters allow you to more accurately determine the relationship.



    Many to Many

    Relationships ManyToManyField is used to define this type of relationship . Its use is no different from the use of other types of fields: just add the appropriate attribute to your model.

    When creating a field using ManyToManyField , the method of the same name should be passed one positional argument: the class your model will reference.

    For example, if a Pizza has Topping (one pizza can have many toppings, which in turn can be found in many pizzas), you can imagine it like this:
    Copy Source | Copy HTML
    class Topping(models.Model):
        # ...
     
    class Pizza(models.Model):
        # ...
        toppings = models.ManyToManyField(Topping)

    As in the case of ForeignKey , you can create recursive relationships (an object with a many-to-one relationship that refers to itself) and relationships with an undefined model ; more details here .

    As a field name of type ManyToManyField ( toppings in the example above), we recommend using a plural noun that describes the set of related objects.

    It doesn’t matter which model has an attribute of type ManyToManyField , the main thing is that it is specified only in one of them.

    Typically, a field of type ManyToManyFielddefined in the object, which will subsequently be changed in the admin interface if you use the Django built-in admin panel (approx. sorry, or slang or tautology). In the above example of filling ( toppings ) are located on the pizza ( Pizza ), because it is more usual for us imagine pizza having different filling rather than a filling contained in the set of pizzas. If you describe the model as shown above, the Pizza form will allow users to choose the toppings.

    image
    You can find a more detailed example here - many-to-many relationship: example

    Fields of type ManyToManyField can also have a number of additional arguments, which are discussed in the description of model fields. These optional parameters allow you to more accurately determine the relationship.



    Additional many-to-many fields are
    added in version Django 1.0 : please read the release notes .

    As long as you are dealing with trivial many-to-many relationships, such as combining and matching pizzas and toppings, all you need is the standard ManyToManyField type . However, sometimes you may need to associate data using a relationship between two models.

    For example, consider a case where an application tracks groups in which some musicians have participated. The relationship between the musician and the groups of which he was or is a member will be many-to-many, so you can use ManyToManyField to represent him . However, you may also be interested in a large number of details, such as the date you joined the group or the reason the musician left it.

    For such situations, Django provides you with the ability to define a separate (intermediate) model that will be used to manage many-to-many relationships. You can create additional fields in an intermediate model. Intermediate model interacts with ManyToManyField using arguments throughwho acts as an intermediary. For our musical (:)) example, the code will look something like this:
    Copy Source | Copy HTML
    class Person(models.Model):
        name = models.CharField(max_length=128)
     
        def __unicode__(self):
            return self.name
     
    class Group(models.Model):
        name = models.CharField(max_length=128)
        members = models.ManyToManyField(Person, through='Membership')
     
        def __unicode__(self):
            return self.name
     
    class Membership(models.Model):
        person = models.ForeignKey(Person)
        group = models.ForeignKey(Group)
        date_joined = models.DateField()
        invite_reason = models.CharField(max_length=64)

    When creating an intermediate model, you explicitly specify foreign keys for models that are involved in a many-to-many relationship. This is an unambiguous declaration and defines how objects interact.

    There are several limitations regarding intermediate models:
    • Your intermediate model must contain one and only one foreign key to the target model (in our example, this is Person ), otherwise a validation error will be generated .
    • Your intermediate model must contain one and only one foreign key to the original model (in our example it is Group ), otherwise a validation error will be generated .
    • The one exception is a model that has many-to-many relationships with itself and refers to itself using an intermediate model. In this case, it is allowed to use two foreign keys to the same model, but they will be considered as two different parts in many-to-many relationships.
    • To define a model that refers to itself using an intermediate model, you should use symmetrical = False (for more details see the help on model fields ).

      Now that you have configured ManyToManyField to interact with your intermediate model, you can start creating several many-to-many relationships. This is done by instantiating your intermediate model:
      Copy Source | Copy HTML
      >>> ringo = Person.objects.create(name="Ringo Starr")
      >>> paul = Person.objects.create(name="Paul McCartney")
      >>> beatles = Group.objects.create(name="The Beatles")
      >>> m1 = Membership(person=ringo, group=beatles,
      ... date_joined=date(1962, 8, 16),
      ... invite_reason= "Needed a new drummer.")
      >>> m1.save()
      >>> beatles.members.all()
      []
      >>> ringo.group_set.all()
      []
      >>> m2 = Membership.objects.create(person=paul, group=beatles,
      ... date_joined=date(1960, 8, 1),
      ... invite_reason= "Wanted to form a band.")
      >>> beatles.members.all()
      [, ]

      Not very similar to regular fields: you cannot use the add and create methods , as well as the assignment operation (for example, beatles.members = [...] ) to determine the relationship:
      Copy Source | Copy HTML
      # THIS WILL NOT WORK
      >>> beatles.members.add(john)
      # NEITHER WILL THIS
      >>> beatles.members.create(name="George Harrison")
      # AND NEITHER WILL THIS
      >>> beatles.members = [john, paul, ringo, george]

      Why? You cannot just create a relationship between Person and Group , so you must specify all the details of the relationship required by the Membership middleware . The simple add , create, and assignment methods do not provide the ability to define additional details. Therefore, they are disabled in many-to-many relationships using an intermediate model. The only option for creating this type of relationship is to instantiate an intermediate model.

      The remove method is disabled for the same reasons. However, you can use the clear () method to remove all many-to-many relationships of an instance:
      Copy Source | Copy HTML
      # Beatles have broken up
      >>> beatles.members.clear()

      So, you have created many-to-many relationships by creating instances of the intermediate model, now you can issue queries. As in the case of the normal variant of relations, you can compose queries using the model attributes:
      Copy Source | Copy HTML
      # Find all the groups with a member whose name starts with 'Paul'
      >>> Group.objects.filter(members__name__startswith='Paul')
      []

      Since you are using an intermediate model, you can also issue queries using the attributes of the intermediary model:
      Copy Source | Copy HTML
      # Find all the members of the Beatles that joined after 1 Jan 1961
      >>> Person.objects.filter(
      ... group__name='The Beatles',
      ... membership__date_joined__gt=date(1961,1,1))
      [




      One-to-One

      Relationship OneToOneField is used to determine this type of relationship . Its use is no different from the use of other types of fields: just add the appropriate attribute to your model.

      This type of relationship is most useful when one of the objects connected by the relationship somehow extends or complements the other.

      When creating a field using OneToOneField , the method of the same name must be passed one positional argument: the class your model will reference.

      For example, if you decide to create a Places database, you will most likely add completely standard things to it, such as an address, telephone, and so on. If you want to create a new database of restaurants located in places from the first database, instead of repeating and duplicating information in the fields of the Restaurant model , you can establish a one-to-one relationship between Restaurant and Place using OneToOneField (because , in fact, is the place; to cope with this task you will have to use inheritance , which implicitly includes a one-to-one relationship).

      Just like with ForeignKey , you can createrecursive relationships and relationships with an undefined model ; more details here .

      image
      You can find a more detailed example here - one-to-one relationship: an example was

      added in Django version 1.0 : please read the release notes .
      Fields of the OneToOneField type take one optional argument, discussed in the description of the model fields .

      Previously, OneToOneField classes automatically became the primary keys of a model. This is no longer the case (although the ability to set primary_key manually remains). Thus, it is now possible to have several fields of typeOneToOneField in one model.



      Models and Files


      It is possible to link two models from different applications. For this, you need to import the desired model to the top of our model, and then just refer to another class, if necessary. For instance:
      Copy Source | Copy HTML
      from mysite.geography.models import ZipCode
       
      class Restaurant(models.Model):
          # ...
          zip_code = models.ForeignKey(ZipCode)




      Field Name Restrictions


      Django sets two restrictions on field names:
      1. The field name cannot be a reserved Python language word, otherwise it will cause a syntax error. For instance:
        Copy Source | Copy HTML
        class Example(models.Model):
            pass = models.IntegerField() # 'pass' is a reserved word! 
      2. A field name cannot contain more than one underscore character in a row. This is a consequence of the query search system in Django. For instance:
        Copy Source | Copy HTML
        class Example(models.Model):
            foo__bar = models.IntegerField() # 'foo__bar' has two underscores! 


      These restrictions can be circumvented because your fields do not have to match the column name in the database (see db_column option ).

      SQL reserved words, such as join , where or select, can be used as field names due to the fact that Django “leaves” all the columns and columns of the database with each SQL query. Database engines use referential syntax.



      Custom field types

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

      If none of the existing field types can be used to achieve your goals, or if you want to take advantage of one of the less common column types, you can create your own field class. Full information on creating fields is provided in the section on writing your own field types .



      That's all for today :) to be continued
      I will be happy to listen to any of your suggestions, questions and comments.

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

    Also popular now: