Ticket #3688: recursive-related-fields-4692.diff
File recursive-related-fields-4692.diff, 6.3 KB (added by , 18 years ago) |
---|
-
django/db/models/fields/related.py
6 6 from django.utils.translation import gettext_lazy, string_concat, ngettext 7 7 from django.utils.functional import curry 8 8 from django.core import validators 9 from django.core.exceptions import ImproperlyConfigured 9 10 from django import oldforms 10 11 from django import newforms as forms 11 12 from django.dispatch import dispatcher … … 23 24 24 25 def add_lookup(rel_cls, field): 25 26 name = field.rel.to 26 module = rel_cls.__module__ 27 key = (module, name) 27 # name should be either the name of a model in the same application or the 28 # name of a model in another application referenced with standard Django 29 # dotted notation ('appname.modelname') 30 if name.find('.') is -1: 31 app_name = rel_cls._meta.app_label 32 model_name = name 33 else: 34 try: 35 app_name, model_name = name.split('.') 36 except ValueError: 37 raise ImproperlyConfigured, "Invalid definition for field %s (%s). Please use app_name.model_name notation." % (field.name, name) 38 key = (app_name, model_name) 28 39 # Has the model already been loaded? 29 40 # If so, resolve the string reference right away 30 model = get_model( rel_cls._meta.app_label, field.rel.to, False)41 model = get_model(app_name, model_name, False) 31 42 if model: 32 43 field.rel.to = model 33 44 field.do_related_class(model, rel_cls) … … 37 48 38 49 def do_pending_lookups(sender): 39 50 other_cls = sender 40 key = (other_cls._ _module__, other_cls.__name__)51 key = (other_cls._meta.app_label, other_cls.__name__) 41 52 for rel_cls, field in pending_lookups.setdefault(key, []): 42 53 field.rel.to = other_cls 43 54 field.do_related_class(other_cls, rel_cls) -
docs/model-api.txt
682 682 manufacturer = models.ForeignKey(Manufacturer) 683 683 # ... 684 684 685 To create a recursive relationship -- an object that has a many-to-one 686 relationship with itself -- use ``models.ForeignKey('self')``. 685 For information on `recursive relationships`_, see below. 687 686 688 If you need to create a relationship on a model that has not yet been defined,689 you can use the name of the model, rather than the model object itself::690 691 class Car(models.Model):692 manufacturer = models.ForeignKey('Manufacturer')693 # ...694 695 class Manufacturer(models.Model):696 # ...697 698 Note, however, that you can only use strings to refer to models in the same699 models.py file -- you cannot use a string to reference a model in a different700 application, or to reference a model that has been imported from elsewhere.701 702 687 Behind the scenes, Django appends ``"_id"`` to the field name to create its 703 688 database column name. In the above example, the database table for the ``Car`` 704 689 model will have a ``manufacturer_id`` column. (You can change this explicitly … … 817 802 # ... 818 803 toppings = models.ManyToManyField(Topping) 819 804 820 As with ``ForeignKey``, a relationship to self can be defined by using the 821 string ``'self'`` instead of the model name, and you can refer to as-yet 822 undefined models by using a string containing the model name. However, you 823 can only use strings to refer to models in the same models.py file -- you 824 cannot use a string to reference a model in a different application, or to 825 reference a model that has been imported from elsewhere. 805 For information on `recursive relationships`_, see below. 826 806 827 807 It's suggested, but not required, that the name of a ``ManyToManyField`` 828 808 (``toppings`` in the example above) be a plural describing the set of related … … 910 890 could make ``Restaurant`` have a ``OneToOneField`` to ``Place`` (because a 911 891 restaurant "is-a" place). 912 892 913 As with ``ForeignKey``, a relationship to self can be defined by using the 914 string ``"self"`` instead of the model name; references to as-yet undefined 915 models can be made by using a string containing the model name. 893 For information on `recursive relationships`_, see below. 916 894 917 895 This ``OneToOneField`` will actually replace the primary key ``id`` field 918 896 (since one-to-one relations share the same primary key), and will be displayed … … 922 900 923 901 .. _One-to-one relationship model example: http://www.djangoproject.com/documentation/models/one_to_one/ 924 902 903 Recursive relationships 904 ~~~~~~~~~~~~~~~~~~~~~~~ 905 To create a recursive relationship -- an object that has a many-to-one 906 relationship with itself -- use ``models.ForeignKey('self')``. 907 908 If you need to create a relationship on a model that has not yet been defined, 909 you can use the name of the model, rather than the model object itself:: 910 911 class Car(models.Model): 912 manufacturer = models.ForeignKey('Manufacturer') 913 # ... 914 915 class Manufacturer(models.Model): 916 # ... 917 918 Note, however, that you can only use strings to refer to models in the same 919 models.py file -- you cannot use a string to reference a model in a different 920 application, or to reference a model that has been imported from elsewhere. 921 922 **New in Django development version:** String-based references have been 923 expanded to allow reference to models in other models.py files. This usage 924 provides a mechanism for enabling recursive relationships between 925 tightly-coupled objects that logically reside in different applications. 926 927 For example, consider a user class and a series of articles: 928 929 class User(models.Model): 930 saved_articles = models.ManyToManyField('Article') 931 # ... 932 933 class Article(models.Model): 934 author = models.ForeignKey(User) 935 # ... 936 937 It doesn't make much sense for users and articles to be stored in the same 938 models.py file. By using dotted-notation (``app_name.model_name``), it is 939 possible to reference across models.py files when recursive ``import`` 940 statements would otherwise cause problems. 941 942 my_project/accounts/models.py: 943 944 class User(models.Model): 945 saved_articles = models.ManyToManyField('articles.Article') 946 # ... 947 948 my_project/articles/models.py: 949 950 class Article(models.Model): 951 author = models.ForeignKey('accounts.User') 952 # ... 953 925 954 Meta options 926 955 ============ 927 956