Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for generic foreign key and generic relation #6

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d26ebb9
Update GenericForeignKey object_id to CharField
timgraham Jul 17, 2024
eb2edbd
use ObjectIdAutoField in test models
timgraham Jul 17, 2024
1ca24f8
update serializer output for MongoAutoField
timgraham Jul 18, 2024
acc5a8a
comment out usage of QuerySet.extra() and distinct()
timgraham Jul 18, 2024
eb87707
remove unsupported usage of nulls_first
timgraham Jul 22, 2024
a87e9ff
aggregation_regress edits
timgraham Aug 19, 2024
44d8244
add test for ModelForm data using numeric pks
timgraham Aug 16, 2024
100a379
drop requirement that QuerySet.explain() log a query
timgraham Aug 16, 2024
3dd7485
schema and migrations test edits
timgraham Aug 24, 2024
3211b6c
backends edits
timgraham Aug 29, 2024
971a089
introspection test edits
timgraham Aug 27, 2024
73f6eeb
Added supports_sequence_reset skip in backends tests.
timgraham Aug 23, 2024
e486811
remove SQL introspection from queries test
timgraham Sep 3, 2024
ab7e2e4
Added QuerySet.union() test with renames.
WaVEV Sep 7, 2024
f5fd65f
schema and migrations test edits
timgraham Aug 24, 2024
2062d1b
backends edits
timgraham Aug 29, 2024
be9bb06
introspection test edits
timgraham Aug 27, 2024
831a01e
Added supports_sequence_reset skip in backends tests.
timgraham Aug 23, 2024
4f60fb2
remove SQL introspection from queries test
timgraham Sep 3, 2024
9e61019
Added QuerySet.union() test with renames.
WaVEV Sep 7, 2024
a586021
prevent basic test from requiring DatabaseFeatures.supports_expressio…
timgraham Sep 16, 2024
de48a57
Merge branch 'mongodb-forks:mongodb-5.0.x' into mongodb-5.0.x
WaVEV Sep 17, 2024
640aef4
Edit test models, uses ObjectId instead of positiveIntegerField.
WaVEV Sep 17, 2024
8bf77cd
Using textfield instead of ObjectIdField.
WaVEV Sep 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion django/contrib/sites/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from django_mongodb.fields import ObjectIdAutoField

import django.contrib.sites.models
from django.contrib.sites.models import _simple_domain_name_validator
from django.db import migrations, models
Expand All @@ -12,7 +14,7 @@ class Migration(migrations.Migration):
fields=[
(
"id",
models.AutoField(
ObjectIdAutoField(
verbose_name="ID",
serialize=False,
auto_created=True,
Expand Down
10 changes: 6 additions & 4 deletions tests/aggregation_regress/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from django_mongodb.fields import ObjectIdAutoField

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models
Expand All @@ -17,7 +19,7 @@ class Publisher(models.Model):
class ItemTag(models.Model):
tag = models.CharField(max_length=100)
content_type = models.ForeignKey(ContentType, models.CASCADE)
object_id = models.PositiveIntegerField()
object_id = models.CharField(max_length=24)
content_object = GenericForeignKey("content_type", "object_id")


Expand Down Expand Up @@ -45,13 +47,13 @@ class Store(models.Model):


class Entries(models.Model):
EntryID = models.AutoField(primary_key=True, db_column="Entry ID")
EntryID = ObjectIdAutoField(primary_key=True, db_column="Entry ID")
Entry = models.CharField(unique=True, max_length=50)
Exclude = models.BooleanField(default=False)


class Clues(models.Model):
ID = models.AutoField(primary_key=True)
ID = ObjectIdAutoField(primary_key=True)
EntryID = models.ForeignKey(
Entries, models.CASCADE, verbose_name="Entry", db_column="Entry ID"
)
Expand All @@ -63,7 +65,7 @@ class WithManualPK(models.Model):
# classes with the same PK value, and there are some (external)
# DB backends that don't work nicely when assigning integer to AutoField
# column (MSSQL at least).
id = models.IntegerField(primary_key=True)
id = ObjectIdAutoField(primary_key=True)


class HardbackBook(Book):
Expand Down
21 changes: 15 additions & 6 deletions tests/aggregation_regress/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import FieldError
from django.db import connection
from django.db.models import (
Aggregate,
Avg,
Expand Down Expand Up @@ -184,7 +183,7 @@ def test_annotation_with_value(self):
)
.annotate(sum_discount=Sum("discount_price"))
)
with self.assertNumQueries(1) as ctx:
with self.assertNumQueries(1):
self.assertSequenceEqual(
values,
[
Expand All @@ -194,8 +193,8 @@ def test_annotation_with_value(self):
}
],
)
if connection.features.allows_group_by_select_index:
self.assertIn("GROUP BY 1", ctx[0]["sql"])
# if connection.features.allows_group_by_select_index:
# self.assertIn("GROUP BY 1", ctx[0]["sql"])

def test_aggregates_in_where_clause(self):
"""
Expand Down Expand Up @@ -829,7 +828,7 @@ def test_empty(self):
],
)

def test_more_more(self):
def test_more_more1(self):
# Regression for #10113 - Fields mentioned in order_by() must be
# included in the GROUP BY. This only becomes a problem when the
# order_by introduces a new join.
Expand All @@ -849,6 +848,7 @@ def test_more_more(self):
lambda b: b.name,
)

def test_more_more2(self):
# Regression for #10127 - Empty select_related() works with annotate
qs = (
Book.objects.filter(rating__lt=4.5)
Expand Down Expand Up @@ -877,6 +877,7 @@ def test_more_more(self):
lambda b: (b.name, b.authors__age__avg, b.publisher.name, b.contact.name),
)

def test_more_more3(self):
# Regression for #10132 - If the values() clause only mentioned extra
# (select=) columns, those columns are used for grouping
qs = (
Expand Down Expand Up @@ -911,6 +912,7 @@ def test_more_more(self):
],
)

def test_more_more4(self):
# Regression for #10182 - Queries with aggregate calls are correctly
# realiased when used in a subquery
ids = (
Expand All @@ -927,6 +929,7 @@ def test_more_more(self):
lambda b: b.name,
)

def test_more_more5(self):
# Regression for #15709 - Ensure each group_by field only exists once
# per query
qstr = str(
Expand Down Expand Up @@ -1023,7 +1026,7 @@ def test_pickle(self):
query,
)

def test_more_more_more(self):
def test_more_more_more1(self):
# Regression for #10199 - Aggregate calls clone the original query so
# the original query can still be used
books = Book.objects.all()
Expand All @@ -1042,6 +1045,7 @@ def test_more_more_more(self):
lambda b: b.name,
)

def test_more_more_more2(self):
# Regression for #10248 - Annotations work with dates()
qs = (
Book.objects.annotate(num_authors=Count("authors"))
Expand All @@ -1056,6 +1060,7 @@ def test_more_more_more(self):
],
)

def test_more_more_more3(self):
# Regression for #10290 - extra selects with parameters can be used for
# grouping.
qs = (
Expand All @@ -1068,6 +1073,7 @@ def test_more_more_more(self):
qs, [150, 175, 224, 264, 473, 566], lambda b: int(b["sheets"])
)

def test_more_more_more4(self):
# Regression for 10425 - annotations don't get in the way of a count()
# clause
self.assertEqual(
Expand All @@ -1077,6 +1083,7 @@ def test_more_more_more(self):
Book.objects.annotate(Count("publisher")).values("publisher").count(), 6
)

def test_more_more_more5(self):
# Note: intentionally no order_by(), that case needs tests, too.
publishers = Publisher.objects.filter(id__in=[self.p1.id, self.p2.id])
self.assertEqual(sorted(p.name for p in publishers), ["Apress", "Sams"])
Expand All @@ -1100,6 +1107,7 @@ def test_more_more_more(self):
)
self.assertEqual(sorted(p.name for p in publishers), ["Apress", "Sams"])

def test_more_more_more6(self):
# Regression for 10666 - inherited fields work with annotations and
# aggregations
self.assertEqual(
Expand Down Expand Up @@ -1152,6 +1160,7 @@ def test_more_more_more(self):
],
)

def test_more_more_more7(self):
# Regression for #10766 - Shouldn't be able to reference an aggregate
# fields in an aggregate() call.
msg = "Cannot compute Avg('mean_age'): 'mean_age' is an aggregate"
Expand Down
6 changes: 4 additions & 2 deletions tests/backends/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from django_mongodb.fields import ObjectIdAutoField

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models
Expand Down Expand Up @@ -47,7 +49,7 @@ class Meta:


class VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ(models.Model):
primary_key_is_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.AutoField(
primary_key_is_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = ObjectIdAutoField(
primary_key=True
)
charfield_is_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.CharField(
Expand Down Expand Up @@ -165,7 +167,7 @@ class Book(models.Model):


class SQLKeywordsModel(models.Model):
id = models.AutoField(primary_key=True, db_column="select")
id = ObjectIdAutoField(primary_key=True, db_column="select")
reporter = models.ForeignKey(Reporter, models.CASCADE, db_column="where")

class Meta:
Expand Down
9 changes: 4 additions & 5 deletions tests/backends/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def test_last_executed_query_without_previous_query(self):
def test_debug_sql(self):
list(Reporter.objects.filter(first_name="test"))
sql = connection.queries[-1]["sql"].lower()
self.assertIn("select", sql)
self.assertIn("$match", sql)
self.assertIn(Reporter._meta.db_table, sql)

def test_query_encoding(self):
Expand Down Expand Up @@ -225,6 +225,7 @@ def test_sequence_name_length_limits_flush(self):
connection.ops.execute_sql_flush(sql_list)


@skipUnlessDBFeature("supports_sequence_reset")
class SequenceResetTest(TestCase):
def test_generic_relation(self):
"Sequence names are correct when resetting generic relations (Ref #13941)"
Expand Down Expand Up @@ -261,14 +262,12 @@ def receiver(sender, connection, **kwargs):

connection_created.connect(receiver)
connection.close()
with connection.cursor():
pass
connection.connection
self.assertIs(data["connection"].connection, connection.connection)

connection_created.disconnect(receiver)
data.clear()
with connection.cursor():
pass
connection.connection
self.assertEqual(data, {})


Expand Down
2 changes: 1 addition & 1 deletion tests/basic/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class PrimaryKeyWithDefault(models.Model):


class PrimaryKeyWithDbDefault(models.Model):
uuid = models.IntegerField(primary_key=True, db_default=1)
uuid = models.IntegerField(primary_key=True, db_default=models.Value(1))


class ChildPrimaryKeyWithDefault(PrimaryKeyWithDefault):
Expand Down
6 changes: 3 additions & 3 deletions tests/delete/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,21 +219,21 @@ class DeleteBottom(models.Model):

class GenericB1(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
object_id = models.CharField(max_length=24)
generic_delete_top = GenericForeignKey("content_type", "object_id")


class GenericB2(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
object_id = models.CharField(max_length=24)
generic_delete_top = GenericForeignKey("content_type", "object_id")
generic_delete_bottom = GenericRelation("GenericDeleteBottom")


class GenericDeleteBottom(models.Model):
generic_b1 = models.ForeignKey(GenericB1, models.RESTRICT)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
object_id = models.CharField(max_length=24)
generic_b2 = GenericForeignKey()


Expand Down
2 changes: 1 addition & 1 deletion tests/delete_regress/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

class Award(models.Model):
name = models.CharField(max_length=25)
object_id = models.PositiveIntegerField()
object_id = models.CharField(max_length=24)
content_type = models.ForeignKey(ContentType, models.CASCADE)
content_object = GenericForeignKey()

Expand Down
12 changes: 6 additions & 6 deletions tests/generic_relations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class TaggedItem(models.Model):

tag = models.SlugField()
content_type = models.ForeignKey(ContentType, models.CASCADE)
object_id = models.PositiveIntegerField()
object_id = models.TextField()

content_object = GenericForeignKey()

Expand All @@ -40,7 +40,7 @@ class AbstractComparison(models.Model):
content_type1 = models.ForeignKey(
ContentType, models.CASCADE, related_name="comparative1_set"
)
object_id1 = models.PositiveIntegerField()
object_id1 = models.TextField()

first_obj = GenericForeignKey(ct_field="content_type1", fk_field="object_id1")

Expand All @@ -54,7 +54,7 @@ class Comparison(AbstractComparison):
content_type2 = models.ForeignKey(
ContentType, models.CASCADE, related_name="comparative2_set"
)
object_id2 = models.PositiveIntegerField()
object_id2 = models.TextField()

other_obj = GenericForeignKey(ct_field="content_type2", fk_field="object_id2")

Expand Down Expand Up @@ -119,20 +119,20 @@ class ValuableRock(Mineral):


class ManualPK(models.Model):
id = models.IntegerField(primary_key=True)
id = models.TextField(primary_key=True)
tags = GenericRelation(TaggedItem, related_query_name="manualpk")


class ForProxyModelModel(models.Model):
content_type = models.ForeignKey(ContentType, models.CASCADE)
object_id = models.PositiveIntegerField()
object_id = models.TextField()
obj = GenericForeignKey(for_concrete_model=False)
title = models.CharField(max_length=255, null=True)


class ForConcreteModelModel(models.Model):
content_type = models.ForeignKey(ContentType, models.CASCADE)
object_id = models.PositiveIntegerField()
object_id = models.TextField()
obj = GenericForeignKey()


Expand Down
3 changes: 2 additions & 1 deletion tests/generic_relations/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from bson import ObjectId

Check failure on line 1 in tests/generic_relations/tests.py

View workflow job for this annotation

GitHub Actions / isort

Imports are incorrectly sorted and/or formatted.
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.prefetch import GenericPrefetch
from django.core.exceptions import FieldError
Expand Down Expand Up @@ -44,7 +45,7 @@

def comp_func(self, obj):
# Original list of tags:
return obj.tag, obj.content_type.model_class(), obj.object_id
return obj.tag, obj.content_type.model_class(), ObjectId(obj.object_id)

async def test_generic_async_acreate(self):
await self.bacon.tags.acreate(tag="orange")
Expand Down
17 changes: 8 additions & 9 deletions tests/introspection/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,14 @@ def test_table_names(self):
)

def test_django_table_names(self):
with connection.cursor() as cursor:
cursor.execute("CREATE TABLE django_ixn_test_table (id INTEGER);")
tl = connection.introspection.django_table_names()
cursor.execute("DROP TABLE django_ixn_test_table;")
self.assertNotIn(
"django_ixn_test_table",
tl,
"django_table_names() returned a non-Django table",
)
connection.database.create_collection("django_ixn_test_table")
tl = connection.introspection.django_table_names()
connection.database["django_ixn_test_table"].drop()
self.assertNotIn(
"django_ixn_test_table",
tl,
"django_table_names() returned a non-Django table",
)

def test_django_table_names_retval_type(self):
# Table name is a list #15216
Expand Down
8 changes: 4 additions & 4 deletions tests/m2m_through_regress/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ def test_serialization(self):
)
self.assertJSONEqual(
out.getvalue().strip(),
'[{"pk": %(m_pk)s, "model": "m2m_through_regress.membership", '
'"fields": {"person": %(p_pk)s, "price": 100, "group": %(g_pk)s}}, '
'{"pk": %(p_pk)s, "model": "m2m_through_regress.person", '
'[{"pk": "%(m_pk)s", "model": "m2m_through_regress.membership", '
'"fields": {"person": "%(p_pk)s", "price": 100, "group": "%(g_pk)s"}}, '
'{"pk": "%(p_pk)s", "model": "m2m_through_regress.person", '
'"fields": {"name": "Bob"}}, '
'{"pk": %(g_pk)s, "model": "m2m_through_regress.group", '
'{"pk": "%(g_pk)s", "model": "m2m_through_regress.group", '
'"fields": {"name": "Roll"}}]' % pks,
)

Expand Down
Loading
Loading