class OpenGraphImageGeneratorSettings(BaseSetting): default_background_image = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.CASCADE, related_name='+', help_text= 'Will be used as a fallback background image for your OpenGraph images if no model specific image field has been defined.', ) company_logo = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.CASCADE, related_name='+', help_text='Will be added to the top left of every OpenGraph image.', ) company_logo_alternative = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.CASCADE, related_name='+', help_text= 'Alternative version of your logo for the dark OpenGraph image variant. You may want to supply a differently colored logo.', ) panels = [ ImageChooserPanel('default_background_image'), ImageChooserPanel('company_logo'), ImageChooserPanel('company_logo_alternative'), ]
class SiteContent(SeriailizerMixin, ClusterableModel): site = models.OneToOneField('wagtailcore.Site', on_delete=models.SET_NULL, blank=True, null=True, related_name='site_content') logo = models.ForeignKey(get_image_model_string(), on_delete=models.SET_NULL, blank=True, null=True, related_name='site_logo') navigation = models.ManyToManyField('wagtailcore.Page') footer_content = models.TextField() site_phone = models.CharField(max_length=16) site_email = models.EmailField(max_length=255) panels = [ FieldPanel('logo'), FieldPanel('site_phone'), FieldPanel('site_email'), FieldPanel('navigation'), InlinePanel('social_media', label='Social Media links'), FieldPanel('footer_content') ] serializer = "wesgarlock.base.serializers:SiteContentSerializer"
class Migration(migrations.Migration): initial = True dependencies = [ ('wagtailcore', '0060_fix_workflow_unique_constraint'), ('wagtailimages', '0023_add_choose_permissions'), ] operations = [ migrations.CreateModel( name='ImageSliderItem', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('text', wagtail.core.fields.RichTextField( default='', help_text='Text zobrazený přes obrázek.', max_length=200)), ('image', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to=get_image_model_string())), ], options={ 'verbose_name': 'Carousel Item', 'verbose_name_plural': 'Carousel Items', }, ), migrations.CreateModel( name='SiteSettingsSection', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('sort_order', models.IntegerField(blank=True, editable=False, null=True)), ('page', modelcluster.fields.ParentalKey( on_delete=django.db.models.deletion.CASCADE, related_name='carouselitems', to='wagtailcore.page')), ('slider', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='sitesettings.imageslideritem')), ], options={ 'verbose_name': 'Carousel Item', 'verbose_name_plural': 'Carousel Items', }, ), ]
class StaffMemberSnippet(index.Indexed, models.Model): photo = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+' ) name = models.CharField(max_length=255) job_title = models.CharField(max_length=255, null=True, blank=True) email = models.EmailField(max_length=255, null=True, blank=True) office_phone_number = models.CharField(max_length=255, null=True, blank=True) mobile_phone_number = models.CharField(max_length=255, null=True, blank=True) job_description = RichTextField(default='', blank=True) office_location = models.CharField(max_length=255, null=True, blank=True) panels = [ FieldPanel('name'), FieldPanel('job_title'), FieldPanel('email'), FieldPanel('office_phone_number'), FieldPanel('mobile_phone_number'), ImageChooserPanel('photo'), FieldPanel('job_description'), ] search_fields = [ index.SearchField('name', partial_match=True), index.SearchField('job_title', partial_match=True), ] def __str__(self): return self.name
class ProgramPageRelatedStaff(Orderable): page = models.ForeignKey( "wagtailcore.Page", null=True, blank=True, on_delete=models.CASCADE, related_name="+", ) source_page = ParentalKey("ProgrammePage", related_name="related_staff") image = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name="+", ) name = models.CharField(max_length=125, blank=True) role = models.CharField(max_length=125, blank=True) description = models.TextField(blank=True) link = models.URLField(blank=True) panels = [ PageChooserPanel("page", page_type="people.StaffPage"), ImageChooserPanel("image"), FieldPanel("name"), FieldPanel("role"), FieldPanel("description"), FieldPanel("link"), ] def __str__(self): return self.name
class StaffMember(Orderable): department = ParentalKey(StaffSection, related_name='staff') photo = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+' ) name = models.CharField(max_length=255) job_title = models.CharField(max_length=255, null=True, blank=True) email = models.EmailField(max_length=255, null=True, blank=True) office_phone_number = models.CharField(max_length=255, null=True, blank=True) mobile_phone_number = models.CharField(max_length=255, null=True, blank=True) job_description = RichTextField() office_location = models.CharField(max_length=255, null=True, blank=True) panels = [ FieldPanel('name'), FieldPanel('job_title'), FieldPanel('email'), FieldPanel('office_phone_number'), FieldPanel('mobile_phone_number'), ImageChooserPanel('photo'), FieldPanel('job_description'), ]
class HomePageCarouselItem(Orderable): page = ParentalKey('v1.HomePage', on_delete=models.CASCADE, related_name='carousel_items') title = models.CharField( max_length=45, help_text=("45 characters maximum (including spaces). " "Sentence case, unless proper noun.")) body = models.TextField( max_length=160, help_text=("160 characters maximum (including spaces).")) link_text = models.CharField( max_length=35, help_text=("35 characters maximum (including spaces). " "Lead with a verb, and be specific.")) # TODO: Change this to use a URLField that also allows relative links. # https://code.djangoproject.com/ticket/10896 link_url = models.CharField("Link URL", max_length=255) image = models.ForeignKey(get_image_model_string(), on_delete=models.SET_NULL, null=True, related_name='+') panels = [ FieldPanel('title'), FieldPanel('body'), FieldPanel('link_text'), FieldPanel('link_url'), ImageChooserPanel('image'), ]
class LandingPage(CMSGenericPage): parent_page_types = [ 'domestic.DomesticHomePage', # TODO: once we've restructured, remove this permission 'domestic.GreatDomesticHomePage', ] subpage_types = [ 'core.ListPage', 'core.InterstitialPage', 'exportplan.ExportPlanDashboardPage', 'domestic.DomesticDashboard', ] template_choices = ( ('learn/landing_page.html', 'Learn'), ('core/generic_page.html', 'Generic'), ) ################ # Content fields ################ description = RichTextField() button = StreamField([('button', core_blocks.ButtonBlock(icon='cog'))], null=True, blank=True) image = models.ForeignKey(get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+') body = StreamField( [ ('section', core_blocks.SectionBlock()), ('title', core_blocks.TitleBlock()), ('text', blocks.RichTextBlock(icon='openquote', helptext='Add a textblock')), ('image', core_blocks.ImageBlock()), ], null=True, blank=True, ) components = StreamField( [ ('route', core_blocks.RouteSectionBlock()), ], null=True, blank=True, ) ######### # Panels ######### content_panels = CMSGenericPage.content_panels + [ FieldPanel('description'), StreamFieldPanel('button'), ImageChooserPanel('image'), StreamFieldPanel('components'), StreamFieldPanel('body'), ]
class PhotoPagePhoto(Orderable, ClusterableModel): page = ParentalKey('photostream.PhotoPage', related_name='photos') photo = models.ForeignKey(get_image_model_string(), models.CASCADE, related_name='+') panels = [ ImageChooserPanel('photo'), ]
class SocialFields(models.Model): feed_image = models.ForeignKey(get_image_model_string(), models.SET_NULL, blank=True, null=True, related_name='+') promote_panels = [ ImageChooserPanel('feed_image'), ] class Meta: abstract = True
def create_import_permission(apps, schema_editor): label, model_name = get_image_model_string().lower().split(".") ContentType = apps.get_model("contenttypes", "ContentType") image_content_type = ContentType.objects.get_for_model( apps.get_model(label, model_name)) Permission = apps.get_model("auth", "Permission") Permission.objects.get_or_create( codename="import_image", name="Can import images", content_type=image_content_type, )
class ImageWithRenditions(models.Model): """ ImageWithRenditions """ image = models.ForeignKey(get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+') image_mobile_rendition = models.CharField( choices=MOBILE_RENDITION_CHOICES, verbose_name='Mobile Rendition', default='none', max_length=10, ) image_desktop_rendition = models.CharField( choices=DESKTOP_RENDITION_CHOICES, verbose_name='Desktop Rendition', default='none', max_length=10, ) @property def mobile_image(self): """ mobile_image """ mobile_image = self.image.generate_and_get_rendition( self.image_mobile_rendition) if hasattr(settings, 'LOCAL_ASSET_FULL_PATH') and settings.LOCAL_ASSET_FULL_PATH: mobile_image = 'http://localhost:8000{0}'.format(mobile_image) return mobile_image @property def desktop_image(self): """ desktop_image """ desktop_image = self.image.generate_and_get_rendition( self.image_desktop_rendition) if hasattr(settings, 'LOCAL_ASSET_FULL_PATH') and settings.LOCAL_ASSET_FULL_PATH: desktop_image = 'http://localhost:8000{0}'.format(desktop_image) return desktop_image panels = [ ImageChooserPanel('image'), FieldPanel('image_mobile_rendition'), FieldPanel('image_desktop_rendition'), ] api_fields = [ APIField('mobile_image'), APIField('desktop_image'), ] class Meta: """ Meta """ abstract = True
class HomePageTransofmrationBlock(models.Model): source_page = ParentalKey("HomePage", related_name="transformation_blocks") heading = models.CharField( max_length=125, help_text="Large heading displayed above the image") image = models.ForeignKey( get_image_model_string(), blank=True, null=True, on_delete=models.SET_NULL, related_name="+", ) video = models.URLField(blank=True) video_caption = models.CharField( blank=True, max_length=80, help_text="The text dipsplayed next to the video play button", ) sub_heading = models.CharField(max_length=125, blank=True, help_text="The title below the image") page_title = models.CharField( max_length=125, blank=True, help_text="A title for the linked related page") page_summary = models.CharField( max_length=250, blank=True, help_text="A summary for the linked related page") page_link_url = models.URLField(blank=True, help_text="A url to a related page") panels = [ FieldPanel("heading"), ImageChooserPanel("image"), FieldPanel("video"), FieldPanel("video_caption"), FieldPanel("sub_heading"), FieldPanel("page_title"), FieldPanel("page_summary"), FieldPanel("page_link_url"), ] def __str__(self): return self.heading def clean(self): errors = defaultdict(list) if self.video and not self.video_caption: errors["video_caption"].append( "Please add a caption for the video") if errors: raise ValidationError(errors)
class BasicPage(Page): template = "basic/basic_page.html" subpage_types = ['basic.BasicPage'] parent_page_types = ['basic.BasicPage', 'wagtailcore.Page'] banner_title = models.CharField(max_length=150, null=True, blank=True) banner_subtitle = models.CharField(max_length=300, blank=True, null=True) banner_image = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+', ) body = StreamField([ ("cta", blocks.CallToActionBlock()), ("large_text", blocks.LargeTextBlock()), ("large_listing_block", blocks.LargeListingBlock()), ("small_listing_block", blocks.SmallListingBlock()), ("richtext", wagtail_blocks.RichTextBlock( template="streams/simple_richtext_block.html", features=["h3", "bold", "italic", "ol", "ul", "link", "image"], group="Text Sections")), ("buttons", blocks.ButtonBlock()), ("image_gallery", blocks.ImageGallery()), ("hr", blocks.HorizontalRuleBlock()), ("horizontal_gallery", blocks.HorizontalGallery()), ], null=True, blank=True) content_panels = Page.content_panels + [ MultiFieldPanel([ FieldPanel('banner_title'), FieldPanel('banner_subtitle'), ImageChooserPanel('banner_image') ], heading='Banner Settings'), StreamFieldPanel("body"), MultiFieldPanel([SnippetChooserPanel("footer_cta")], 'Optional footer cta'), ] # Optional Footer CTA footer_cta = models.ForeignKey( 'cta.CallToAction', blank=True, null=True, on_delete=models.SET_NULL, related_name='+', help_text='Optional footer call to action for this page')
class PiecePageAbstract(Page): body = RichTextField(verbose_name=_('body'), blank=True) tags = ClusterTaggableManager(through='PiecePageTag', blank=True) date = models.DateField( _("Post date"), default=datetime.datetime.today, help_text=_("This date may be displayed on the Piece post. It is not " "used to schedule posts to go live at a later date.")) header_image = models.ForeignKey(get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+', verbose_name=_('Header image')) search_fields = Page.search_fields + [ index.SearchField('body'), ] Piece_categories = ParentalManyToManyField( 'PieceCategory', through='PieceCategoryPiecePage', blank=True) settings_panels = [ MultiFieldPanel([ FieldRowPanel([ FieldPanel('go_live_at'), FieldPanel('expire_at'), ], classname="label-above"), ], 'Scheduled publishing', classname="publishing"), FieldPanel('date'), ] def get_absolute_url(self): return self.url class Meta: abstract = True verbose_name = _('Piece page') verbose_name_plural = _('Piece pages') api_fields = [APIField('body')] content_panels = [ FieldPanel('title', classname="full title"), MultiFieldPanel([ FieldPanel('tags'), FieldPanel('Piece_categories'), ], heading="Tags and Categories"), ImageChooserPanel('header_image'), FieldPanel('body', classname="full"), ]
class StaffMemberSnippet(index.Indexed, models.Model): class Meta: verbose_name = 'Job Role' verbose_name_plural = 'Job Roles' photo = models.ForeignKey(get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+') name = models.CharField(max_length=255) job_title = models.CharField(max_length=255, null=True, blank=False) email = models.EmailField(max_length=255, null=True, blank=True) office_phone_number = models.CharField(max_length=255, null=True, blank=True) mobile_phone_number = models.CharField(max_length=255, null=True, blank=True) job_description = RichTextField(default='', blank=True) office_location = models.CharField(max_length=255, null=True, blank=True) panels = [ HelpPanel( 'Humans should be assigned to the job role. If a person has switched roles, please update snippet of their new role with their infomation, rather than updating their current role snippet with their new role.' ), MultiFieldPanel(( FieldPanel('name'), FieldPanel('mobile_phone_number'), ImageChooserPanel('photo'), FieldPanel('email'), ), heading='Employee centric details'), MultiFieldPanel(( FieldPanel('job_title'), FieldPanel('job_description'), FieldPanel('office_phone_number'), ), heading='Role centric details', help_text='These should not need to change'), ] search_fields = [ index.SearchField('job_title', partial_match=True, boost=1.1), index.SearchField('name', partial_match=True), ] type_fields = ('photo', 'name', 'job_title', 'email', 'office_phone_number', 'mobile_phone_number', 'job_description', 'office_location') def __str__(self): return f'{self.job_title} ({self.name})'
class HomePageInfoUnit(Orderable, ClusterableModel): page = ParentalKey( 'v1.HomePage', on_delete=models.CASCADE, related_name='info_units' ) title = models.CharField(max_length=35, help_text=( "35 characters maximum (including spaces). " "Sentence case, unless proper noun." )) body = models.TextField(max_length=140, help_text=( "140 characters maximum (including spaces)." )) image = models.ForeignKey( get_image_model_string(), on_delete=models.SET_NULL, null=True, related_name='+' ) panels = [ FieldPanel('title'), FieldPanel('body'), ImageChooserPanel('image'), # Note: this min_num=1 doesn't seem to work properly, allowing users to # save new info units without providing links. This might be due to the # incomplete support for nested InlinePanels in our version of Wagtail. # See comments above and https://github.com/wagtail/wagtail/pull/5566. InlinePanel('links', min_num=1, label="Link"), ] def as_info_unit(self): """Convert model instance into data for molecules.InfoUnit. This allows us to use the existing InfoUnit template to render this model instance. """ return { 'image': { 'upload': self.image, }, 'heading': { 'text': self.title, 'level': 'h2', 'level_class': 'h3', }, 'body': self.body, 'links': [ { 'text': link.text, 'url': link.url, } for link in self.links.all() ], }
class BlogCategory(models.Model): name = models.CharField(max_length=80, unique=True, verbose_name=_('Category Name')) slug = models.SlugField(unique=True, max_length=80) parent = models.ForeignKey( 'self', blank=True, null=True, related_name="children", help_text=_( 'Categories, unlike tags, can have a hierarchy. You might have a ' 'Jazz category, and under that have children categories for Bebop' ' and Big Band. Totally optional.'), on_delete=models.CASCADE, ) description = models.CharField(max_length=500, blank=True) menu_image = models.ForeignKey( get_image_model_string(), on_delete=models.CASCADE, related_name='+', verbose_name=_('Menu Image'), ) class Meta: ordering = ['name'] verbose_name = _("Blog Category") verbose_name_plural = _("Blog Categories") panels = [ FieldPanel('name'), FieldPanel('parent'), FieldPanel('description'), ImageChooserPanel('menu_image'), ] def __str__(self): return self.name def clean(self): if self.parent: parent = self.parent if self.parent == self: raise ValidationError('Parent category cannot be self.') if parent.parent and parent.parent == self: raise ValidationError('Cannot have circular Parents.') def save(self, *args, **kwargs): if not self.slug: unique_slugify(self, self.name) return super(BlogCategory, self).save(*args, **kwargs)
class MetadataPageMixin(MetadataMixin, models.Model): search_image = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+', ) panels = [ ImageChooserPanel('search_image'), ] _metadata = { 'published_time': 'published_time', 'modified_time': 'latest_revision_created_at', 'expiration_time': 'expire_at', } class Meta: abstract = True @property def published_time(self): return self.go_live_at or self.first_published_at def get_meta_title(self): return self.seo_title or self.title def get_meta_description(self): return self.search_description def get_meta_keywords(self): return [] def get_meta_url(self): return self.build_absolute_uri(self.url) def get_meta_image(self): if self.search_image is not None: return self.build_absolute_uri( self.search_image.get_rendition( getattr(settings, 'META_SEARCH_IMAGE_RENDITION', 'fill-800x450')).url) return super(MetadataPageMixin, self).get_meta_image() def get_author(self): author = super(MetadataPageMixin, self).get_author() if hasattr(self, 'owner') and isinstance(self.owner, get_user_model()): author.get_full_name = self.owner.get_full_name return author
class SomePage(Page): image = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name="+", verbose_name="Image", ) content_panels = Page.content_panels + [ ImageChooserPanel("image"), ]
class Migration(migrations.Migration): dependencies = [ ("wagtailimages", "0022_uploadedimage"), migrations.swappable_dependency(get_image_model_string()), ("auth", "0011_update_proxy_permissions"), ("contenttypes", "0002_remove_content_type_name"), ] operations = [ migrations.RunPython(create_import_permission, delete_import_permission), ]
class TwitterPage(TwitterModelMixin, Page): og_image = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name="+", verbose_name=_("Og image"), ) og_title = models.CharField(blank=True, max_length=100) og_description = models.CharField(blank=True, max_length=100) another_title = models.CharField(blank=True, max_length=100) another_description = models.CharField(blank=True, max_length=100)
class HomePage(BasePage): template = "home/home_page.jinja" serializer = "daash.base.serializers:HomePageSerializer" primary_page = models.ForeignKey('wagtailcore.Page', on_delete=models.SET_NULL, blank=True, null=True, related_name="primary_homepage_link") secondary_page = models.ForeignKey('wagtailcore.Page', on_delete=models.SET_NULL, blank=True, null=True, related_name="secondary_homepage_link") hero_image = models.ForeignKey(get_image_model_string(), on_delete=models.SET_NULL, related_name='+', null=True) about_image = models.ForeignKey(get_image_model_string(), on_delete=models.SET_NULL, related_name='+', null=True) about_me = RichTextField() content_panels = BasePage.content_panels + [ PageChooserPanel('primary_page'), PageChooserPanel('secondary_page'), ImageChooserPanel('hero_image'), ImageChooserPanel('about_image'), FieldPanel("about_me") ] api_fields = BasePage.api_fields + [ 'primary_page', 'secondary_page', 'hero_image', 'about_image' ] class Meta: verbose_name = "home_page" verbose_name_plural = "home_pages"
class Migration(migrations.Migration): initial = True dependencies = [ ("wagtailimages", "0022_uploadedimage"), ("wagtail_image_import", "0001_create_import_permission"), migrations.swappable_dependency(get_image_model_string()), ] operations = [ migrations.CreateModel( name="DriveIDMapping", fields=[ ( "id", models.AutoField( auto_created=True, primary_key=True, serialize=False, verbose_name="ID", ), ), ("drive_id", models.CharField(max_length=100)), ( "image", models.OneToOneField( on_delete=django.db.models.deletion.CASCADE, to=get_image_model_string(), ), ), ], options={ "verbose_name": "Drive ID Mapping", "verbose_name_plural": "Drive ID Mappings", }, ), ]
class BasePage(BasePageMixin, Page): description = RichTextField(default='') meta_description = models.CharField(max_length=120, blank=True, null=True) og_description = models.CharField(max_length=300, blank=True, null=True) og_image = models.ForeignKey(get_image_model_string(), null=True, on_delete=models.SET_NULL, related_name='+') content_panels = Page.content_panels + [ FieldPanel('description', classname='full'), ] promote_panels = Page.promote_panels + [ MultiFieldPanel([ FieldPanel('meta_description', help_text='in browser text: max chars 120'), FieldPanel('og_description', help_text='social media text: max chars 300'), ImageChooserPanel('og_image'), ], 'Open Graph Content'), ] api_fields = [ APIField('description'), APIField('og_image_400', serializer=ImageRenditionField('width-400', source='og_image')), APIField('og_image_800', serializer=ImageRenditionField('width-800', source='og_image')), APIField('og_image_1920', serializer=ImageRenditionField('width-1920', source='og_image')) ] def save(self, *args, **kwargs): result = super().save(*args, **kwargs) if len(self.title) > 60: raise ValidationError('Must be at least 60 or less chars.') if self.og_description == '': self.og_description = self.meta_description return result class Meta: abstract = True verbose_name = _('basepage') verbose_name_plural = _('basepages')
def to_representation(self, value): return { 'id': value.id, 'name': value.name, 'image': { 'id': value.image.id, 'meta': { 'type': get_image_model_string(), 'detail_url': f'{Site.objects.get(is_default_site=True).root_url}{reverse("wagtailapi:images:detail", args=[value.image.id])}', 'download_url': value.image.file.url }, 'title': value.image.file.name } }
class BlogPageAbstract(Page): body = RichTextField(verbose_name=_('body'), blank=True, null=False) #tags date = models.DateField(_('Post Date')) header_image = models.ForeignKey(get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+', verbose_name=_('Header image')) content_panels = Page.content_panels + [] class Meta: abstract = True
class DriveIDMapping(models.Model): """ Represents the Drive ID of an image which has previously been imported from Google Drive, used for identifying duplicates/reimports """ image = models.OneToOneField(get_image_model_string(), on_delete=models.CASCADE) drive_id = models.CharField(max_length=100) def __str__(self): return "{}: {}-{}".format(self._meta.verbose_name, self.image.title, self.drive_id) class Meta: verbose_name = _("Drive ID Mapping") verbose_name_plural = "Drive ID Mappings"
class StudentPageGallerySlide(Orderable): source_page = ParentalKey("StudentPage", related_name="gallery_slides") title = models.CharField(max_length=120) image = models.ForeignKey( get_image_model_string(), null=True, related_name="+", on_delete=models.SET_NULL, ) author = models.CharField(max_length=120) panels = [ ImageChooserPanel("image"), FieldPanel("title"), FieldPanel("author") ]
class CarouselSlide(Orderable, models.Model): """ Represents a slide for the Carousel model. Can be modified through the snippets UI. """ class Meta: verbose_name = _('Carousel Slide') carousel = ParentalKey( Carousel, related_name='carousel_slides', verbose_name=_('Carousel'), ) image = models.ForeignKey( get_image_model_string(), null=True, blank=True, on_delete=models.SET_NULL, related_name='+', verbose_name=_('Image'), ) background_color = models.CharField( max_length=255, blank=True, verbose_name=_('Background color'), help_text=_('Hexadecimal, rgba, or CSS color notation (e.g. #ff0011)'), ) custom_css_class = models.CharField( max_length=255, blank=True, verbose_name=_('Custom CSS class'), ) custom_id = models.CharField( max_length=255, blank=True, verbose_name=_('Custom ID'), ) content = StreamField(HTML_STREAMBLOCKS, blank=True) panels = ([ ImageChooserPanel('image'), FieldPanel('background_color'), FieldPanel('custom_css_class'), FieldPanel('custom_id'), StreamFieldPanel('content'), ])
def test_standard_get_image_model_string(self): """Test get_image_model_STRING with no WAGTAILIMAGES_IMAGE_MODEL""" del settings.WAGTAILIMAGES_IMAGE_MODEL self.assertEqual(get_image_model_string(), 'wagtailimages.Image')
def test_custom_get_image_model_string(self): """Test get_image_model_string with a custom image model""" self.assertEqual(get_image_model_string(), 'tests.CustomImage')