Exemple #1
0
 def setUp(self):
     # Create a few Reporters.
     self.r = Reporter(first_name='John', last_name='Smith', email='*****@*****.**')
     self.r.save()
     self.r2 = Reporter(first_name='Paul', last_name='Jones', email='*****@*****.**')
     self.r2.save()
     # Create an Article.
     self.a = Article(id=None, headline="This is a test",
                      pub_date=datetime(2005, 7, 27), reporter=self.r)
     self.a.save()
Exemple #2
0
 def setUp(self):
     # Create a few Reporters.
     self.r = Reporter(first_name='John', last_name='Smith', email='*****@*****.**')
     self.r.save()
     self.r2 = Reporter(first_name='Paul', last_name='Jones', email='*****@*****.**')
     self.r2.save()
     # Create an Article.
     self.a = Article(id=None, headline="This is a test",
                      pub_date=datetime(2005, 7, 27), reporter=self.r)
     self.a.save()
Exemple #3
0
def reporter():
    from models import db as thisdb
    if request.method == "GET":
        return render_template("reporter.html")
    else:
        title = request.form.get('title')
        content = request.form.get('content')
        reporter = Reporter(title=title, content=content)
        user_id = session.get('user_id')
        user = User.query.filter(User.id == user_id).first()
        reporter.author = user
        thisdb.session.add(reporter)
        thisdb.session.commit()
        return redirect(url_for('forum'))
Exemple #4
0
 def setUp(self):
     # Create a Reporter.
     self.r = Reporter(name='John Smith')
     self.r.save()
     # Create an Article.
     self.a = Article(headline="First", reporter=self.r)
     self.a.save()
     # Create an Article via the Reporter object.
     self.a2 = self.r.article_set.create(headline="Second")
     # Create an Article with no Reporter by passing "reporter=None".
     self.a3 = Article(headline="Third", reporter=None)
     self.a3.save()
     # Create another article and reporter
     self.r2 = Reporter(name='Paul Jones')
     self.r2.save()
     self.a4 = self.r2.article_set.create(headline='Fourth')
Exemple #5
0
 def setUp(self):
     # Create a Reporter.
     self.r = Reporter(name="John Smith")
     self.r.save()
     # Create an Article.
     self.a = Article(headline="First", reporter=self.r)
     self.a.save()
     # Create an Article via the Reporter object.
     self.a2 = self.r.article_set.create(headline="Second")
     # Create an Article with no Reporter by passing "reporter=None".
     self.a3 = Article(headline="Third", reporter=None)
     self.a3.save()
     # Create another article and reporter
     self.r2 = Reporter(name="Paul Jones")
     self.r2.save()
     self.a4 = self.r2.article_set.create(headline="Fourth")
Exemple #6
0
class ManyToOneTests(TestCase):
    def setUp(self):
        # Create a few Reporters.
        self.r = Reporter(first_name='John', last_name='Smith', email='*****@*****.**')
        self.r.save()
        self.r2 = Reporter(first_name='Paul', last_name='Jones', email='*****@*****.**')
        self.r2.save()
        # Create an Article.
        self.a = Article(id=None, headline="This is a test",
                         pub_date=datetime(2005, 7, 27), reporter=self.r)
        self.a.save()

    def test_get(self):
        # Article objects have access to their related Reporter objects.
        r = self.a.reporter
        self.assertEqual(r.id, self.r.id)
        # These are strings instead of unicode strings because that's what was used in
        # the creation of this reporter (and we haven't refreshed the data from the
        # database, which always returns unicode strings).
        self.assertEqual((r.first_name, self.r.last_name), ('John', 'Smith'))

    def test_create(self):
        # You can also instantiate an Article by passing the Reporter's ID
        # instead of a Reporter object.
        a3 = Article(id=None, headline="Third article",
                     pub_date=datetime(2005, 7, 27), reporter_id=self.r.id)
        a3.save()
        self.assertEqual(a3.reporter.id, self.r.id)

        # Similarly, the reporter ID can be a string.
        a4 = Article(id=None, headline="Fourth article",
                     pub_date=datetime(2005, 7, 27), reporter_id=str(self.r.id))
        a4.save()
        self.assertEqual(repr(a4.reporter), "<Reporter: John Smith>")

    def test_add(self):
        # Create an Article via the Reporter object.
        new_article = self.r.article_set.create(headline="John's second story",
                                                pub_date=datetime(2005, 7, 29))
        self.assertEqual(repr(new_article), "<Article: John's second story>")
        self.assertEqual(new_article.reporter.id, self.r.id)

        # Create a new article, and add it to the article set.
        new_article2 = Article(headline="Paul's story", pub_date=datetime(2006, 1, 17))
        self.r.article_set.add(new_article2)
        self.assertEqual(new_article2.reporter.id, self.r.id)
        self.assertQuerysetEqual(self.r.article_set.all(),
            [
                "<Article: John's second story>",
                "<Article: Paul's story>",
                "<Article: This is a test>",
            ])

        # Add the same article to a different article set - check that it moves.
        self.r2.article_set.add(new_article2)
        self.assertEqual(new_article2.reporter.id, self.r2.id)
        self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Paul's story>"])

        # Adding an object of the wrong type raises TypeError.
        self.assertRaises(TypeError, self.r.article_set.add, self.r2)
        self.assertQuerysetEqual(self.r.article_set.all(),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])

    def test_assign(self):
        new_article = self.r.article_set.create(headline="John's second story",
                                                pub_date=datetime(2005, 7, 29))
        new_article2 = self.r2.article_set.create(headline="Paul's story",
                                                  pub_date=datetime(2006, 1, 17))
        # Assign the article to the reporter directly using the descriptor.
        new_article2.reporter = self.r
        new_article2.save()
        self.assertEqual(repr(new_article2.reporter), "<Reporter: John Smith>")
        self.assertEqual(new_article2.reporter.id, self.r.id)
        self.assertQuerysetEqual(self.r.article_set.all(), [
            "<Article: John's second story>",
            "<Article: Paul's story>",
            "<Article: This is a test>",
        ])
        self.assertQuerysetEqual(self.r2.article_set.all(), [])
        # Set the article back again using set descriptor.
        self.r2.article_set = [new_article, new_article2]
        self.assertQuerysetEqual(self.r.article_set.all(), ["<Article: This is a test>"])
        self.assertQuerysetEqual(self.r2.article_set.all(),
            [
                "<Article: John's second story>",
                "<Article: Paul's story>",
            ])

        # Funny case - assignment notation can only go so far; because the
        # ForeignKey cannot be null, existing members of the set must remain.
        self.r.article_set = [new_article]
        self.assertQuerysetEqual(self.r.article_set.all(),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Paul's story>"])
        # Reporter cannot be null - there should not be a clear or remove method
        self.assertFalse(hasattr(self.r2.article_set, 'remove'))
        self.assertFalse(hasattr(self.r2.article_set, 'clear'))

    def test_selects(self):
        new_article = self.r.article_set.create(headline="John's second story",
                                                pub_date=datetime(2005, 7, 29))
        new_article2 = self.r2.article_set.create(headline="Paul's story",
                                                  pub_date=datetime(2006, 1, 17))
        # Reporter objects have access to their related Article objects.
        self.assertQuerysetEqual(self.r.article_set.all(), [
            "<Article: John's second story>",
            "<Article: This is a test>",
        ])
        self.assertQuerysetEqual(self.r.article_set.filter(headline__startswith='This'),
                                 ["<Article: This is a test>"])
        self.assertEqual(self.r.article_set.count(), 2)
        self.assertEqual(self.r2.article_set.count(), 1)
        # Get articles by id
        self.assertQuerysetEqual(Article.objects.filter(id__exact=self.a.id),
                                 ["<Article: This is a test>"])
        self.assertQuerysetEqual(Article.objects.filter(pk=self.a.id),
                                 ["<Article: This is a test>"])
        # Query on an article property
        self.assertQuerysetEqual(Article.objects.filter(headline__startswith='This'),
                                 ["<Article: This is a test>"])
        # The API automatically follows relationships as far as you need.
        # Use double underscores to separate relationships.
        # This works as many levels deep as you want. There's no limit.
        # Find all Articles for any Reporter whose first name is "John".
        self.assertQuerysetEqual(Article.objects.filter(reporter__first_name__exact='John'),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        # Check that implied __exact also works
        self.assertQuerysetEqual(Article.objects.filter(reporter__first_name='John'),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        # Query twice over the related field.
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__first_name__exact='John',
                                   reporter__last_name__exact='Smith'),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        # The underlying query only makes one join when a related table is referenced twice.
        queryset = Article.objects.filter(reporter__first_name__exact='John',
                                       reporter__last_name__exact='Smith')
        self.assertNumQueries(1, list, queryset)
        self.assertEqual(queryset.query.get_compiler(queryset.db).as_sql()[0].count('INNER JOIN'), 1)

        # The automatically joined table has a predictable name.
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__first_name__exact='John').extra(
                where=["many_to_one_reporter.last_name='Smith'"]),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        # ... and should work fine with the unicode that comes out of forms.Form.cleaned_data
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__first_name__exact='John'
                                  ).extra(where=["many_to_one_reporter.last_name='%s'" % u'Smith']),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        # Find all Articles for a Reporter.
        # Use direct ID check, pk check, and object comparison
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__id__exact=self.r.id),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__pk=self.r.id),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(
            Article.objects.filter(reporter=self.r.id),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(
            Article.objects.filter(reporter=self.r),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__in=[self.r.id,self.r2.id]).distinct(),
            [
                    "<Article: John's second story>",
                    "<Article: Paul's story>",
                    "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__in=[self.r,self.r2]).distinct(),
            [
                "<Article: John's second story>",
                "<Article: Paul's story>",
                "<Article: This is a test>",
            ])
        # You can also use a queryset instead of a literal list of instances.
        # The queryset must be reduced to a list of values using values(),
        # then converted into a query
        self.assertQuerysetEqual(
            Article.objects.filter(
                        reporter__in=Reporter.objects.filter(first_name='John').values('pk').query
                    ).distinct(),
            [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])

    def test_reverse_selects(self):
        a3 = Article.objects.create(id=None, headline="Third article",
                                    pub_date=datetime(2005, 7, 27), reporter_id=self.r.id)
        a4 = Article.objects.create(id=None, headline="Fourth article",
                                    pub_date=datetime(2005, 7, 27), reporter_id=str(self.r.id))
        # Reporters can be queried
        self.assertQuerysetEqual(Reporter.objects.filter(id__exact=self.r.id),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(Reporter.objects.filter(pk=self.r.id),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(Reporter.objects.filter(first_name__startswith='John'),
                                 ["<Reporter: John Smith>"])
        # Reporters can query in opposite direction of ForeignKey definition
        self.assertQuerysetEqual(Reporter.objects.filter(article__id__exact=self.a.id),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(Reporter.objects.filter(article__pk=self.a.id),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(Reporter.objects.filter(article=self.a.id),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(Reporter.objects.filter(article=self.a),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__in=[self.a.id,a3.id]).distinct(),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__in=[self.a.id,a3]).distinct(),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__in=[self.a,a3]).distinct(),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__headline__startswith='T'),
            ["<Reporter: John Smith>", "<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__headline__startswith='T').distinct(),
            ["<Reporter: John Smith>"])

        # Counting in the opposite direction works in conjunction with distinct()
        self.assertEqual(
            Reporter.objects.filter(article__headline__startswith='T').count(), 2)
        self.assertEqual(
            Reporter.objects.filter(article__headline__startswith='T').distinct().count(), 1)

        # Queries can go round in circles.
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__reporter__first_name__startswith='John'),
            [
                "<Reporter: John Smith>",
                "<Reporter: John Smith>",
                "<Reporter: John Smith>",
            ])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct(),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__reporter__exact=self.r).distinct(),
            ["<Reporter: John Smith>"])

        # Check that implied __exact also works.
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__reporter=self.r).distinct(),
            ["<Reporter: John Smith>"])

        # It's possible to use values() calls across many-to-one relations.
        # (Note, too, that we clear the ordering here so as not to drag the
        # 'headline' field into the columns being used to determine uniqueness)
        d = {'reporter__first_name': u'John', 'reporter__last_name': u'Smith'}
        self.assertEqual([d],
            list(Article.objects.filter(reporter=self.r).distinct().order_by()
                 .values('reporter__first_name', 'reporter__last_name')))

    def test_select_related(self):
        # Check that Article.objects.select_related().dates() works properly when
        # there are multiple Articles with the same date but different foreign-key
        # objects (Reporters).
        r1 = Reporter.objects.create(first_name='Mike', last_name='Royko', email='*****@*****.**')
        r2 = Reporter.objects.create(first_name='John', last_name='Kass', email='*****@*****.**')
        a1 = Article.objects.create(headline='First', pub_date=datetime(1980, 4, 23), reporter=r1)
        a2 = Article.objects.create(headline='Second', pub_date=datetime(1980, 4, 23), reporter=r2)
        self.assertEqual(list(Article.objects.select_related().dates('pub_date', 'day')),
            [
                datetime(1980, 4, 23, 0, 0),
                datetime(2005, 7, 27, 0, 0),
            ])
        self.assertEqual(list(Article.objects.select_related().dates('pub_date', 'month')),
            [
                datetime(1980, 4, 1, 0, 0),
                datetime(2005, 7, 1, 0, 0),
            ])
        self.assertEqual(list(Article.objects.select_related().dates('pub_date', 'year')),
            [
                datetime(1980, 1, 1, 0, 0),
                datetime(2005, 1, 1, 0, 0),
            ])

    def test_delete(self):
        new_article = self.r.article_set.create(headline="John's second story",
                                                pub_date=datetime(2005, 7, 29))
        new_article2 = self.r2.article_set.create(headline="Paul's story",
                                                  pub_date=datetime(2006, 1, 17))
        a3 = Article.objects.create(id=None, headline="Third article",
                                    pub_date=datetime(2005, 7, 27), reporter_id=self.r.id)
        a4 = Article.objects.create(id=None, headline="Fourth article",
                                    pub_date=datetime(2005, 7, 27), reporter_id=str(self.r.id))
        # If you delete a reporter, his articles will be deleted.
        self.assertQuerysetEqual(Article.objects.all(),
            [
                "<Article: Fourth article>",
                "<Article: John's second story>",
                "<Article: Paul's story>",
                "<Article: Third article>",
                "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(Reporter.objects.order_by('first_name'),
            [
                "<Reporter: John Smith>",
                "<Reporter: Paul Jones>",
            ])
        self.r2.delete()
        self.assertQuerysetEqual(Article.objects.all(),
            [
                "<Article: Fourth article>",
                "<Article: John's second story>",
                "<Article: Third article>",
                "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(Reporter.objects.order_by('first_name'),
                                 ["<Reporter: John Smith>"])
        # You can delete using a JOIN in the query.
        Reporter.objects.filter(article__headline__startswith='This').delete()
        self.assertQuerysetEqual(Reporter.objects.all(), [])
        self.assertQuerysetEqual(Article.objects.all(), [])

    def test_regression_12876(self):
        # Regression for #12876 -- Model methods that include queries that
        # recursive don't cause recursion depth problems under deepcopy.
        self.r.cached_query = Article.objects.filter(reporter=self.r)
        self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>")

    def test_explicit_fk(self):
        # Create a new Article with get_or_create using an explicit value
        # for a ForeignKey.
        a2, created = Article.objects.get_or_create(id=None,
                                                    headline="John's second test",
                                                    pub_date=datetime(2011, 5, 7),
                                                    reporter_id=self.r.id)
        self.assertTrue(created)
        self.assertEqual(a2.reporter.id, self.r.id)

        # You can specify filters containing the explicit FK value.
        self.assertQuerysetEqual(
            Article.objects.filter(reporter_id__exact=self.r.id),
            [
                "<Article: John's second test>",
                "<Article: This is a test>",
            ])

        # Create an Article by Paul for the same date.
        a3 = Article.objects.create(id=None, headline="Paul's commentary",
                                    pub_date=datetime(2011, 5, 7),
                                    reporter_id=self.r2.id)
        self.assertEqual(a3.reporter.id, self.r2.id)

        # Get should respect explicit foreign keys as well.
        self.assertRaises(MultipleObjectsReturned,
                          Article.objects.get, reporter_id=self.r.id)
        self.assertEqual(repr(a3),
                         repr(Article.objects.get(reporter_id=self.r2.id,
                                             pub_date=datetime(2011, 5, 7))))

    def test_manager_class_caching(self):
        r1 = Reporter.objects.create(first_name='Mike')
        r2 = Reporter.objects.create(first_name='John')

        # Same twice
        self.assertTrue(r1.article_set.__class__ is r1.article_set.__class__)

        # Same as each other
        self.assertTrue(r1.article_set.__class__ is r2.article_set.__class__)
Exemple #7
0
 def manually_managed_mistake(self):
     r = Reporter(first_name="Edward", last_name="Woodward")
     r.save()
Exemple #8
0
 def manually_managed(self):
     r = Reporter(first_name="Dirk", last_name="Gently")
     r.save()
     transaction.commit()
Exemple #9
0
 def create_a_reporter_then_fail(self, first, last):
     a = Reporter(first_name=first, last_name=last)
     a.save()
     raise Exception("I meant to do that")
Exemple #10
0
 def manually_managed_mistake(self):
     r = Reporter(first_name="Edward", last_name="Woodward")
     r.save()
Exemple #11
0
 def manually_managed(self):
     r = Reporter(first_name="Dirk", last_name="Gently")
     r.save()
     transaction.commit()
Exemple #12
0
 def create_a_reporter_then_fail(self, first, last):
     a = Reporter(first_name=first, last_name=last)
     a.save()
     raise Exception("I meant to do that")
Exemple #13
0
class ManyToOneNullTests(TestCase):
    def setUp(self):
        # Create a Reporter.
        self.r = Reporter(name='John Smith')
        self.r.save()
        # Create an Article.
        self.a = Article(headline="First", reporter=self.r)
        self.a.save()
        # Create an Article via the Reporter object.
        self.a2 = self.r.article_set.create(headline="Second")
        # Create an Article with no Reporter by passing "reporter=None".
        self.a3 = Article(headline="Third", reporter=None)
        self.a3.save()
        # Create another article and reporter
        self.r2 = Reporter(name='Paul Jones')
        self.r2.save()
        self.a4 = self.r2.article_set.create(headline='Fourth')

    def test_get_related(self):
        self.assertEqual(self.a.reporter.id, self.r.id)
        # Article objects have access to their related Reporter objects.
        r = self.a.reporter
        self.assertEqual(r.id, self.r.id)

    def test_created_via_related_set(self):
        self.assertEqual(self.a2.reporter.id, self.r.id)

    def test_related_set(self):
        # Reporter objects have access to their related Article objects.
        self.assertQuerysetEqual(self.r.article_set.all(),
                                 ['<Article: First>', '<Article: Second>'])
        self.assertQuerysetEqual(
            self.r.article_set.filter(headline__startswith='Fir'),
            ['<Article: First>'])
        self.assertEqual(self.r.article_set.count(), 2)

    def test_created_without_related(self):
        self.assertEqual(self.a3.reporter, None)
        # Need to reget a3 to refresh the cache
        a3 = Article.objects.get(pk=self.a3.pk)
        self.assertRaises(AttributeError, getattr, a3.reporter, 'id')
        # Accessing an article's 'reporter' attribute returns None
        # if the reporter is set to None.
        self.assertEqual(a3.reporter, None)
        # To retrieve the articles with no reporters set, use "reporter__isnull=True".
        self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True),
                                 ['<Article: Third>'])
        # We can achieve the same thing by filtering for the case where the
        # reporter is None.
        self.assertQuerysetEqual(Article.objects.filter(reporter=None),
                                 ['<Article: Third>'])
        # Set the reporter for the Third article
        self.assertQuerysetEqual(self.r.article_set.all(),
                                 ['<Article: First>', '<Article: Second>'])
        self.r.article_set.add(a3)
        self.assertQuerysetEqual(
            self.r.article_set.all(),
            ['<Article: First>', '<Article: Second>', '<Article: Third>'])
        # Remove an article from the set, and check that it was removed.
        self.r.article_set.remove(a3)
        self.assertQuerysetEqual(self.r.article_set.all(),
                                 ['<Article: First>', '<Article: Second>'])
        self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True),
                                 ['<Article: Third>'])

    def test_remove_from_wrong_set(self):
        self.assertQuerysetEqual(self.r2.article_set.all(),
                                 ['<Article: Fourth>'])
        # Try to remove a4 from a set it does not belong to
        self.assertRaises(Reporter.DoesNotExist, self.r.article_set.remove,
                          self.a4)
        self.assertQuerysetEqual(self.r2.article_set.all(),
                                 ['<Article: Fourth>'])

    def test_assign_clear_related_set(self):
        # Use descriptor assignment to allocate ForeignKey. Null is legal, so
        # existing members of set that are not in the assignment set are set null
        self.r2.article_set = [self.a2, self.a3]
        self.assertQuerysetEqual(self.r2.article_set.all(),
                                 ['<Article: Second>', '<Article: Third>'])
        # Clear the rest of the set
        self.r.article_set.clear()
        self.assertQuerysetEqual(self.r.article_set.all(), [])
        self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True),
                                 ['<Article: First>', '<Article: Fourth>'])
Exemple #14
0
class ManyToOneTests(TestCase):
    def setUp(self):
        # Create a few Reporters.
        self.r = Reporter(first_name='John',
                          last_name='Smith',
                          email='*****@*****.**')
        self.r.save()
        self.r2 = Reporter(first_name='Paul',
                           last_name='Jones',
                           email='*****@*****.**')
        self.r2.save()
        # Create an Article.
        self.a = Article(id=None,
                         headline="This is a test",
                         pub_date=datetime(2005, 7, 27),
                         reporter=self.r)
        self.a.save()

    def test_get(self):
        # Article objects have access to their related Reporter objects.
        r = self.a.reporter
        self.assertEqual(r.id, self.r.id)
        # These are strings instead of unicode strings because that's what was used in
        # the creation of this reporter (and we haven't refreshed the data from the
        # database, which always returns unicode strings).
        self.assertEqual((r.first_name, self.r.last_name), ('John', 'Smith'))

    def test_create(self):
        # You can also instantiate an Article by passing the Reporter's ID
        # instead of a Reporter object.
        a3 = Article(id=None,
                     headline="Third article",
                     pub_date=datetime(2005, 7, 27),
                     reporter_id=self.r.id)
        a3.save()
        self.assertEqual(a3.reporter.id, self.r.id)

        # Similarly, the reporter ID can be a string.
        a4 = Article(id=None,
                     headline="Fourth article",
                     pub_date=datetime(2005, 7, 27),
                     reporter_id=str(self.r.id))
        a4.save()
        self.assertEqual(repr(a4.reporter), "<Reporter: John Smith>")

    def test_add(self):
        # Create an Article via the Reporter object.
        new_article = self.r.article_set.create(headline="John's second story",
                                                pub_date=datetime(2005, 7, 29))
        self.assertEqual(repr(new_article), "<Article: John's second story>")
        self.assertEqual(new_article.reporter.id, self.r.id)

        # Create a new article, and add it to the article set.
        new_article2 = Article(headline="Paul's story",
                               pub_date=datetime(2006, 1, 17))
        self.r.article_set.add(new_article2)
        self.assertEqual(new_article2.reporter.id, self.r.id)
        self.assertQuerysetEqual(self.r.article_set.all(), [
            "<Article: John's second story>",
            "<Article: Paul's story>",
            "<Article: This is a test>",
        ])

        # Add the same article to a different article set - check that it moves.
        self.r2.article_set.add(new_article2)
        self.assertEqual(new_article2.reporter.id, self.r2.id)
        self.assertQuerysetEqual(self.r2.article_set.all(),
                                 ["<Article: Paul's story>"])

        # Adding an object of the wrong type raises TypeError.
        self.assertRaises(TypeError, self.r.article_set.add, self.r2)
        self.assertQuerysetEqual(self.r.article_set.all(), [
            "<Article: John's second story>",
            "<Article: This is a test>",
        ])

    def test_assign(self):
        new_article = self.r.article_set.create(headline="John's second story",
                                                pub_date=datetime(2005, 7, 29))
        new_article2 = self.r2.article_set.create(headline="Paul's story",
                                                  pub_date=datetime(
                                                      2006, 1, 17))
        # Assign the article to the reporter directly using the descriptor.
        new_article2.reporter = self.r
        new_article2.save()
        self.assertEqual(repr(new_article2.reporter), "<Reporter: John Smith>")
        self.assertEqual(new_article2.reporter.id, self.r.id)
        self.assertQuerysetEqual(self.r.article_set.all(), [
            "<Article: John's second story>",
            "<Article: Paul's story>",
            "<Article: This is a test>",
        ])
        self.assertQuerysetEqual(self.r2.article_set.all(), [])
        # Set the article back again using set descriptor.
        self.r2.article_set = [new_article, new_article2]
        self.assertQuerysetEqual(self.r.article_set.all(),
                                 ["<Article: This is a test>"])
        self.assertQuerysetEqual(self.r2.article_set.all(), [
            "<Article: John's second story>",
            "<Article: Paul's story>",
        ])

        # Funny case - assignment notation can only go so far; because the
        # ForeignKey cannot be null, existing members of the set must remain.
        self.r.article_set = [new_article]
        self.assertQuerysetEqual(self.r.article_set.all(), [
            "<Article: John's second story>",
            "<Article: This is a test>",
        ])
        self.assertQuerysetEqual(self.r2.article_set.all(),
                                 ["<Article: Paul's story>"])
        # Reporter cannot be null - there should not be a clear or remove method
        self.assertFalse(hasattr(self.r2.article_set, 'remove'))
        self.assertFalse(hasattr(self.r2.article_set, 'clear'))

    def test_selects(self):
        new_article = self.r.article_set.create(headline="John's second story",
                                                pub_date=datetime(2005, 7, 29))
        new_article2 = self.r2.article_set.create(headline="Paul's story",
                                                  pub_date=datetime(
                                                      2006, 1, 17))
        # Reporter objects have access to their related Article objects.
        self.assertQuerysetEqual(self.r.article_set.all(), [
            "<Article: John's second story>",
            "<Article: This is a test>",
        ])
        self.assertQuerysetEqual(
            self.r.article_set.filter(headline__startswith='This'),
            ["<Article: This is a test>"])
        self.assertEqual(self.r.article_set.count(), 2)
        self.assertEqual(self.r2.article_set.count(), 1)
        # Get articles by id
        self.assertQuerysetEqual(Article.objects.filter(id__exact=self.a.id),
                                 ["<Article: This is a test>"])
        self.assertQuerysetEqual(Article.objects.filter(pk=self.a.id),
                                 ["<Article: This is a test>"])
        # Query on an article property
        self.assertQuerysetEqual(
            Article.objects.filter(headline__startswith='This'),
            ["<Article: This is a test>"])
        # The API automatically follows relationships as far as you need.
        # Use double underscores to separate relationships.
        # This works as many levels deep as you want. There's no limit.
        # Find all Articles for any Reporter whose first name is "John".
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__first_name__exact='John'), [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        # Check that implied __exact also works
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__first_name='John'), [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        # Query twice over the related field.
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__first_name__exact='John',
                                   reporter__last_name__exact='Smith'), [
                                       "<Article: John's second story>",
                                       "<Article: This is a test>",
                                   ])
        # The underlying query only makes one join when a related table is referenced twice.
        queryset = Article.objects.filter(reporter__first_name__exact='John',
                                          reporter__last_name__exact='Smith')
        self.assertNumQueries(1, list, queryset)
        self.assertEqual(
            queryset.query.get_compiler(
                queryset.db).as_sql()[0].count('INNER JOIN'), 1)

        # The automatically joined table has a predictable name.
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__first_name__exact='John').extra(
                where=["many_to_one_reporter.last_name='Smith'"]), [
                    "<Article: John's second story>",
                    "<Article: This is a test>",
                ])
        # ... and should work fine with the unicode that comes out of forms.Form.cleaned_data
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__first_name__exact='John').extra(
                where=["many_to_one_reporter.last_name='%s'" % u'Smith']), [
                    "<Article: John's second story>",
                    "<Article: This is a test>",
                ])
        # Find all Articles for a Reporter.
        # Use direct ID check, pk check, and object comparison
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__id__exact=self.r.id), [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__pk=self.r.id), [
                "<Article: John's second story>",
                "<Article: This is a test>",
            ])
        self.assertQuerysetEqual(Article.objects.filter(reporter=self.r.id), [
            "<Article: John's second story>",
            "<Article: This is a test>",
        ])
        self.assertQuerysetEqual(Article.objects.filter(reporter=self.r), [
            "<Article: John's second story>",
            "<Article: This is a test>",
        ])
        self.assertQuerysetEqual(
            Article.objects.filter(
                reporter__in=[self.r.id, self.r2.id]).distinct(), [
                    "<Article: John's second story>",
                    "<Article: Paul's story>",
                    "<Article: This is a test>",
                ])
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__in=[self.r, self.r2]).distinct(),
            [
                "<Article: John's second story>",
                "<Article: Paul's story>",
                "<Article: This is a test>",
            ])
        # You can also use a queryset instead of a literal list of instances.
        # The queryset must be reduced to a list of values using values(),
        # then converted into a query
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__in=Reporter.objects.filter(
                first_name='John').values('pk').query).distinct(), [
                    "<Article: John's second story>",
                    "<Article: This is a test>",
                ])

    def test_reverse_selects(self):
        a3 = Article.objects.create(id=None,
                                    headline="Third article",
                                    pub_date=datetime(2005, 7, 27),
                                    reporter_id=self.r.id)
        a4 = Article.objects.create(id=None,
                                    headline="Fourth article",
                                    pub_date=datetime(2005, 7, 27),
                                    reporter_id=str(self.r.id))
        # Reporters can be queried
        self.assertQuerysetEqual(Reporter.objects.filter(id__exact=self.r.id),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(Reporter.objects.filter(pk=self.r.id),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(first_name__startswith='John'),
            ["<Reporter: John Smith>"])
        # Reporters can query in opposite direction of ForeignKey definition
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__id__exact=self.a.id),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__pk=self.a.id),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(Reporter.objects.filter(article=self.a.id),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(Reporter.objects.filter(article=self.a),
                                 ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__in=[self.a.id, a3.id]).distinct(),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__in=[self.a.id, a3]).distinct(),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__in=[self.a, a3]).distinct(),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__headline__startswith='T'),
            ["<Reporter: John Smith>", "<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(
                article__headline__startswith='T').distinct(),
            ["<Reporter: John Smith>"])

        # Counting in the opposite direction works in conjunction with distinct()
        self.assertEqual(
            Reporter.objects.filter(article__headline__startswith='T').count(),
            2)
        self.assertEqual(
            Reporter.objects.filter(
                article__headline__startswith='T').distinct().count(), 1)

        # Queries can go round in circles.
        self.assertQuerysetEqual(
            Reporter.objects.filter(
                article__reporter__first_name__startswith='John'), [
                    "<Reporter: John Smith>",
                    "<Reporter: John Smith>",
                    "<Reporter: John Smith>",
                ])
        self.assertQuerysetEqual(
            Reporter.objects.filter(
                article__reporter__first_name__startswith='John').distinct(),
            ["<Reporter: John Smith>"])
        self.assertQuerysetEqual(
            Reporter.objects.filter(
                article__reporter__exact=self.r).distinct(),
            ["<Reporter: John Smith>"])

        # Check that implied __exact also works.
        self.assertQuerysetEqual(
            Reporter.objects.filter(article__reporter=self.r).distinct(),
            ["<Reporter: John Smith>"])

        # It's possible to use values() calls across many-to-one relations.
        # (Note, too, that we clear the ordering here so as not to drag the
        # 'headline' field into the columns being used to determine uniqueness)
        d = {'reporter__first_name': u'John', 'reporter__last_name': u'Smith'}
        self.assertEqual([d],
                         list(
                             Article.objects.filter(
                                 reporter=self.r).distinct().order_by().values(
                                     'reporter__first_name',
                                     'reporter__last_name')))

    def test_select_related(self):
        # Check that Article.objects.select_related().dates() works properly when
        # there are multiple Articles with the same date but different foreign-key
        # objects (Reporters).
        r1 = Reporter.objects.create(first_name='Mike',
                                     last_name='Royko',
                                     email='*****@*****.**')
        r2 = Reporter.objects.create(first_name='John',
                                     last_name='Kass',
                                     email='*****@*****.**')
        a1 = Article.objects.create(headline='First',
                                    pub_date=datetime(1980, 4, 23),
                                    reporter=r1)
        a2 = Article.objects.create(headline='Second',
                                    pub_date=datetime(1980, 4, 23),
                                    reporter=r2)
        self.assertEqual(
            list(Article.objects.select_related().dates('pub_date', 'day')), [
                datetime(1980, 4, 23, 0, 0),
                datetime(2005, 7, 27, 0, 0),
            ])
        self.assertEqual(
            list(Article.objects.select_related().dates('pub_date', 'month')),
            [
                datetime(1980, 4, 1, 0, 0),
                datetime(2005, 7, 1, 0, 0),
            ])
        self.assertEqual(
            list(Article.objects.select_related().dates('pub_date', 'year')), [
                datetime(1980, 1, 1, 0, 0),
                datetime(2005, 1, 1, 0, 0),
            ])

    def test_delete(self):
        new_article = self.r.article_set.create(headline="John's second story",
                                                pub_date=datetime(2005, 7, 29))
        new_article2 = self.r2.article_set.create(headline="Paul's story",
                                                  pub_date=datetime(
                                                      2006, 1, 17))
        a3 = Article.objects.create(id=None,
                                    headline="Third article",
                                    pub_date=datetime(2005, 7, 27),
                                    reporter_id=self.r.id)
        a4 = Article.objects.create(id=None,
                                    headline="Fourth article",
                                    pub_date=datetime(2005, 7, 27),
                                    reporter_id=str(self.r.id))
        # If you delete a reporter, his articles will be deleted.
        self.assertQuerysetEqual(Article.objects.all(), [
            "<Article: Fourth article>",
            "<Article: John's second story>",
            "<Article: Paul's story>",
            "<Article: Third article>",
            "<Article: This is a test>",
        ])
        self.assertQuerysetEqual(Reporter.objects.order_by('first_name'), [
            "<Reporter: John Smith>",
            "<Reporter: Paul Jones>",
        ])
        self.r2.delete()
        self.assertQuerysetEqual(Article.objects.all(), [
            "<Article: Fourth article>",
            "<Article: John's second story>",
            "<Article: Third article>",
            "<Article: This is a test>",
        ])
        self.assertQuerysetEqual(Reporter.objects.order_by('first_name'),
                                 ["<Reporter: John Smith>"])
        # You can delete using a JOIN in the query.
        Reporter.objects.filter(article__headline__startswith='This').delete()
        self.assertQuerysetEqual(Reporter.objects.all(), [])
        self.assertQuerysetEqual(Article.objects.all(), [])

    def test_regression_12876(self):
        # Regression for #12876 -- Model methods that include queries that
        # recursive don't cause recursion depth problems under deepcopy.
        self.r.cached_query = Article.objects.filter(reporter=self.r)
        self.assertEqual(repr(deepcopy(self.r)), "<Reporter: John Smith>")

    def test_explicit_fk(self):
        # Create a new Article with get_or_create using an explicit value
        # for a ForeignKey.
        a2, created = Article.objects.get_or_create(
            id=None,
            headline="John's second test",
            pub_date=datetime(2011, 5, 7),
            reporter_id=self.r.id)
        self.assertTrue(created)
        self.assertEqual(a2.reporter.id, self.r.id)

        # You can specify filters containing the explicit FK value.
        self.assertQuerysetEqual(
            Article.objects.filter(reporter_id__exact=self.r.id), [
                "<Article: John's second test>",
                "<Article: This is a test>",
            ])

        # Create an Article by Paul for the same date.
        a3 = Article.objects.create(id=None,
                                    headline="Paul's commentary",
                                    pub_date=datetime(2011, 5, 7),
                                    reporter_id=self.r2.id)
        self.assertEqual(a3.reporter.id, self.r2.id)

        # Get should respect explicit foreign keys as well.
        self.assertRaises(MultipleObjectsReturned,
                          Article.objects.get,
                          reporter_id=self.r.id)
        self.assertEqual(
            repr(a3),
            repr(
                Article.objects.get(reporter_id=self.r2.id,
                                    pub_date=datetime(2011, 5, 7))))
Exemple #15
0
class ManyToOneNullTests(TestCase):
    def setUp(self):
        # Create a Reporter.
        self.r = Reporter(name="John Smith")
        self.r.save()
        # Create an Article.
        self.a = Article(headline="First", reporter=self.r)
        self.a.save()
        # Create an Article via the Reporter object.
        self.a2 = self.r.article_set.create(headline="Second")
        # Create an Article with no Reporter by passing "reporter=None".
        self.a3 = Article(headline="Third", reporter=None)
        self.a3.save()
        # Create another article and reporter
        self.r2 = Reporter(name="Paul Jones")
        self.r2.save()
        self.a4 = self.r2.article_set.create(headline="Fourth")

    def test_get_related(self):
        self.assertEqual(self.a.reporter.id, self.r.id)
        # Article objects have access to their related Reporter objects.
        r = self.a.reporter
        self.assertEqual(r.id, self.r.id)

    def test_created_via_related_set(self):
        self.assertEqual(self.a2.reporter.id, self.r.id)

    def test_related_set(self):
        # Reporter objects have access to their related Article objects.
        self.assertQuerysetEqual(self.r.article_set.all(), ["<Article: First>", "<Article: Second>"])
        self.assertQuerysetEqual(self.r.article_set.filter(headline__startswith="Fir"), ["<Article: First>"])
        self.assertEqual(self.r.article_set.count(), 2)

    def test_created_without_related(self):
        self.assertEqual(self.a3.reporter, None)
        # Need to reget a3 to refresh the cache
        a3 = Article.objects.get(pk=self.a3.pk)
        self.assertRaises(AttributeError, getattr, a3.reporter, "id")
        # Accessing an article's 'reporter' attribute returns None
        # if the reporter is set to None.
        self.assertEqual(a3.reporter, None)
        # To retrieve the articles with no reporters set, use "reporter__isnull=True".
        self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True), ["<Article: Third>"])
        # We can achieve the same thing by filtering for the case where the
        # reporter is None.
        self.assertQuerysetEqual(Article.objects.filter(reporter=None), ["<Article: Third>"])
        # Set the reporter for the Third article
        self.assertQuerysetEqual(self.r.article_set.all(), ["<Article: First>", "<Article: Second>"])
        self.r.article_set.add(a3)
        self.assertQuerysetEqual(
            self.r.article_set.all(), ["<Article: First>", "<Article: Second>", "<Article: Third>"]
        )
        # Remove an article from the set, and check that it was removed.
        self.r.article_set.remove(a3)
        self.assertQuerysetEqual(self.r.article_set.all(), ["<Article: First>", "<Article: Second>"])
        self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True), ["<Article: Third>"])

    def test_remove_from_wrong_set(self):
        self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Fourth>"])
        # Try to remove a4 from a set it does not belong to
        self.assertRaises(Reporter.DoesNotExist, self.r.article_set.remove, self.a4)
        self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Fourth>"])

    def test_assign_clear_related_set(self):
        # Use descriptor assignment to allocate ForeignKey. Null is legal, so
        # existing members of set that are not in the assignment set are set null
        self.r2.article_set = [self.a2, self.a3]
        self.assertQuerysetEqual(self.r2.article_set.all(), ["<Article: Second>", "<Article: Third>"])
        # Clear the rest of the set
        self.r.article_set.clear()
        self.assertQuerysetEqual(self.r.article_set.all(), [])
        self.assertQuerysetEqual(
            Article.objects.filter(reporter__isnull=True), ["<Article: First>", "<Article: Fourth>"]
        )