26 нояб. 2009 г.

Ситуация с Many-to-Many в django

На днях контрибуторы django что-то там поменяли с сырыми sql-запросами для Many-to-Many полей. Это было сделано для поддержки нескольких баз и повышения какой-то там безопасности (видимо, при удалении связанных элементов удалялось что-то лишнее).

В общем, одно можно сказать точно: в документации к Many-to-Many полям появились такие строки:


  1051 Working with Many-to-Many Models 

  1052 -------------------------------- 

  1053  

  1054 By default, admin widgets for many-to-many relations will be displayed 

  1055 on whichever model contains the actual reference to the ``ManyToManyField``. 

  1056 Depending on your ``ModelAdmin`` definition, each many-to-many field in your 

  1057 model will be represented by a standard HTML ``<select multiple>``, a 

  1058 horizontal or vertical filteror a ``raw_id_admin`` widget. However, it is 

  1059 also possible to to replace these widgets with inlines. 

  1060  

  1061 Suppose we have the following models:: 

  1062  

  1063     class Person(models.Model): 

  1064         name = models.CharField(max_length=128

  1065  

  1066     class Group(models.Model): 

  1067         name = models.CharField(max_length=128

  1068         members = models.ManyToManyField(Person, related_name='groups'

  1069  

  1070 If you want to display many-to-many relations using an inline, you can do 

  1071 so by defining an ``InlineModelAdmin`` object for the relationship. 

  1072  

  1073     class MembershipInline(admin.TabularInline): 

  1074         model = Group.members.through 

  1075  

  1076     class PersonAdmin(admin.ModelAdmin): 

  1077         inlines = [ 

  1078             MembershipInline, 

  1079         ] 

  1080  

  1081     class GroupAdmin(admin.ModelAdmin): 

  1082         inlines = [ 

  1083             MembershipInline, 

  1084         ] 

  1085         exclude = ('members',) 

  1086  

  1087 There are two features worth noting in this example. 

  1088  

  1089 Firstly - the ``MembershipInline`` class references ``Group.members.through``. 

  1090 The ``through`` attribute is a reference to the model that manages the 

  1091 many-to-many relation. This model is automatically created by Django when you 

  1092 define a many-to-many field. 

  1093  

  1094 Secondly, the ``GroupAdmin`` must manually exclude the ``members`` field. 

  1095 Django displays an admin widget for a many-to-many field on the model that 

  1096 defines the relation (in this case, ``Group``). If you want to use an inline 

  1097 model to represent the many-to-many relationship, you must tell Django's admin 

  1098 to *not* display this widget - otherwise you will end up with two widgets on 

  1099 your admin page for managing the relation. 

  1100  

  1101 In all other respects, the ``InlineModelAdmin`` is exactly the same as any 

  1102 other. You can customize the appearance using any of the normal 

  1103 ``InlineModelAdmin`` properties. 


Суть: теперь у нас есть новая возможность, сделать inline (модель в модели, в админке) редактирование самизнаетекаких полей. Сие – благо. В цмске для посуточной аренды у меня до сих пор вылазят какие-то проблемы с виджетом для списка сайтов (связанных со страницами).

2 комментария:

Unknown комментирует...

Оно, вроде, сто лет было, просто недавно исправили багу с .through для промежуточных моделей, указанных текстом. Или не о том речь?

Ivan Markeev комментирует...

На сколько я понимаю, инлайн оно раньше не работало. У меня например, не through, не симетрикал не решали проблему. Виджеты валились с ошибкой, о нескольких результатах соответствующих запросу.