Add autocomplete endpoint for custom tag models

pull/5837/head
Matt Westcott 2020-02-17 22:21:07 +00:00
rodzic 51d8433b6b
commit 5d8b343528
5 zmienionych plików z 128 dodań i 6 usunięć

Wyświetl plik

@ -14,6 +14,7 @@ from wagtail.admin.auth import user_has_any_page_permission
from wagtail.admin.mail import send_mail
from wagtail.admin.menu import MenuItem
from wagtail.core.models import Page
from wagtail.tests.testapp.models import RestaurantTag
from wagtail.tests.utils import WagtailTestUtils
@ -170,6 +171,8 @@ class TestTagsAutocomplete(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
Tag.objects.create(name="Test", slug="test")
RestaurantTag.objects.create(name="Italian", slug="italian")
RestaurantTag.objects.create(name="Indian", slug="indian")
def test_tags_autocomplete(self):
response = self.client.get(reverse('wagtailadmin_tag_autocomplete'), {
@ -212,6 +215,30 @@ class TestTagsAutocomplete(TestCase, WagtailTestUtils):
data = json.loads(response.content.decode('utf-8'))
self.assertEqual(data, [])
def test_tags_autocomplete_custom_model(self):
response = self.client.get(
reverse('wagtailadmin_tag_model_autocomplete', args=('tests', 'restauranttag')),
{'term': 'ital'}
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/json')
data = json.loads(response.content.decode('utf-8'))
self.assertEqual(data, ['Italian'])
# should not return results from the standard Tag model
response = self.client.get(
reverse('wagtailadmin_tag_model_autocomplete', args=('tests', 'restauranttag')),
{'term': 'test'}
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'application/json')
data = json.loads(response.content.decode('utf-8'))
self.assertEqual(data, [])
class TestMenuItem(TestCase, WagtailTestUtils):
def setUp(self):

Wyświetl plik

@ -42,6 +42,7 @@ urlpatterns = [
url(r'^choose-anchor-link/$', chooser.anchor_link, name='wagtailadmin_choose_page_anchor_link'),
url(r'^tag-autocomplete/$', tags.autocomplete, name='wagtailadmin_tag_autocomplete'),
url(r'^tag-autocomplete/(\w+)/(\w+)/$', tags.autocomplete, name='wagtailadmin_tag_model_autocomplete'),
url(r'^collections/', include(wagtailadmin_collections_urls, namespace='wagtailadmin_collections')),

Wyświetl plik

@ -1,12 +1,26 @@
from django.http import JsonResponse
from taggit.models import Tag
from django.contrib.contenttypes.models import ContentType
from django.http import Http404, JsonResponse
from taggit.models import Tag, TagBase
def autocomplete(request):
def autocomplete(request, app_name=None, model_name=None):
if app_name and model_name:
try:
content_type = ContentType.objects.get_by_natural_key(app_name, model_name)
except ContentType.DoesNotExist:
raise Http404
tag_model = content_type.model_class()
if not issubclass(tag_model, TagBase):
raise Http404
else:
tag_model = Tag
term = request.GET.get('term', None)
if term:
tags = Tag.objects.filter(name__istartswith=term).order_by('name')
tags = tag_model.objects.filter(name__istartswith=term).order_by('name')
else:
tags = Tag.objects.none()
tags = tag_model.objects.none()
return JsonResponse([tag.name for tag in tags], safe=False)

Wyświetl plik

@ -0,0 +1,55 @@
# Generated by Django 2.2.6 on 2020-02-17 18:49
from django.db import migrations, models
import django.db.models.deletion
import modelcluster.contrib.taggit
import modelcluster.fields
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0045_assign_unlock_grouppagepermission'),
('tests', '0046_personpage'),
]
operations = [
migrations.CreateModel(
name='RestaurantPage',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
],
options={
'abstract': False,
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='RestaurantTag',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True, verbose_name='Name')),
('slug', models.SlugField(max_length=100, unique=True, verbose_name='Slug')),
],
options={
'verbose_name': 'Tag',
'verbose_name_plural': 'Tags',
},
),
migrations.CreateModel(
name='TaggedRestaurant',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('content_object', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='tests.RestaurantPage')),
('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_restaurants', to='tests.RestaurantTag')),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='restaurantpage',
name='tags',
field=modelcluster.contrib.taggit.ClusterTaggableManager(blank=True, help_text='A comma-separated list of tags.', through='tests.TaggedRestaurant', to='tests.RestaurantTag', verbose_name='Tags'),
),
]

Wyświetl plik

@ -16,7 +16,7 @@ from modelcluster.contrib.taggit import ClusterTaggableManager
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from modelcluster.models import ClusterableModel
from taggit.managers import TaggableManager
from taggit.models import TaggedItemBase
from taggit.models import ItemBase, TagBase, TaggedItemBase
from wagtail.admin.edit_handlers import (
FieldPanel, InlinePanel, MultiFieldPanel, ObjectList, PageChooserPanel, StreamFieldPanel,
@ -1411,3 +1411,28 @@ class AddressTag(TaggedItemBase):
on_delete=models.CASCADE,
related_name='tagged_items'
)
class RestaurantPage(Page):
tags = ClusterTaggableManager(through='tests.TaggedRestaurant', blank=True)
content_panels = Page.content_panels + [
FieldPanel('tags'),
]
class RestaurantTag(TagBase):
class Meta:
verbose_name = "Tag"
verbose_name_plural = "Tags"
class TaggedRestaurant(ItemBase):
tag = models.ForeignKey(
RestaurantTag, related_name="tagged_restaurants", on_delete=models.CASCADE
)
content_object = ParentalKey(
to='tests.RestaurantPage',
on_delete=models.CASCADE,
related_name='tagged_items'
)