I have this "PageModel" on my website and want to use modeladmin to add/edit them in a sperate menu.
from cities.models import City
class City(Page):
cityobject = models.ForeignKey(City, on_delete=models.SET_NULL, null=True, blank=True)
streamfield = StreamField(BasicStreamBlock, null=True, blank=True)
content_panels = Page.content_panels + [
FieldPanel('cityobject', classname="full"),
StreamFieldPanel('streamfield'),
]
I also use this approach for a multilingual website:
http://docs.wagtail.io/en/v1.13.1/advanced_topics/i18n/duplicate_tree.html
What I want is within wagtail admin to have a button "Cities" beside the explorer to add cities. But before I add them, I would like to select for which website. For example:
Cities -> EN -> London
Cities -> DE -> Berlin
How can I do this?
If you register a ModelAdmin class for a page type that can exist in more than one part of the tree, when you use the 'Add' button at the top of the listing to add a new page, you should be prompted automatically to choose a parent for it (before being presented with the page editor interface).
The behaviour actually changes depending on the logged-in user's permissions. For example, if the user can add pages to any part of the tree, then they would be prompted to choose what the parent page should be. But, for a user with limited permissions, who might only be able to add pages to one of the possible parents - the one possible option would be identified automatically, and the user wouldn't be prompted.
EDIT:
If you want to add additional menu items to the menu in the Wagtail admin area, you might want to consider using a ModelAdminGroup class for your app instead, and overriding the get_submenu_items method to append custom MenuItem instances to the list before returning. If you can copy the URL pattern used on the 'Add' button at the top of the listing, you should get the same conditional 'Choose a parent' functionality as described above.
If you haven't used the ModelAdminGroup class before, an example of use can be found in the docs: http://docs.wagtail.io/en/latest/reference/contrib/modeladmin/#a-more-complicated-example
Related
I have reviewed the question on Is there any way to show a field on a listing page in Wagtail admin? but my situation seems to similar but also different enough that that particular solution won't work for me. Instead of on the Page listing I wish to achieve a similar thing on the Model Admin listing and I would think this should be such a common requirement that I am picking that someone must have done this before I have attempted it.
I haven't really figured out how to even try anything to get started but what I have looked at is the modeladmin template tags under wagtail.contrib.modeladmin on GitHub but I am completely guessing.
Can anyone point me to which templates I need to modify and whether I need to modify any of the template tags and how to override anything I need to override?
There's no need to override templates for this - this is standard functionality in ModelAdmin. Adding extra fields to the listing is done by setting list_display on the ModelAdmin class:
class BookAdmin(ModelAdmin):
model = Book
list_display = ('title', 'author')
For displaying images, ModelAdmin provides ThumbnailMixin:
from wagtail.contrib.modeladmin.mixins import ThumbnailMixin
from wagtail.contrib.modeladmin.options import ModelAdmin
class BookAdmin(ThumbnailMixin, ModelAdmin):
model = Book
thumb_image_field_name = 'cover_image'
list_display = ('title', 'author', 'admin_thumb')
('admin_thumb' is a special-purpose field name provided by ThumbnailMixin, and should be used rather than the actual image field on your model - cover_image in this example.)
I need a complex selection widget because there are a lot of options in a multiple select widget. But I see HeavySelect2MultipleWidget needs views and urls to use it. I think there is not possible it in Wagtail by default.
This is the code:
class Resource(Page):
authors = ParentalManyToManyField('Authors', blank=True)
content_panels = Page.content_panels + [
FieldPanel('authors', widget=forms.CheckboxSelectMultiple)
]
It would be nice to use
FieldPanel('authors', widget=HeavySelect2MultipleWidget)
but it raises a
You must ether specify "data_view" or "data_url".
According to the Django-Select2 documentation you have to initiate (call) the widget with the attributes first.
As the error says - data_url or data_view has not been provided to the widget.
It will be up to you to generate that view or url specific to your use case. You could override the serve method of your page model to serve the data and provide the appropriate url pattern or simply create a different view altogether as documented here (see Heavy Components section).
For example:
FieldPanel(
'authors',
widget=HeavySelect2MultipleWidget(
data_url='url/to/json/resonse'
)
)
HeavySelect2MultipleWidget extends HeavySelect2Widget - see docs for more detail:
http://django-select2.readthedocs.io/en/latest/django_select2.html#django_select2.forms.HeavySelect2Widget
I have not used this specific widget but have used Django-Select2 in Wagtail in a similar set up and it has worked well.
I've been using wagtail-modeladmin to create custom lists of certain page types. That gives me the ability to edit those pages. But I'd also like to be able to click through somehow to the "normal" admin explorer version of those pages, and be able to view/add child pages to them.
essentially giving myself a column with the little arrows in on the right, just like in the normal wagtail admin page explorer...
OK I know it's bad form to answer your own question, but I've got this working by using a custom method on the model admin object that reverse wagtails admin urls:
class MySpecialPageModelAdmin(ModelAdmin):
def view_children(self, obj):
url = reverse('wagtailadmin_explore', args=[obj.id])
return format_html(f'View Children')
list_display = ('title', 'live', 'view_children')
but actually, I think I'm not going to end up using this, just replacing this particular modeladmin with a direct link to the right place in the explorer.
I'm not sure if this is possible at all but this is what I want to acheive:
The website I am working on for a martial arts school.I have program pages that give general info on them. Then I have a link that says 'register to view available times' (for a free trial).
I am wondering how to get the user to the specific page for that program's registration. After that, I want to apply the same sort of thing to each program page. E.g. If I am on kids classes > Register > Redirect to Kids Class Times
Womens > Register > Redirect to Women's Class Times.
Also, want the same thing to happen for a 'login' function.
Joomla natively does not support this. You will have to use a third party extension to achieve this. I have used Community Builder (https://www.joomlapolis.com/) before that is both free and open-source that can do what you want.
If i understood your question you like to put some content in to view only for person who is registered on your website.
Here is how to.
1. Create menu item in menu manager >
Add content to your menu. ( modules , articles ) > .
Set the same menu item from Public to Registered.
Button to do so, will be on right side tab: " Details " in menu setting.
2.Then you create a link to these menu or item alias which is public. When the person will click on link the joomla will ask for login and redirect to the menu page.
Hope this helps.
I have a single page application with AngularJs and Django. On my main page, I get all the forms needed when loading the page. BUT, some fields are dynamically updated.
Let's say I have
class Model1(models.Model):
pass
class Model2(models.Model):
model_1 = models.ForeignKey(Model1)
forms:
class Model2Form(forms.ModelForm):
class Meta:
model = Model2
fields = ('model_1', )
My SPA allows me to create instances of Model1 (without reloading the page). I know how to filter the options shown and dynamically add the new instances in the select field BUT, doing so, when the html is first rendered, before angular magic takes place and filter the available options, I get the queryset made by django which is by default model.objects.all(). All right, I'd like to display none of that. I tried to add in the init of my function:
self.fields['model_1'].queryset = Model1.objects.none()
and indeed no option is displayed in the select field when the form is first rendered but then, I can't validate my form, I get the error: Select a valid choice. That choice is not one of the available choices. (obviously, it had no option available due to the queryset.none() )
I'd really like not to load forms when called but doing it when my page first load. Is there any option to help me do so?
Cheers guyz,
Keep rocking
You need to specify that the model_1 field of Model2 can be null, as specified here:
Allow null in foreign key to user. Django
model_1 = models.ForeignKey(Model1, null=True, blank=True, default = None)
I find out how to handle that problem. It is quite stupid, I did not give you all the parameters of the problem.
The forms are rendered on load but when I validate it, it goes through a CRUD operation and an OTHER form is initialized at this point which will handle the data I'm sending. So I can override the queryset in the init of that (second) form based on some extra kwargs to differentiate between the form I'm using for the first rendering and the form to handle my data.
No need to make any field nullable or add extra validation.
Hope I'm clear enough. Cheers