add filterset test to drf integration tests

This commit is contained in:
Brian Kohan 2026-01-13 12:31:55 -08:00
parent e7c1ae37e4
commit f2e65fc842
No known key found for this signature in database
GPG Key ID: 5C6CE8BA38C43FC1
15 changed files with 1405 additions and 1087 deletions

View File

@ -197,6 +197,7 @@ extra-views = [
"django-extra-views>=0.16.0",
]
drf = [
"django-filter>=24.0",
"djangorestframework>=3.16.1",
]
guardian = [

View File

@ -1,10 +1,10 @@
# Generated by Django 4.2 on 2026-01-13 11:18
# Generated by Django 5.2 on 2026-01-13 13:59
import django.db.models.deletion
import polymorphic.tests.deletion.models
from decimal import Decimal
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import polymorphic.tests.deletion.models
class Migration(migrations.Migration):
@ -12,11 +12,51 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Poly1',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Poly2',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Poly4',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Poly4_1',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='A_160',
fields=[
@ -55,6 +95,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
@ -102,6 +143,18 @@ class Migration(migrations.Migration):
('lastname', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Payment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('amount', models.DecimalField(blank=True, decimal_places=2, default=Decimal('0'), max_digits=10)),
('index', models.PositiveIntegerField(default=0)),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'ordering': ('index',),
},
),
migrations.CreateModel(
name='CustomModel',
fields=[
@ -148,19 +201,6 @@ class Migration(migrations.Migration):
'ordering': ('title',),
},
),
migrations.CreateModel(
name='Payment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('amount', models.DecimalField(blank=True, decimal_places=2, default=Decimal('0'), max_digits=10)),
('index', models.PositiveIntegerField(default=0)),
('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.order')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'ordering': ('index',),
},
),
migrations.CreateModel(
name='PlainA',
fields=[
@ -173,48 +213,6 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
),
migrations.CreateModel(
name='Poly1',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Poly2',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('normal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='polies', to='deletion.normal2')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Poly4',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('normals', models.ManyToManyField(blank=True, related_name='polies', to='deletion.normal4')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Poly4_1',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='PolyDevice',
fields=[
@ -251,6 +249,26 @@ class Migration(migrations.Migration):
},
bases=('deletion.poly1',),
),
migrations.CreateModel(
name='B1',
fields=[
('poly1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly1')),
],
options={
'abstract': False,
},
bases=('deletion.poly1',),
),
migrations.CreateModel(
name='C1',
fields=[
('poly1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly1')),
],
options={
'abstract': False,
},
bases=('deletion.poly1',),
),
migrations.CreateModel(
name='A2',
fields=[
@ -261,6 +279,26 @@ class Migration(migrations.Migration):
},
bases=('deletion.poly2',),
),
migrations.CreateModel(
name='B2',
fields=[
('poly2_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly2')),
],
options={
'abstract': False,
},
bases=('deletion.poly2',),
),
migrations.CreateModel(
name='C2',
fields=[
('poly2_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly2')),
],
options={
'abstract': False,
},
bases=('deletion.poly2',),
),
migrations.CreateModel(
name='A4',
fields=[
@ -271,70 +309,6 @@ class Migration(migrations.Migration):
},
bases=('deletion.poly4',),
),
migrations.CreateModel(
name='A4_1',
fields=[
('poly4_1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly4_1')),
],
options={
'abstract': False,
},
bases=('deletion.poly4_1',),
),
migrations.CreateModel(
name='B1',
fields=[
('poly1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly1')),
],
options={
'abstract': False,
},
bases=('deletion.poly1',),
),
migrations.CreateModel(
name='B1_160',
fields=[
('b_160_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_160')),
],
options={
'abstract': False,
},
bases=('deletion.b_160',),
),
migrations.CreateModel(
name='B1_160Plain',
fields=[
('b_160plain_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_160plain')),
],
bases=('deletion.b_160plain',),
),
migrations.CreateModel(
name='B2',
fields=[
('poly2_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly2')),
],
options={
'abstract': False,
},
bases=('deletion.poly2',),
),
migrations.CreateModel(
name='B2_160',
fields=[
('b_160_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_160')),
],
options={
'abstract': False,
},
bases=('deletion.b_160',),
),
migrations.CreateModel(
name='B2_160Plain',
fields=[
('b_160plain_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_160plain')),
],
bases=('deletion.b_160plain',),
),
migrations.CreateModel(
name='B4',
fields=[
@ -345,6 +319,26 @@ class Migration(migrations.Migration):
},
bases=('deletion.poly4',),
),
migrations.CreateModel(
name='C4',
fields=[
('poly4_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly4')),
],
options={
'abstract': False,
},
bases=('deletion.poly4',),
),
migrations.CreateModel(
name='A4_1',
fields=[
('poly4_1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly4_1')),
],
options={
'abstract': False,
},
bases=('deletion.poly4_1',),
),
migrations.CreateModel(
name='B4_1',
fields=[
@ -355,6 +349,16 @@ class Migration(migrations.Migration):
},
bases=('deletion.poly4_1',),
),
migrations.CreateModel(
name='C4_1',
fields=[
('poly4_1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly4_1')),
],
options={
'abstract': False,
},
bases=('deletion.poly4_1',),
),
migrations.CreateModel(
name='B_274',
fields=[
@ -365,6 +369,16 @@ class Migration(migrations.Migration):
},
bases=('deletion.a_274',),
),
migrations.CreateModel(
name='D_274',
fields=[
('a_274_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.a_274')),
],
options={
'abstract': False,
},
bases=('deletion.a_274',),
),
migrations.CreateModel(
name='B_540',
fields=[
@ -376,46 +390,6 @@ class Migration(migrations.Migration):
},
bases=('deletion.a_540',),
),
migrations.CreateModel(
name='C1',
fields=[
('poly1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly1')),
],
options={
'abstract': False,
},
bases=('deletion.poly1',),
),
migrations.CreateModel(
name='C2',
fields=[
('poly2_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly2')),
],
options={
'abstract': False,
},
bases=('deletion.poly2',),
),
migrations.CreateModel(
name='C4',
fields=[
('poly4_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly4')),
],
options={
'abstract': False,
},
bases=('deletion.poly4',),
),
migrations.CreateModel(
name='C4_1',
fields=[
('poly4_1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly4_1')),
],
options={
'abstract': False,
},
bases=('deletion.poly4_1',),
),
migrations.CreateModel(
name='Cat',
fields=[
@ -427,6 +401,73 @@ class Migration(migrations.Migration):
},
bases=('deletion.animal',),
),
migrations.CreateModel(
name='Dog',
fields=[
('animal_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.animal')),
('dog_param', models.CharField(max_length=100)),
],
options={
'abstract': False,
},
bases=('deletion.animal',),
),
migrations.CreateModel(
name='TextAnswer',
fields=[
('answer_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.answer')),
('answer', models.CharField(blank=True, default='', max_length=500)),
],
options={
'abstract': False,
},
bases=('deletion.answer',),
),
migrations.CreateModel(
name='YesNoAnswer',
fields=[
('answer_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.answer')),
('answer', models.BooleanField(default=False, verbose_name='answer')),
],
options={
'abstract': False,
},
bases=('deletion.answer',),
),
migrations.CreateModel(
name='B1_160',
fields=[
('b_160_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_160')),
],
options={
'abstract': False,
},
bases=('deletion.b_160',),
),
migrations.CreateModel(
name='B2_160',
fields=[
('b_160_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_160')),
],
options={
'abstract': False,
},
bases=('deletion.b_160',),
),
migrations.CreateModel(
name='B1_160Plain',
fields=[
('b_160plain_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_160plain')),
],
bases=('deletion.b_160plain',),
),
migrations.CreateModel(
name='B2_160Plain',
fields=[
('b_160plain_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_160plain')),
],
bases=('deletion.b_160plain',),
),
migrations.CreateModel(
name='Child',
fields=[
@ -445,16 +486,6 @@ class Migration(migrations.Migration):
},
bases=('deletion.payment',),
),
migrations.CreateModel(
name='D_274',
fields=[
('a_274_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.a_274')),
],
options={
'abstract': False,
},
bases=('deletion.a_274',),
),
migrations.CreateModel(
name='DatasetFolder',
fields=[
@ -462,17 +493,6 @@ class Migration(migrations.Migration):
],
bases=('deletion.custommodel',),
),
migrations.CreateModel(
name='Dog',
fields=[
('animal_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.animal')),
('dog_param', models.CharField(max_length=100)),
],
options={
'abstract': False,
},
bases=('deletion.animal',),
),
migrations.CreateModel(
name='OriginalFile',
fields=[
@ -489,13 +509,22 @@ class Migration(migrations.Migration):
},
bases=('deletion.custommodel', models.Model),
),
migrations.AddField(
model_name='animal',
name='farm',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='animals', to='deletion.farm'),
),
migrations.CreateModel(
name='PlainB1',
name='Normal1',
fields=[
('plaina_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.plaina')),
('standalones', models.ManyToManyField(to='deletion.standalone')),
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('poly', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.poly1')),
],
bases=('deletion.plaina',),
),
migrations.AddField(
model_name='poly2',
name='normal',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='polies', to='deletion.normal2'),
),
migrations.CreateModel(
name='Poly3',
@ -508,6 +537,18 @@ class Migration(migrations.Migration):
},
bases=('deletion.normal3', models.Model),
),
migrations.AddField(
model_name='poly4',
name='normals',
field=models.ManyToManyField(blank=True, related_name='polies', to='deletion.normal4'),
),
migrations.CreateModel(
name='Normal4_1',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('polies', models.ManyToManyField(blank=True, related_name='normals', to='deletion.poly4_1')),
],
),
migrations.CreateModel(
name='Poly5',
fields=[
@ -520,6 +561,19 @@ class Migration(migrations.Migration):
},
bases=('deletion.normal5', models.Model),
),
migrations.AddField(
model_name='payment',
name='order',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.order'),
),
migrations.CreateModel(
name='PlainB1',
fields=[
('plaina_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.plaina')),
('standalones', models.ManyToManyField(to='deletion.standalone')),
],
bases=('deletion.plaina',),
),
migrations.CreateModel(
name='PolyEthernetInterface',
fields=[
@ -553,28 +607,6 @@ class Migration(migrations.Migration):
},
bases=('deletion.polyinterface',),
),
migrations.CreateModel(
name='TextAnswer',
fields=[
('answer_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.answer')),
('answer', models.CharField(blank=True, default='', max_length=500)),
],
options={
'abstract': False,
},
bases=('deletion.answer',),
),
migrations.CreateModel(
name='YesNoAnswer',
fields=[
('answer_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.answer')),
('answer', models.BooleanField(default=False, verbose_name='answer')),
],
options={
'abstract': False,
},
bases=('deletion.answer',),
),
migrations.CreateModel(
name='Question',
fields=[
@ -582,39 +614,115 @@ class Migration(migrations.Migration):
('poll', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.poll')),
],
),
migrations.AddField(
model_name='plaina',
name='standalone_parent',
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='plainas', to='deletion.standalone'),
),
migrations.CreateModel(
name='Normal4_1',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('polies', models.ManyToManyField(blank=True, related_name='normals', to='deletion.poly4_1')),
],
),
migrations.CreateModel(
name='Normal1',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('poly', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.poly1')),
],
),
migrations.AddField(
model_name='answer',
name='question',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.question'),
),
migrations.AddField(
model_name='animal',
name='farm',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='animals', to='deletion.farm'),
model_name='plaina',
name='standalone_parent',
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='plainas', to='deletion.standalone'),
),
migrations.CreateModel(
name='C_274',
fields=[
('b_274_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_274')),
],
options={
'abstract': False,
},
bases=('deletion.b_274',),
),
migrations.CreateModel(
name='E_274',
fields=[
('d_274_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.d_274')),
],
options={
'abstract': False,
},
bases=('deletion.d_274',),
),
migrations.CreateModel(
name='C_160',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('b', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.b1_160')),
],
),
migrations.CreateModel(
name='C_160Plain',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('b', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.b1_160plain')),
],
),
migrations.CreateModel(
name='GrandChild',
fields=[
('child_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.child')),
],
bases=('deletion.child',),
),
migrations.CreateModel(
name='RelatedToChild',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('child', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='relatives', to='deletion.child')),
],
),
migrations.CreateModel(
name='SepaPayment',
fields=[
('payment_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.payment')),
('iban', models.CharField(max_length=34)),
('bic', models.CharField(max_length=11)),
('beneficiaries', models.ManyToManyField(blank=True, related_name='sepa', to='deletion.beneficiary')),
],
options={
'abstract': False,
},
bases=('deletion.payment',),
),
migrations.CreateModel(
name='DatasetRelation',
fields=[
('originalfile_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.originalfile')),
('file', models.FileField(max_length=500, upload_to=polymorphic.tests.deletion.models.project_directory_path)),
('original_file_name', models.CharField(max_length=100)),
],
options={
'abstract': False,
},
bases=('deletion.originalfile',),
),
migrations.CreateModel(
name='OriginalImage',
fields=[
('originalfile_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.originalfile')),
('original_file_name', models.CharField(max_length=100)),
('file', models.FileField(max_length=500, upload_to=polymorphic.tests.deletion.models.project_directory_path)),
],
options={
'abstract': False,
},
bases=('deletion.originalfile',),
),
migrations.CreateModel(
name='Project',
fields=[
('custommodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.custommodel')),
('name', models.CharField(max_length=30)),
('created_at', models.DateTimeField(auto_now_add=True)),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
bases=('deletion.custommodel',),
),
migrations.AddField(
model_name='animal',
name='polymorphic_ctype',
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype'),
model_name='datasetfolder',
name='prjct',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.project'),
),
migrations.CreateModel(
name='A3',
@ -626,6 +734,16 @@ class Migration(migrations.Migration):
},
bases=('deletion.poly3',),
),
migrations.CreateModel(
name='B3',
fields=[
('poly3_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly3')),
],
options={
'abstract': False,
},
bases=('deletion.poly3',),
),
migrations.CreateModel(
name='A5',
fields=[
@ -637,16 +755,6 @@ class Migration(migrations.Migration):
},
bases=('deletion.poly5',),
),
migrations.CreateModel(
name='B3',
fields=[
('poly3_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.poly3')),
],
options={
'abstract': False,
},
bases=('deletion.poly3',),
),
migrations.CreateModel(
name='B5',
fields=[
@ -659,55 +767,12 @@ class Migration(migrations.Migration):
bases=('deletion.poly5',),
),
migrations.CreateModel(
name='C_274',
name='PlainB2',
fields=[
('b_274_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.b_274')),
('plaina_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.plaina')),
('standalone', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='plainb2s', to='deletion.standalone')),
],
options={
'abstract': False,
},
bases=('deletion.b_274',),
),
migrations.CreateModel(
name='DatasetRelation',
fields=[
('originalfile_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.originalfile')),
('file', models.FileField(max_length=500, upload_to=polymorphic.tests.deletion.models.project_directory_path)),
('original_file_name', models.CharField(max_length=100)),
],
options={
'abstract': False,
},
bases=('deletion.originalfile',),
),
migrations.CreateModel(
name='E_274',
fields=[
('d_274_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.d_274')),
],
options={
'abstract': False,
},
bases=('deletion.d_274',),
),
migrations.CreateModel(
name='GrandChild',
fields=[
('child_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.child')),
],
bases=('deletion.child',),
),
migrations.CreateModel(
name='OriginalImage',
fields=[
('originalfile_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.originalfile')),
('original_file_name', models.CharField(max_length=100)),
('file', models.FileField(max_length=500, upload_to=polymorphic.tests.deletion.models.project_directory_path)),
],
options={
'abstract': False,
},
bases=('deletion.originalfile',),
bases=('deletion.plaina',),
),
migrations.CreateModel(
name='PolyFixedInterface',
@ -731,63 +796,6 @@ class Migration(migrations.Migration):
},
bases=('deletion.polyethernetinterface',),
),
migrations.CreateModel(
name='SepaPayment',
fields=[
('payment_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.payment')),
('iban', models.CharField(max_length=34)),
('bic', models.CharField(max_length=11)),
('beneficiaries', models.ManyToManyField(blank=True, related_name='sepa', to='deletion.beneficiary')),
],
options={
'abstract': False,
},
bases=('deletion.payment',),
),
migrations.CreateModel(
name='RelatedToChild',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('child', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='relatives', to='deletion.child')),
],
),
migrations.CreateModel(
name='Project',
fields=[
('custommodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.custommodel')),
('name', models.CharField(max_length=30)),
('created_at', models.DateTimeField(auto_now_add=True)),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
bases=('deletion.custommodel',),
),
migrations.CreateModel(
name='PlainB2',
fields=[
('plaina_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.plaina')),
('standalone', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='plainb2s', to='deletion.standalone')),
],
bases=('deletion.plaina',),
),
migrations.AddField(
model_name='datasetfolder',
name='prjct',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.project'),
),
migrations.CreateModel(
name='C_160Plain',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('b', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.b1_160plain')),
],
),
migrations.CreateModel(
name='C_160',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('b', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='deletion.b1_160')),
],
),
migrations.CreateModel(
name='RelatedToGrandChild',
fields=[
@ -795,14 +803,6 @@ class Migration(migrations.Migration):
('grand_child', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='grand_relatives', to='deletion.grandchild')),
],
),
migrations.CreateModel(
name='PlainC1',
fields=[
('plainb1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.plainb1')),
('standalone', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='plainc1s', to='deletion.standalone')),
],
bases=('deletion.plainb1',),
),
migrations.CreateModel(
name='OriginalDataset',
fields=[
@ -819,4 +819,12 @@ class Migration(migrations.Migration):
},
bases=('deletion.originalfile',),
),
migrations.CreateModel(
name='PlainC1',
fields=[
('plainb1_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='deletion.plainb1')),
('standalone', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='plainc1s', to='deletion.standalone')),
],
bases=('deletion.plainb1',),
),
]

View File

@ -0,0 +1,37 @@
from .models import AiModelAnnotator, UserAnnotator, Annotator, Data
from rest_framework import serializers
from polymorphic.contrib.drf.serializers import PolymorphicSerializer
class AiModelAnnotatorSerializer(serializers.ModelSerializer):
class Meta:
model = AiModelAnnotator
fields = "__all__"
class UserAnnotatorSerializer(serializers.ModelSerializer):
class Meta:
model = UserAnnotator
fields = "__all__"
class AnnotatorSerializer(serializers.ModelSerializer):
class Meta:
model = Annotator
fields = "__all__"
class AnnotatorPolymorphicSerializer(PolymorphicSerializer):
model_serializer_mapping = {
Annotator: AnnotatorSerializer,
AiModelAnnotator: AiModelAnnotatorSerializer,
UserAnnotator: UserAnnotatorSerializer,
}
class AnnotationSerializer(serializers.ModelSerializer):
annotator = serializers.PrimaryKeyRelatedField(queryset=Annotator.objects.all())
class Meta:
model = Data
fields = "__all__"

View File

@ -0,0 +1,33 @@
from .filter_serializers import AnnotationSerializer
from .models import Data, AiModelAnnotator
from rest_framework import viewsets, mixins
from django_filters.rest_framework import DjangoFilterBackend
import django_filters
class DataFilterSet(django_filters.FilterSet):
"""FilterSet for Data model with polymorphic annotator filtering."""
annotator__ai_model = django_filters.CharFilter(method="filter_by_ai_model")
class Meta:
model = Data
fields = ["annotator"]
def filter_by_ai_model(self, queryset, name, value):
return queryset.filter(annotator__in=AiModelAnnotator.objects.filter(ai_model=value))
class AnnotationTrainingViewSet(
mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
viewsets.GenericViewSet,
):
queryset = Data.objects.all()
serializer_class = AnnotationSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = DataFilterSet
# this does not work
# filterset_fields = ["annotator", "annotator___AiModelAnnotator__ai_model"]

View File

@ -1,7 +1,8 @@
# Generated by Django 4.2 on 2026-01-13 11:18
# Generated by Django 5.2 on 2026-01-13 13:59
from django.db import migrations, models
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
@ -10,15 +11,14 @@ class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='BlogBase',
name='Annotator',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=10)),
('slug', models.SlugField(max_length=255, unique=True)),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
@ -36,6 +36,30 @@ class Migration(migrations.Migration):
'abstract': False,
},
),
migrations.CreateModel(
name='BlogBase',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=10)),
('slug', models.SlugField(max_length=255, unique=True)),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='AiModelAnnotator',
fields=[
('annotator_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='drf_example.annotator')),
('ai_model', models.CharField(max_length=255)),
('version', models.CharField(default=None, max_length=16, null=True)),
],
options={
'abstract': False,
},
bases=('drf_example.annotator',),
),
migrations.CreateModel(
name='ArtProject',
fields=[
@ -47,6 +71,17 @@ class Migration(migrations.Migration):
},
bases=('drf_example.project',),
),
migrations.CreateModel(
name='ResearchProject',
fields=[
('project_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='drf_example.project')),
('supervisor', models.CharField(max_length=30)),
],
options={
'abstract': False,
},
bases=('drf_example.project',),
),
migrations.CreateModel(
name='BlogOne',
fields=[
@ -69,15 +104,22 @@ class Migration(migrations.Migration):
bases=('drf_example.blogbase',),
),
migrations.CreateModel(
name='ResearchProject',
name='Data',
fields=[
('project_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='drf_example.project')),
('supervisor', models.CharField(max_length=30)),
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('annotator', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='drf_example.annotator')),
],
),
migrations.CreateModel(
name='UserAnnotator',
fields=[
('annotator_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='drf_example.annotator')),
('user', models.ForeignKey(default=None, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
],
options={
'abstract': False,
},
bases=('drf_example.project',),
bases=('drf_example.annotator',),
),
migrations.CreateModel(
name='BlogThree',

View File

@ -4,6 +4,12 @@ from .example_models import (
ArtProject,
ResearchProject,
)
from .filters import (
Annotator,
UserAnnotator,
AiModelAnnotator,
Data,
)
__all__ = [
"BlogBase",
@ -13,4 +19,8 @@ __all__ = [
"Project",
"ArtProject",
"ResearchProject",
"Annotator",
"UserAnnotator",
"AiModelAnnotator",
"Data",
]

View File

@ -0,0 +1,24 @@
"""
https://github.com/jazzband/django-polymorphic/issues/520
"""
from polymorphic.models import PolymorphicModel
from django.db import models
from django.contrib.auth import get_user_model
class Annotator(PolymorphicModel):
pass
class UserAnnotator(Annotator):
user = models.ForeignKey(get_user_model(), on_delete=models.PROTECT, default=None)
class AiModelAnnotator(Annotator):
ai_model = models.CharField(max_length=255)
version = models.CharField(max_length=16, default=None, null=True)
class Data(models.Model):
annotator = models.ForeignKey(Annotator, on_delete=models.PROTECT)

View File

@ -12,7 +12,14 @@ try:
BlogPolymorphicSerializer,
)
from .models import BlogBase, BlogOne, BlogTwo, Project, ArtProject, ResearchProject
from .models import (
BlogBase,
BlogOne,
BlogTwo,
Project,
ArtProject,
ResearchProject,
)
except ImportError:
pytest.skip("djangorestframework is not installed", allow_module_level=True)
@ -439,3 +446,139 @@ class TestProjectViewSet:
data = {"topic": "Test", "resourcetype": "InvalidType"}
response = client.post("/examples/integrations/drf/projects/", data, format="json")
assert response.status_code == 400
class TestDjangoFiltersViewSet:
"""Test django-filter integration with polymorphic models (issue #520)."""
@pytest.fixture
def client(self):
return APIClient()
@pytest.fixture
def user(self, django_user_model):
return django_user_model.objects.create_user(username="testuser", password="testpass")
@pytest.fixture
def user_annotator(self, user):
from .models import UserAnnotator
return UserAnnotator.objects.create(user=user)
@pytest.fixture
def ai_annotator_gpt4(self):
from .models import AiModelAnnotator
return AiModelAnnotator.objects.create(ai_model="gpt-4", version="1.0")
@pytest.fixture
def ai_annotator_claude(self):
from .models import AiModelAnnotator
return AiModelAnnotator.objects.create(ai_model="claude-3", version="2.0")
@pytest.fixture
def data_by_user(self, user_annotator):
from .models import Data
return Data.objects.create(annotator=user_annotator)
@pytest.fixture
def data_by_gpt4(self, ai_annotator_gpt4):
from .models import Data
return Data.objects.create(annotator=ai_annotator_gpt4)
@pytest.fixture
def data_by_claude(self, ai_annotator_claude):
from .models import Data
return Data.objects.create(annotator=ai_annotator_claude)
def test_list_all_annotations(self, client, data_by_user, data_by_gpt4, data_by_claude):
"""Test listing all annotation data without filters."""
response = client.get("/examples/integrations/drf/annotations/")
assert response.status_code == 200
assert len(response.data) == 3
def test_filter_by_annotator(self, client, data_by_user, data_by_gpt4, ai_annotator_gpt4):
"""Test filtering by annotator ID."""
response = client.get(
f"/examples/integrations/drf/annotations/?annotator={ai_annotator_gpt4.pk}"
)
assert response.status_code == 200
assert len(response.data) == 1
assert response.data[0]["id"] == data_by_gpt4.pk
def test_filter_by_ai_model(self, client, data_by_user, data_by_gpt4, data_by_claude):
"""Test filtering by annotator__ai_model field (issue #520)."""
# This is the key test - filtering by a field on the polymorphic child model
response = client.get("/examples/integrations/drf/annotations/?annotator__ai_model=gpt-4")
assert response.status_code == 200
assert len(response.data) == 1
assert response.data[0]["id"] == data_by_gpt4.pk
def test_filter_by_different_ai_model(
self, client, data_by_user, data_by_gpt4, data_by_claude
):
"""Test filtering by a different AI model."""
response = client.get(
"/examples/integrations/drf/annotations/?annotator__ai_model=claude-3"
)
assert response.status_code == 200
assert len(response.data) == 1
assert response.data[0]["id"] == data_by_claude.pk
def test_filter_by_nonexistent_ai_model(
self, client, data_by_user, data_by_gpt4, data_by_claude
):
"""Test filtering by an AI model that doesn't exist."""
response = client.get(
"/examples/integrations/drf/annotations/?annotator__ai_model=nonexistent"
)
assert response.status_code == 200
assert len(response.data) == 0
def test_filter_excludes_non_ai_annotators(
self, client, data_by_user, data_by_gpt4, data_by_claude
):
"""Test that filtering by ai_model excludes UserAnnotator instances."""
# When filtering by annotator__ai_model, only AiModelAnnotator results should be returned
# UserAnnotator doesn't have ai_model field, so data_by_user should not appear
response = client.get("/examples/integrations/drf/annotations/?annotator__ai_model=gpt-4")
assert response.status_code == 200
assert len(response.data) == 1
# Verify the user-annotated data is not in results
assert all(item["id"] != data_by_user.pk for item in response.data)
def test_retrieve_annotation(self, client, data_by_gpt4):
"""Test retrieving a single annotation."""
response = client.get(f"/examples/integrations/drf/annotations/{data_by_gpt4.pk}/")
assert response.status_code == 200
assert response.data["id"] == data_by_gpt4.pk
def test_create_annotation_with_user_annotator(self, client, user_annotator):
"""Test creating annotation data with a UserAnnotator."""
data = {"annotator": user_annotator.pk}
response = client.post("/examples/integrations/drf/annotations/", data, format="json")
assert response.status_code == 201
assert response.data["annotator"] == user_annotator.pk
from .models import Data
assert Data.objects.count() == 1
created = Data.objects.first()
assert created.annotator.pk == user_annotator.pk
def test_create_annotation_with_ai_annotator(self, client, ai_annotator_gpt4):
"""Test creating annotation data with an AiModelAnnotator."""
data = {"annotator": ai_annotator_gpt4.pk}
response = client.post("/examples/integrations/drf/annotations/", data, format="json")
assert response.status_code == 201
assert response.data["annotator"] == ai_annotator_gpt4.pk
from .models import Data
assert Data.objects.count() == 1
created = Data.objects.first()
assert created.annotator.pk == ai_annotator_gpt4.pk

View File

@ -1,10 +1,12 @@
from rest_framework.routers import DefaultRouter
from .views import ProjectViewSet
from .filter_views import AnnotationTrainingViewSet
app_name = "drf"
router = DefaultRouter()
router.register(r"projects", ProjectViewSet)
router.register(r"annotations", AnnotationTrainingViewSet)
urlpatterns = router.urls

View File

@ -1,7 +1,7 @@
# Generated by Django 4.2 on 2026-01-13 11:18
# Generated by Django 5.2 on 2026-01-13 13:59
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):

View File

@ -1,7 +1,7 @@
# Generated by Django 4.2 on 2026-01-13 11:18
# Generated by Django 5.2 on 2026-01-13 13:59
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
# Generated by Django 4.2 on 2026-01-13 11:18
# Generated by Django 5.2 on 2026-01-13 13:59
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):

View File

@ -134,6 +134,7 @@ try:
import rest_framework # noqa: F401
INSTALLED_APPS.insert(0, "rest_framework")
INSTALLED_APPS.insert(0, "django_filters")
INSTALLED_APPS.insert(0, "polymorphic.tests.examples.integrations.drf")
except ImportError:
pass

19
uv.lock
View File

@ -625,6 +625,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/10/6a/511cf7ad5ac8d0890eb7ec374668759e9fbb263af98abb516fdc14be2633/django_extra_views-0.16.0-py2.py3-none-any.whl", hash = "sha256:af990d1779813b728231e94bcc703614fef60015c4c31d53185c5f4f898a37be", size = 15344, upload-time = "2025-04-22T15:10:56.814Z" },
]
[[package]]
name = "django-filter"
version = "25.2"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django", version = "5.2.10", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.12'" },
{ name = "django", version = "6.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.12'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/2c/e4/465d2699cd388c0005fb8d6ae6709f239917c6d8790ac35719676fffdcf3/django_filter-25.2.tar.gz", hash = "sha256:760e984a931f4468d096f5541787efb8998c61217b73006163bf2f9523fe8f23", size = 143818, upload-time = "2025-10-05T09:51:31.521Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c1/40/6a02495c5658beb1f31eb09952d8aa12ef3c2a66342331ce3a35f7132439/django_filter-25.2-py3-none-any.whl", hash = "sha256:9c0f8609057309bba611062fe1b720b4a873652541192d232dd28970383633e3", size = 94145, upload-time = "2025-10-05T09:51:29.728Z" },
]
[[package]]
name = "django-guardian"
version = "3.2.0"
@ -685,6 +698,7 @@ docs = [
{ name = "sphinxcontrib-django" },
]
drf = [
{ name = "django-filter" },
{ name = "djangorestframework" },
]
extra-views = [
@ -742,7 +756,10 @@ docs = [
{ name = "sphinx-autobuild", specifier = ">=2024.10.3" },
{ name = "sphinxcontrib-django", specifier = ">=2.5" },
]
drf = [{ name = "djangorestframework", specifier = ">=3.16.1" }]
drf = [
{ name = "django-filter", specifier = ">=24.0" },
{ name = "djangorestframework", specifier = ">=3.16.1" },
]
extra-views = [{ name = "django-extra-views", specifier = ">=0.16.0" }]
guardian = [{ name = "django-guardian", specifier = ">=2.4.0" }]
mysql = [{ name = "mysqlclient", specifier = ">=1.4.0" }]