kopia lustrzana https://github.com/wagtail/wagtail
Add autocomplete endpoint for custom tag models
rodzic
51d8433b6b
commit
5d8b343528
|
@ -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):
|
||||
|
|
|
@ -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')),
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'),
|
||||
),
|
||||
]
|
|
@ -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'
|
||||
)
|
||||
|
|
Ładowanie…
Reference in New Issue