Ticket #7369: null_fk_r7574.patch

File null_fk_r7574.patch, 4.2 KB (added by George Vilches, 16 years ago)

Patch to correct non-null relationships after null ForeignKeys, against r7574.

  • django/db/models/sql/query.py

     
    851851        return alias
    852852
    853853    def fill_related_selections(self, opts=None, root_alias=None, cur_depth=1,
    854             used=None, requested=None, restricted=None):
     854            used=None, requested=None, restricted=None, nullable=None):
    855855        """
    856856        Fill in the information needed for a select_related query. The current
    857857        depth is measured as the number of connections away from the root model
     
    883883                    (not restricted and f.null) or f.rel.parent_link):
    884884                continue
    885885            table = f.rel.to._meta.db_table
     886            if nullable or f.null:
     887                promote = True
     888            else:
     889                promote = False
    886890            if model:
    887891                int_opts = opts
    888892                alias = root_alias
     
    891895                    int_opts = int_model._meta
    892896                    alias = self.join((alias, int_opts.db_table, lhs_col,
    893897                            int_opts.pk.column), exclusions=used,
    894                             promote=f.null)
     898                            promote=promote)
    895899            else:
    896900                alias = root_alias
    897901            alias = self.join((alias, table, f.column,
    898902                    f.rel.get_related_field().column), exclusions=used,
    899                     promote=f.null)
     903                    promote=promote)
    900904            used.add(alias)
    901905            self.related_select_cols.extend([(alias, f2.column)
    902906                    for f2 in f.rel.to._meta.fields])
     
    905909                next = requested.get(f.name, {})
    906910            else:
    907911                next = False
     912            if f.null is not None:
     913                new_nullable = f.null
     914            else:
     915                new_nullable = None
    908916            self.fill_related_selections(f.rel.to._meta, alias, cur_depth + 1,
    909                     used, next, restricted)
     917                    used, next, restricted, new_nullable)
    910918
    911919    def add_filter(self, filter_expr, connector=AND, negate=False, trim=False,
    912920            can_reuse=None):
  • tests/modeltests/null_fk/models.py

     
     1"""
     2
     3"""
     4
     5from django.db import models
     6
     7class SystemInfo(models.Model):
     8    system_name = models.CharField(max_length=32)
     9
     10
     11class Forum(models.Model):
     12    system_info = models.ForeignKey(SystemInfo)
     13    forum_name = models.CharField(max_length=32)
     14
     15
     16class Post(models.Model):
     17    forum = models.ForeignKey(Forum, null=True)
     18    title = models.CharField(max_length=32)
     19
     20    def __unicode__(self):
     21        return self.title
     22
     23
     24class Comment(models.Model):
     25    post = models.ForeignKey(Post, null=True)
     26    comment_text = models.CharField(max_length=250)
     27   
     28    def __unicode__(self):
     29        return self.comment_text
     30   
     31
     32__test__ = {'API_TESTS':"""
     33
     34>>> s = SystemInfo.objects.create(system_name='First forum')
     35>>> f = Forum.objects.create(system_info=s, forum_name='First forum')
     36>>> p = Post.objects.create(forum=f, title='First Post')
     37>>> c = Comment.objects.create(post=p, comment_text='My first comment')
     38>>> c = Comment.objects.create(comment_text='My second comment')
     39
     40# Starting from comment, make sure that a .select_related(...) with a specified
     41# set of fields will properly LEFT JOIN multiple levels of NULLs (and the things
     42# that come after the NULLs, or else data that should exist won't).
     43>>> c = Comment.objects.select_related().get(id=1)
     44>>> c.post
     45<Post: First Post>
     46>>> c = Comment.objects.select_related().get(id=2)
     47>>> c.post
     48
     49>>> comments = Comment.objects.select_related('post__forum__system_info').all()
     50>>> [(c.id, c.post.id) for c in comments]
     51[(1, 1), (2, None)]
     52>>> [(c.comment_text, c.post.title) for c in comments]
     53[(u'My first comment', u'First Post'), (u'My second comment', None)]
     54
     55"""}
     56   
     57 No newline at end of file
Back to Top