Wagtail Page create via model_mommy - wagtail

I'm trying to create some tests for my first Django site. One thing that is burdensome is creating example pages for testing (at least you have to specify a lot of parameters and some (such as ContentType) are not always obvious. More generally, I'd like to use Model Mommy to create many of the objects I need.
Near as I can tell, it can't create an instance of a Page (claiming that a "Page matching query does not exist"). [the test case is a simple import of Page and Model Mommy then create an instance of a page].
I'm not sure if this is properly an issue for Wagtail or for Model Mommy, but debugging it is getting a bit out of my depth and it would be very useful if it could work.
Unless there is something obvious I'm missing or can/should do, I'm posting this more to flag the problem than to try to get a solution right now.
Thx,
--Don

Mommy doesn't handle Django Tree Beard relations. Tree Beard is the package used by Wagtail to create the page tree.
Mommy doesn't create the tree structure correctly. You should add your pages to the tree yourself. You can do this with add_child.
Root is created by the Wagtail migrations: https://github.com/wagtail/wagtail/blob/master/wagtail/core/migrations/0002_initial_data.py#L13-L38
There is no need to set the content type manually if you use your specific class directly. I used FooPage in the example below.
from wagtail.wagtailcore.models import Page
from app.models import FooPage
root = Page.objects.get(slug='root')
page = FooPage(title='Example', ...)
root.add_child(instance=page)

Related

Add column heading (and corresponding property) to Wagtail index view

My team and I have created a section to allow our company to add landing pages. We'd like to include some additional columns to the index view of the associated model, as illustrated in this image.
I've found a few old posts (2014-ish) that indicate this wasn't possible, but I can't find anything newer that makes that claim invalid. Is it possible to do this, and if so can someone point me in the right direction?
If you are willing to patch the view and template for the Page Explorer, you should be able to do this. My group isn't patching the Page Explorer so I don't have example code for that but our general approach is as follows:
We have a django app called wagtail_patches which is listed in our INSTALLED_APPS before the wagtail apps.
In wagtail_patches/apps.py we have:
from django.apps import AppConfig
class WagtailPatchesConfig(AppConfig):
name = 'wagtail_patches'
verbose_name = 'Wagtail Patches'
ready_is_done = False
def ready(self):
"""
This function runs as soon as the app is loaded. It executes our monkey patches to various parts of Wagtail
that change it to support our architecture of fully separated tenants.
"""
# As suggested by the Django docs, we need to make absolutely certain that this code runs only once.
if not self.ready_is_done:
# The act of performing this import executes all the code in monkey_patches.
from . import monkey_patches
# Unlike monkey_patches, the code of wagtail_hook_patches is in the function patch_hooks().
from .wagtail_hook_patches import patch_hooks
patch_hooks()
self.ready_is_done = True
else:
print("{}.ready() executed more than once! This method's code is skipped on subsequent runs.".format(
self.__class__.__name__
))
Then in wagtail_patches/monkey_patches.py we import the module to be patched, then write a new method, and then replace the stock version with the new method. For example:
from wagtail.admin.forms.collections import CollectionForm
def collection_form_clean_name(self):
if <weird custom condition>:
raise ValidationError('some error message')
CollectionForm.clean_name = collection_form_clean_name
Overriding templates is just like normal django template overriding, place your customized version of some file in a folder hierarchy matching it's usual position within Wagtail.
You can do this with ModelAdmin for a specific model, but it won't appear in the Pages Explorer view as in your screenshot. Instead, it will appear in a new menu item on the left sidebar. I also find that Hooks is a great place to store this logic. Just be aware of how ModelAdmin differs from modeladmin. The Bakery Demo has some good examples of how this all works.

Injecting snippets into a Wagtail StreamField interface

My company is using Wagtail to build robust pages for our website, likely using the StreamField component. We're wondering if Wagtail allows the possibility of us creating reusable parts (perhaps in a snippet), and injecting them into a page.
I'm including a simple diagram of what I'd like to do. Note that while snippets are one possible suggestion, it doesn't need to the specific solution.
The goal of course is to create an element which can be embedded in another page, but can be updated in a single place and cascade everywhere it's used.
Wordpress for example, has a plugin which offers this functionality in short code format:
[embed id=123456]
You can create new block for stream field, let's say MySnippetBlock and then use SnippetChooserBlock to choose the snippet you want.
MySnippetBlock(StructBlock):
title = CharBlock()
snippet = SnippetChooserBlock()
Then in your StreamBlock field you can use above custom block:
MyPage(Page):
stream_field_content = StreamField([('snippet_block', MySnippetBlock())])
...
Or you can use SnippetChooserBlock directly within StreamField if there is no need for additional info attached to it.
stream_field_content = StreamField([('snippet_block', SnippetChooserBlock())])

Create Landing Page in Drupal 7

In Drupal one can basically style the elements, like the search box, or the basic page etc. and then put some content in the site and the resulting page will be generated. But what if you want one specific site (e.g. the index page) to be different? E.g. have a image as a background, a different navigation styling etc.
What's the best paractice way of doing this?
Best practice is to have a different theme which you can switch to by using hook_custom_theme() where you check the current path. Also make sure that your theme to switch to is enabled:
/**
* Implements hook_custom_theme().
*/
function YOUR_MODULE_custom_theme() {
# check path with arg(0)
# return theme name to switch to
return 'different_theme_machine_name';
}
Alternatively you can also try ThemeKey doing this out of the box with an interface & allowing you the specify rules.
If you need to change only the content(body) section of your page, use Disply Suite. You can create unique look and feel layouts for your body section of each page.
If you trying to change the complete layout of one page (eg: Services), Create new Content Type 'Services'. Then create a template file for this content type, You must name this template call page--services.tpl.php. And also you can overwrite the index page layout by creating page--front.tpl.php template. Done!
What you are saying you want to change is all styling. And you know you can do a page to look drastically different with CSS... and you can do it that way depending on your chosen Drupal theme.
Now, with the Chrome Inspector (or FF inspector) look at the body tag, it probably has many classes which indicates in what page you are, what type of node (if it's a node) or if it's an admin section, or an anonymous user.
Using those specific classes you can style a frontpage, or a view, or a node, or anything, without installing more modules... with some limitations because you can't change rendered HTML this way.
Finally, don't get scared by using modules in Drupal, it's how Drupal works and it works pretty well. The thing is to install the best tools to increase your productivity, and Drupal have excellent options to change your theming and content like Display Suite (like #BaikHo suggested).
Hope that helps.
PD: Using the less module and with custom your theme you can have LESS css which is considerably faster than using only CSS, and because it's integrated with Drupal you can theme make everything even faster. Give it a try.

Drupal taxonomy views override path for specific content

I am beginning to be a little desperate here. I have following structure (Drupal 7):
I use taxonomy menu to build menu links,
The taxonomy_term default (page) view is used to override drupal's taxonomy/term/% path
In addition to it I use menu_block module (but I doubt that this is important). What I am trying to achieve:
I need to build node browser by category (taxonomy term) but it has exceptions - for example taxonomy term with id 850 (taxonomy/term/850) must have different content structure than other therms. Is it possible to override default views display with these exceptions? I tryied to create another display with this path but the result was "not found". I also thought on using blocks not page displays, yet this solutions does not seem to be the Drupal way to me.
I was facing the same problem while trying to have different display/structure for publications in contrast to normal articles.
What I did, created a separate view for that specific taxonomy such as taxonomy/term/850, and in the path in view I entered 'taxonomy/term/850' (in this case)
This caused it override taxonomy/term/%
and displayed it differently according to my need.

Drupal: D7 rewriting values returned by views

I have a requirement to perform an indexed search across content which must include a couple of tags in the result. The tags must be a random selection. The platform is Drupal 7.12
I have created a view that manages the results of a SOLR search through the search_api. The view returns the required content and seems to work as intended. I have included a couple of Global: custom text fields as placeholders for the tag entries.
I am now looking for a solution to manage the requirement to randomise the tag values. The randomisation is not the issue, the issue is how to include the random values into the view result.
My current approach is to write a views_pre_render hook to intercept the placeholders which appear as fields ([nothing] and [nothing_1]). The test code looks like the following
function MODULE_views_pre_render( &$view )
{
$view_display = $view->display['default'];
$display_option = $view_display->display_options;
$fields = $display_option['fields'];
foreach( $view->result as $result )
{
$fields['nothing']['alter']['text'] = sprintf("test %d", rand(1,9));
}
}
I am currently not seeing any change in the placeholder when the view is rendered.
Any pointers to approach, alternate solutions etc would be gratefully received as this is consuming a lot of scarce time at the moment. Calling print_r( $view ) from within the hook dumps over 46M into a log file for a result set of 2 items.
There are two possible solutions for your task.
First approach is do everything on the template level. Define a template for the view field you want to randomize. In advanced settings of your display go to Theme: Information. Make sure that the proper theme is selected and find the template suggestions for your field. They are listed starting from most general to the most specific and you can choose whatever suits you better.
I guess the most specific template suggestion for your field would be something like this: views-view-field--[YOR VIEW NAME]--[YOUR DISPLAY NAME]--nothing.tpl.php. Create the file with that name in the theme templates directory and in this template you can render what ever you want.
By default this template has only one line:
print $output;
you can change this to:
print sprintf("test %d", rand(1,9));
or to anything else, whatsoever :)
Second approach is to go with Views PHP module. WIth this module you can add a custom PHP field in which you can do whatever you want. Even though the module hasn't been released it seems to work quite well for the most of the tasks and most certainly for such a simple task as randomizing numbers it will work out for sure.
I stumbled upon this while searching for another issue and thought I would contribute.
Instead of adding another module or modifying a template, just add a views "sort criteria" of "Global: Random".

Resources