def __init__(self, *args, **kwargs): super(SiteSettingsAdminForm, self).__init__(*args, **kwargs) self.fields["keywords"].widget = AdminTextareaWidget(attrs={'rows': 3}) self.fields["description"].widget = AdminTextareaWidget(attrs={'rows': 5}) self.fields['rss_content_types'].choices = site.get_base_ctype_choices() if ('', '------') in self.fields['rss_content_types'].choices: self.fields['rss_content_types'].choices.remove(('', '------'))
class PicturePlugin(ContentPlugin): """ Plugin for rendering pictures. """ model = PictureItem category = ContentPlugin.MEDIA render_template = "fluent_contents/plugins/picture/default.html" search_fields = ('caption', ) formfield_overrides = { 'caption': { 'widget': AdminTextareaWidget(attrs={ 'cols': 30, 'rows': 4, 'class': 'vTextField' }), }, } radio_fields = {'align': ContentPlugin.HORIZONTAL} class Media: css = { 'screen': ('fluent_contents/plugins/picture/picture_admin.css', ) }
class ExecutionLogEntryAdmin(admin.ModelAdmin): formfield_overrides = { models.CharField: { 'widget': AdminTextInputWidget(attrs={'readonly': 'readonly'}) }, models.TextField: { 'widget': AdminTextareaWidget(attrs={ 'readonly': 'readonly', 'rows': 40 }) }, models.IntegerField: { 'widget': AdminIntegerFieldWidget(attrs={'readonly': 'readonly'}) }, models.ForeignKey: { 'widget': forms.Select(attrs={'disabled': 'disabled'}) } } list_display = ('submission', 'command', 'retval', 'team', 'contest') search_fields = ('submission', 'team') list_filter = ('submission__team', 'submission__team__contest') def has_add_permission(self, request): return False
def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name in ('meta_title', 'meta_keywords'): kwargs.setdefault('widget', AdminTextInputWidget(attrs={'class': 'vLargeTextField'})) if db_field.name == 'meta_description': kwargs.setdefault('widget', AdminTextareaWidget(attrs={'rows': 3})) return super(HtmlPageAdmin, self).formfield_for_dbfield(db_field, **kwargs)
def formfield(self, **kwargs): defaults = { 'widget': AdminTextareaWidget(attrs={'rows':self.rows, 'cols':self.cols}), 'form_class': form_fields.PoSafeTextField } defaults.update(kwargs) return super(SafeTextField, self).formfield(**defaults)
class PicturePlugin(ContentPlugin): """ Plugin for rendering pictures. """ model = PictureItem category = ContentPlugin.MEDIA render_template = "fluent_contents/plugins/picture/default.html" search_fields = ("caption", ) formfield_overrides = { "caption": { "widget": AdminTextareaWidget(attrs={ "cols": 30, "rows": 4, "class": "vTextField" }) } } radio_fields = {"align": ContentPlugin.HORIZONTAL} class Media: css = { "screen": ("fluent_contents/plugins/picture/picture_admin.css", ) }
class Meta: model = ProjectCreateTemplate exclude = [] widgets = { 'description': SummernoteWidget(attrs={'height': '200px'}), 'default_description': SummernoteWidget(attrs={'height': '200px'}), 'default_pitch': AdminTextareaWidget(attrs={'cols': '40', 'rows': '5'}) }
class FilerPicturePlugin(ContentPlugin): model = FilerPictureItem category = _("Filer") admin_form_template = "admin/fluentcms_filer/picture/admin_form.html" admin_init_template = "admin/fluentcms_filer/picture/admin_init.html" render_template = "fluentcms_filer/picture.html" formfield_overrides = { "caption": { "widget": AdminTextareaWidget(attrs={"cols": 30, "rows": 4, "class": "vTextField"}), }, } radio_fields = {"align": ContentPlugin.HORIZONTAL} class Media: css = {"screen": ("fluentcms_filer/picture/admin.css",)}
class PackagePlugin(ContentPlugin): model = PackageItem render_template = "themeelements/packageitem.html" category = _("Theme elements") formfield_overrides = { 'description': { 'widget': AdminTextareaWidget(attrs={ 'rows': 4, 'style': 'width: 30em;' }) } } class Media: js = ('themeelements/admin/packageplugin.js', )
class FilerPicturePlugin(ContentPlugin): model = FilerPictureItem category = _('Filer') render_template = "fluentcms_filer/picture.html" formfield_overrides = { 'caption': { 'widget': AdminTextareaWidget(attrs={ 'cols': 30, 'rows': 4, 'class': 'vTextField' }), }, } radio_fields = {'align': ContentPlugin.HORIZONTAL} class Media: css = {'screen': ('fluentcms_filer/picture/admin.css', )}
class SeoEntryAdminMixin(object): """ Mixin for the SEO fields. """ FIELDSET_SEO = (_('SEO settings'), { 'fields': ('meta_keywords', 'meta_description'), 'classes': ('collapse',), }) # AbstractEntryBaseAdmin allows to specify the widgets by field name, # which formfield_overrides doesn't support by default. formfield_overrides = { 'meta_keywords': { 'widget': AdminTextInputWidget(attrs={'class': 'vLargeTextField'}) }, 'meta_description': { 'widget': AdminTextareaWidget(attrs={'rows': 3}) }, }
class RaAdmin(RaThemeMixin, VersionAdmin): # ModelAdmin Attributes view_on_site = False list_per_page = 25 save_on_top = True list_select_related = True fields = default_fields list_display = ('get_enhanced_obj_title', 'slug', 'notes', 'get_history_link') list_display_links = ('slug', ) date_hierarchy = 'creation_date' # Custom templates history_latest_first = True search_fields = ['title', 'slug'] formfield_overrides = { # DateTimeField: {'widget': AdminSplitDateTime}, # DecimalField: {'widget': NumberInput}, # ForeignKey: {'widget': RaBootstrapForeignKeyWidget}, TextField: { 'widget': AdminTextareaWidget(attrs={'rows': 2}) } } # Ra New Attributes # ------------------ description = None # Description of the model to be displayed in hte changelist filter under the name enable_next_serial = True # Enable the default slug to be a serial number enable_view_view = True # If False there is no "DetailView ie Stats view" print_template = None no_records_message = _('No Data') typed_reports_order_list = None # new attrs: print_settings = {} print_title = '' print_class = HTMLPrintingClass def reversion_register(self, model, **kwargs): kwargs['for_concrete_model'] = False super(RaAdmin, self).reversion_register(model, **kwargs) def get_enhanced_obj_title(self, obj): request = CrequestMiddleware.get_request() links = [] pk_attname = self.model._meta.pk.attname pk = getattr(obj, pk_attname) main_url = False if self.has_change_permission(request, obj): url = reverse( '%s:%s_%s_change' % (app_settings.RA_ADMIN_SITE_NAME, self.model._meta.app_label, self.model._meta.model_name), args=(quote(pk), ), current_app=self.admin_site.name) if not main_url: main_url = url view_link = '<a href="%s" data-popup="tooltip" title="%s" data-placement="bottom">' \ ' <i class="fas fa-edit"></i> </a>' % ( url, capfirst(_('change'))) links.append(view_link) links = "<span class='go-to-change-form'>%s</span>" % ''.join( links) + '' obj_link_title = "<a href='%s'>%s</a>" % (main_url, obj.title) return mark_safe('%s %s' % (obj_link_title, links)) return obj.title def get_history_link(self, obj): info = self.model._meta.app_label, self.model._meta.model_name url = reverse('ra_admin:%s_%s_history' % info, args=(obj.pk, )) return mark_safe( """<a href="%s" class="legitRipple" data-popup="tooltip" title="%s"> <i class="fas fa-history text-indigo-800"></i> <span class="legitRipple-ripple"></span></a>""" % (url, _('History'))) get_history_link.short_description = _('History') get_enhanced_obj_title.short_description = _('title') get_enhanced_obj_title.admin_order_field = 'title' def get_stats_icon(self, obj): url = reverse( '%s:%s_%s_view' % (app_settings.RA_ADMIN_SITE_NAME, self.model._meta.app_label, self.model._meta.model_name), args=(quote(obj.pk), ), current_app=self.admin_site.name) view_link = '<a href="%s" data-popup="tooltip" title="%s %s" data-placement="bottom"> ' \ '<i class="fas fa-chart-line"></i> </a>' % ( url, capfirst(_('Statistics for')), obj.title) return mark_safe(view_link) get_stats_icon.short_description = _('Stats') # Permissions def has_view_permission(self, request, obj=None): if not self.enable_view_view: return False opts = self.opts codename = get_permission_codename('view', opts) return request.user.has_perm("%s.%s" % (opts.app_label, codename)) def view_view(self, request, object_id, form_url='', extra_context=None): extra_context = extra_context or {} extra_context['has_add_permission'] = self.has_add_permission(request) ''' Code copied from ChangeForm ''' to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_view_permission(request, obj): raise PermissionDenied if obj is None: raise Http404( _('%(name)s object with primary key %(key)r does not exist.' ) % { 'name': force_text(opts.verbose_name), 'key': escape(object_id) }) # if request.method == 'POST' and "_saveasnew" in request.POST: # return self.add_view(request, form_url=reverse('admin:%s_%s_add' % ( # opts.app_label, opts.model_name), current_app=self.admin_site.name)) context = dict( self.admin_site.each_context(request), title=obj, app_label=opts.app_label, object_id=object_id, original=obj, is_popup=(IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET), to_field=to_field, # media=media, preserved_filters=self.get_preserved_filters(request), ) context.update(extra_context or {}) opts = self.model._meta app_label = opts.app_label preserved_filters = self.get_preserved_filters(request) form_url = add_preserved_filters( { 'preserved_filters': preserved_filters, 'opts': opts }, form_url) view_on_site_url = self.get_view_on_site_url(obj) context.update({ 'add': add, 'change': not add, 'has_add_permission': self.has_add_permission(request), 'has_change_permission': self.has_change_permission(request, obj), 'has_delete_permission': self.has_delete_permission(request, obj), 'has_file_field': True, 'has_absolute_url': view_on_site_url is not None, 'absolute_url': view_on_site_url, 'form_url': form_url, 'opts': opts, 'content_type_id': get_content_type_for_model(self.model).pk, 'save_as': self.save_as, 'save_on_top': self.save_on_top, 'to_field_var': TO_FIELD_VAR, 'is_popup_var': IS_POPUP_VAR, 'app_label': app_label, }) request.current_app = self.admin_site.name return TemplateResponse( request, self.view_template or [ "admin/%s/%s/view.html" % (opts.app_label, opts.model_name), "admin/%s/view.html" % opts.app_label, f"{app_settings.RA_THEME}/view.html", ], context) @csrf_protect_m def changelist_view(self, request, extra_context=None): extra_context = extra_context or {} extra_context['description'] = self.description return super(RaAdmin, self).changelist_view(request, extra_context) def get_changelist(self, request, **kwargs): return RaChangeList def save_model(self, request, obj, form, change): obj.lastmod_user = request.user obj.lastmod_date = now() if not change: obj.owner = request.user obj.creation_date = now() super(RaAdmin, self).save_model(request, obj, form, change) def get_urls(self): # Override ModelAdmin from django.conf.urls import url def wrap(view): def wrapper(*args, **kwargs): return self.admin_site.admin_view(view)(*args, **kwargs) return update_wrapper(wrapper, view) info = self.model._meta.app_label, self.model._meta.model_name admin_site = self.admin_site reversion_urls = [ url("^recover/$", admin_site.admin_view(self.recoverlist_view), name='%s_%s_recoverlist' % info), url("^recover/([^/]+)/$", admin_site.admin_view(self.recover_view), name='%s_%s_recover' % info), url("^([^/]+)/history/([^/]+)/$", admin_site.admin_view(self.revision_view), name='%s_%s_revision' % info), ] urlpatterns = [ url(r'^$', wrap(self.changelist_view), name='%s_%s_changelist' % info), url(r'^add/$', wrap(self.add_view), name='%s_%s_add' % info), url(r'^(.+)/history/$', wrap(self.history_view), name='%s_%s_history' % info), url(r'^(.+)/delete/$', wrap(self.delete_view), name='%s_%s_delete' % info), url(r'^(.+)/change/$', wrap(self.change_view), name='%s_%s_change' % info), ] # url(r'^(.+)/$', wrap(self.view_view), name='%s_%s_view' % info), if self.enable_view_view: urlpatterns += [ url(r'^(.+)/$', wrap(self.view_view), name='%s_%s_view' % info), ] # End Override # ------------------------------------------------------------------------------ my_urls = [ path('autocomplete/', wrap(self.autocomplete_view), name='%s_%s_autocomplete' % info), url(r'^slug/(?P<slug>[\w-]+)/$', self.admin_site.admin_view(self.get_by_slug)), ] return my_urls + reversion_urls + urlpatterns def get_by_slug(self, request, **kwargs): query = self.model.objects.filter(**kwargs) result = query.exists() if result: query = query[0] admin_url = reverse( '%s:%s_%s_change' % (app_settings.RA_ADMIN_SITE_NAME, self.model._meta.app_label, self.model._meta.model_name), args=(query.id, )) return HttpResponseRedirect(admin_url) else: raise Http404 def formfield_for_dbfield(self, db_field, request, **kwargs): if isinstance(db_field, models.ForeignKey): if db_field.__class__ in self.formfield_overrides: kwargs = dict(self.formfield_overrides[db_field.__class__], **kwargs) formfield = self.formfield_for_foreignkey(db_field, request, **kwargs) if formfield and db_field.name not in self.raw_id_fields: related_modeladmin = self.admin_site._registry.get( db_field.remote_field.model) wrapper_kwargs = {} if related_modeladmin: wrapper_kwargs.update( can_add_related=related_modeladmin.has_add_permission( request), can_change_related=related_modeladmin. has_change_permission(request), can_delete_related=related_modeladmin. has_delete_permission(request), ) formfield.widget = RaRelatedFieldWidgetWrapper( formfield.widget, db_field.remote_field, self.admin_site, **wrapper_kwargs) return app_settings.RA_FORMFIELD_FOR_DBFIELD_FUNC( self, db_field, formfield, request, **kwargs) # if db_field.name == 'doc_date' and db_field.__class__ == DateTimeField: # field = forms.SplitDateTimeField(widget=AdminSplitDateTimeNoBr, label=_('Date')) # else: field = super(RaAdmin, self).formfield_for_dbfield(db_field, request, **kwargs) if db_field.name == 'slug' and self.enable_next_serial: field.initial = self.get_next_serial() elif db_field.name == 'doc_date': field.initial = now() return app_settings.RA_FORMFIELD_FOR_DBFIELD_FUNC( self, db_field, field, request, **kwargs) def get_next_serial(self): from ra.base.helpers import get_next_serial return get_next_serial(self.model) def whole_changeform_validation(self, request, form, formsets, change, **kwargs): ''' A Hook for validating the whole changeform :param form: the ModelAdmin Form :param formsets: inline formsets :param kwargs: extra kwargs :return: True for valid [default] False for Invalid ''' return True def pre_save(self, form, formsets, change): """ Hook for doing any final computation setting before saving :param form: :param formsets: :param change: :return: """ pass def post_save(self, request, new_object, form, formsets, change): """ Hook for doing any final logic after saving :param form: :param formsets: :param change: :return: """ pass ### def _changeform_view(self, request, object_id, form_url, extra_context): """ A copy of original django method with 4 tricks 1. Calls whole_changeform_validation 2. Calls pre_save() before saving 3. Calls post_save() after saving 4. emits the signal changeform_saved signal :param request: :param object_id: :param form_url: :param extra_context: :return: """ to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR)) if to_field and not self.to_field_allowed(request, to_field): raise DisallowedModelAdminToField( "The field %s cannot be referenced." % to_field) model = self.model opts = model._meta if request.method == 'POST' and '_saveasnew' in request.POST: object_id = None add = object_id is None if add: if not self.has_add_permission(request): raise PermissionDenied obj = None else: obj = self.get_object(request, unquote(object_id), to_field) if not self.has_view_or_change_permission(request, obj): raise PermissionDenied if obj is None: return self._get_obj_does_not_exist_redirect( request, opts, object_id) ModelForm = self.get_form(request, obj, change=not add) if request.method == 'POST': form = ModelForm(request.POST, request.FILES, instance=obj) form_validated = form.is_valid() if form_validated: new_object = self.save_form(request, form, change=not add) else: new_object = form.instance formsets, inline_instances = self._create_formsets(request, new_object, change=not add) if all_valid( formsets ) and form_validated and self.whole_changeform_validation( request, form, formsets, not add): self.pre_save(form, formsets, change=not add) self.save_model(request, new_object, form, not add) self.save_related(request, form, formsets, not add) self.post_save(request, new_object, form, formsets, not add) changeform_saved.send(self.model, instance=new_object, created=add) change_message = self.construct_change_message( request, form, formsets, add) if add: self.log_addition(request, new_object, change_message) return self.response_add(request, new_object) else: self.log_change(request, new_object, change_message) return self.response_change(request, new_object) else: form_validated = False else: if add: initial = self.get_changeform_initial_data(request) form = ModelForm(initial=initial) formsets, inline_instances = self._create_formsets( request, form.instance, change=False) else: form = ModelForm(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) if not add and not self.has_change_permission(request, obj): readonly_fields = flatten_fieldsets( self.get_fieldsets(request, obj)) else: readonly_fields = self.get_readonly_fields(request, obj) adminForm = helpers.AdminForm( form, list(self.get_fieldsets(request, obj)), # Clear prepopulated fields on a view-only form to avoid a crash. self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {}, readonly_fields, model_admin=self) media = self.media + adminForm.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: media = media + inline_formset.media if add: title = _('Add %s') elif self.has_change_permission(request, obj): title = _('Change %s') else: title = _('View %s') context = { **self.admin_site.each_context(request), 'title': title % opts.verbose_name, 'adminform': adminForm, 'object_id': object_id, 'original': obj, 'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, 'to_field': to_field, 'media': media, 'inline_admin_formsets': inline_formsets, 'errors': helpers.AdminErrorList(form, formsets), 'preserved_filters': self.get_preserved_filters(request), } # Hide the "Save" and "Save and continue" buttons if "Save as New" was # previously chosen to prevent the interface from getting confusing. if request.method == 'POST' and not form_validated and "_saveasnew" in request.POST: context['show_save'] = False context['show_save_and_continue'] = False # Use the change template instead of the add template. add = False context.update(extra_context or {}) return self.render_change_form(request, context, add=add, change=not add, obj=obj, form_url=form_url) def get_actions(self, request): actions = super(RaAdmin, self).get_actions(request) if not (app_settings.RA_ENABLE_ADMIN_DELETE_ALL and request.user.is_superuser): if 'delete_selected' in actions: del actions['delete_selected'] return actions def get_list_display(self, request): list_display = super(RaAdmin, self).get_list_display(request) if self.has_view_permission(request): list_display = ('get_stats_icon', ) + list_display return list_display
class InstanceProvisionTemplateForm(TemplateForm): service = forms.ModelChoiceField( label="OpenStack service", queryset=models.OpenStackService.objects.all(), required=False) flavor = forms.ModelChoiceField(label="Flavor", queryset=models.Flavor.objects.all(), required=False) image = forms.ModelChoiceField(label="Image", queryset=models.Image.objects.all(), required=False) data_volume_size = forms.IntegerField(label='Data volume size', required=False) system_volume_size = forms.IntegerField(label='System volume size', required=False) security_groups = forms.ModelMultipleChoiceField( models.SecurityGroup.objects.all().order_by('name'), label='Security groups', required=False, widget=FilteredSelectMultiple(verbose_name='Instance security groups', is_stacked=False)) user_data = forms.CharField(label='User data', widget=AdminTextareaWidget(), required=False) class Meta(TemplateForm.Meta): fields = TemplateForm.Meta.fields + ('service', 'project', 'flavor', 'image', 'data_volume_size', 'system_volume_size') class Serializer(BaseTemplateSerializer): service = serializers.HyperlinkedRelatedField( view_name='openstack-detail', queryset=models.OpenStackService.objects.all(), lookup_field='uuid', required=False, ) flavor = serializers.HyperlinkedRelatedField( view_name='openstack-flavor-detail', lookup_field='uuid', queryset=models.Flavor.objects.all(), required=False, ) image = serializers.HyperlinkedRelatedField( view_name='openstack-image-detail', lookup_field='uuid', queryset=models.Image.objects.all(), required=False, ) data_volume_size = serializers.IntegerField(required=False) system_volume_size = serializers.IntegerField(required=False) security_groups = serializers.ListField( child=NestedHyperlinkedRelatedField( view_name='openstack-sgp-detail', lookup_field='uuid', queryset=models.SecurityGroup.objects.all(), required=False)) user_data = serializers.CharField(required=False) @classmethod def get_serializer_class(cls): return cls.Serializer @classmethod def get_resource_model(cls): return models.Instance
class Meta: model = Post fields = "__all__" widgets = {"intro": AdminTextareaWidget(), "content": AdminTinyMCE()}
class FaqBaseModelAdmin(MultiSiteAdminMixin, TranslatableAdmin, PlaceholderFieldAdmin): """ Base admin for FAQ questions """ filter_site = appsettings.FLUENT_FAQ_FILTER_SITE_ID list_display = ('title', 'language_column', 'modification_date', 'actions_column') form = FaqBaseModelForm search_fields = ('translations__slug', 'translations__title') # Using fieldnames here works because formfield_for_dbfield() is overwritten. formfield_overrides = { 'meta_keywords': { 'widget': AdminTextInputWidget(attrs={'class': 'vLargeTextField'}) }, 'meta_description': { 'widget': AdminTextareaWidget(attrs={'rows': 3}) }, } FIELDSET_GENERAL = (None, { 'fields': ( 'title', 'slug', ), }) FIELDSET_SEO = (_('SEO settings'), { 'fields': ('meta_keywords', 'meta_description'), 'classes': ('collapse', ), }) FIELDSET_PUBLICATION = ( _('Publication settings'), { 'fields': ('order', ), #'classes': ('collapse',), }) fieldsets = ( FIELDSET_GENERAL, FIELDSET_SEO, FIELDSET_PUBLICATION, ) class Media: css = {'all': ('fluent_faq/admin/admin.css', )} def get_prepopulated_fields(self, request, obj=None): # Needed for django-parler return { 'slug': ('title', ), } def save_model(self, request, obj, form, change): # Automatically store the user in the author field. if not change: obj.author = request.user obj.save() def formfield_for_dbfield(self, db_field, **kwargs): """ Allow formfield_overrides to contain field names too. """ overrides = self.formfield_overrides.get(db_field.name) if overrides: kwargs.update(overrides) return super(FaqBaseModelAdmin, self).formfield_for_dbfield(db_field, **kwargs) def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): # When the page is accessed via a pagetype, warn that the node can't be previewed yet. context['preview_error'] = '' if 'fluent_pages' in settings.INSTALLED_APPS: from fluent_pages.urlresolvers import PageTypeNotMounted, MultipleReverseMatch try: self._reverse_faqpage_index(request, obj) except PageTypeNotMounted: from fluent_faq.pagetypes.faqpage.models import FaqPage context['preview_error'] = ugettext( "The {object_name} can't be previewed yet, a '{page_type_name}' page needs to be created first." ).format(object_name=self.model._meta.verbose_name, page_type_name=FaqPage._meta.verbose_name) except MultipleReverseMatch: # When 'faqquestion_index is ambiguous (because there are multiple FAQ nodes in the fluent-pages tree), # the edit page will automatically pick an option. pass except NoReverseMatch: # Since forgetting the pagetype app is easy, give off a warning to help developers # find their way with these apps. raise ImproperlyConfigured( "To use django-fluent-faq, either include('fluent_faq.urls') in the URLConf, " "or add the 'fluent_faq.pagetypes.faqpage' app to the INSTALLED_APPS." ) return super(FaqBaseModelAdmin, self).render_change_form(request, context, add, change, form_url, obj) def _reverse_faqpage_index(self, request, obj=None): # Internal method with "protected access" to handle translation differences. # This is only called when 'fluent_pages' is in the INSTALLED_APPS. return mixed_reverse('faqquestion_index') @classmethod def get_actions_column(cls, faqquestion): return mark_safe(u' '.join( conditional_escape(a) for a in cls._actions_column_icons(faqquestion))) @classmethod def _actions_column_icons(cls, object): actions = [] if cls.can_preview_object(object): try: url = object.get_absolute_url() except (NoReverseMatch, TranslationDoesNotExist): # A FaqQuestion is already added, but the URL can no longer be resolved. # This can either mean that urls.py is missing a 'fluent_faq.urls' (unlikely), # or that this is a PageTypeNotMounted exception because the "FAQ page" node was removed. # In the second case, the edit page should still be reachable, and the "view on site" link will give an alert. pass else: actions.append( mark_safe( u'<a href="{url}" title="{title}" target="_blank"><img src="{static}fluent_faq/img/admin/world.gif" width="16" height="16" alt="{title}" /></a>' .format(url=url, title=_('View on site'), static=settings.STATIC_URL))) return actions @classmethod def can_preview_object(cls, object): """ Override whether the node can be previewed. """ #return hasattr(faqquestion, 'get_absolute_url') and faqquestion.is_published return True def actions_column(self, faqquestion): return self.get_actions_column(faqquestion) actions_column.allow_tags = True actions_column.short_description = _('Actions')
class ContactFormPlugin(ContentPlugin): """ Plugin to render and process a contact form. """ model = ContactFormItem form = ContactFormItemForm category = _("Media") render_template = "fluentcms_contactform/forms/{style}.html" render_ignore_item_language = True cache_output = False submit_button_name = "contact{pk}_submit" formfield_overrides = { "success_message": { "widget": AdminTextareaWidget(attrs={"rows": 4}) } } def get_render_template(self, request, instance, **kwargs): """ Support different templates based on the ``form_style``. """ return [ self.render_template.format(style=instance.form_style), self.render_template.format(style="base"), ] def render(self, request, instance, **kwargs): """ Render the plugin, process the form. """ # Allow multiple forms at the same page. prefix = f"contact{instance.pk}" submit_button_name = self.submit_button_name.format(pk=instance.pk) session_data_key = f"contact{instance.pk}_submitted" # Base context context = self.get_context(request, instance, **kwargs) context["submit_button_name"] = submit_button_name context["completed"] = False ContactForm = instance.get_form_class() if request.method == "POST": if submit_button_name in request.POST or "contactform_submit" in request.POST: form = ContactForm(request.POST, request.FILES, user=request.user, prefix=prefix) else: form = ContactForm(initial=request.POST, user=request.user, prefix=prefix) if form.is_valid(): # Submit the email, save the data in the database. form.submit(request, instance.email_to, style=instance.form_style) # Request a redirect. # Use the session temporary so results are shown at the next GET call. # TODO: offer option to redirect to a different page. request.session[session_data_key] = True return self.redirect(request.path) else: form = ContactForm(user=request.user, prefix=prefix) # Show completed message if request.session.get(session_data_key): del request.session[session_data_key] context["completed"] = True if hasattr(form, "helper") and form.helper.inputs: # Hacky, when using crispy layouts, make sure the button name is set. # In case this fails, the code above also checks for the general 'contactform_submit' name. submit_buttons = [ input for input in form.helper.inputs if isinstance(input, SubmitButton) ] if submit_buttons: submit_buttons[0].name = submit_button_name context["form"] = form template = self.get_render_template(request, instance, **kwargs) return self.render_to_string(request, template, context)
def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name == "internal_note": kwargs["widget"] = AdminTextareaWidget(attrs={"rows": 4}) return super().formfield_for_dbfield(db_field, **kwargs)
def __init__(self, *args, **kwargs): super(HTMLBlockAdminForm, self).__init__(*args, **kwargs) self.fields['text'].widget = AdminTextareaWidget()