Wagtail page model: foreign key entity + multiple parameters - django

i'm using Wagtail CMS to create product catalogue. I created basic page type for product:
class Product(Page):
It has basic fields like title, description, image aso. But i need "something special":
There is special part available in many variants and each product can have some of them. So I created another model, very simple by:
#register_snippet
class Variant(models.Model):
to store all variants. Variant has name and image. There are about 200 products and 30 variants.
My problem is and I don't know how to manage in Wagtail two tasks:
to link Product with Variants (foreign key) with many-to-many relation to select product related variants in same page as other page entities
each relations has additional parameters (2 params) which are relation specific (material and diameter) and again I haven't found how to display and manage such relations in page editor
I know that Django can handle it by inline formsets (django admin supports it out of box), but is there Wagtail-way to get this done and editable by Wagtail editor? I prefer to manage whole product in the same place, not relations separated in django-admin.
Thanks for any help or advice.

InlinePanel is the Wagtail equivalent of Django admin's inline formsets. An example of this is given in Wagtail's tutorial: https://docs.wagtail.io/en/stable/getting_started/tutorial.html#images
In this case, it's setting up a many-to-many relation between pages and images, with an additional parameter (caption) on the relation; your Product -> Variant relation could be set up in the same way.

Related

Where is ID saved in django ModelAdmin autocomplete_fields?

I am rewriting some administration interface to django 2.2, currently using django autocomplete_fields admin feature. Simply said I have ModelAdmin object OrderAdmin, which has nested TabularInline ProductAdmin: variable-length table of products which might be added to order. Each of these ProductAdmin holders just contains ForeignKey to actual product class, with some other attributes.
Now I wonder: where does django store id - ForeignKey - of item selected with autocomplete field? It doesn't mark OPTION in selectbox as selected, and although there is suspicious hidden input field with #cashregisterproduct_set-0-id on page, it doesn't have any value. Or is there some special way how to access it? I was thinking about adding id to __str__ method of model and parsing, but thats just ugly.
Thanks for tip.
EDIT: to make it 100% clear, where from does django get ForeignKey of object selected through autoselect_field, when creating new object from ModelAdmin?
I got misguided thinking that this is managed by django. Selected data might be accessed by using select2 framework:
selected_value = $('.myselectbox').select2().val();
related: https://stackoverflow.com/a/47451658/16268461

Django ManyToManyField order is not being kept

I have two models: Customer and Resources. Customer has a ManyToManyField to Resources. I add the relations from the admin panel e.g.:
Customer_1 -> Resource_8, Resource_5, Resource_14
The main problem is that I want to insert these relationships in that exact order: resource 8, 5 and 14. But when the admin form is submitted, it saves the relations as follows:
Customer_1 -> Resource_5, Resource_8, Resource_14
I assume that it is ordering the resources by its ID and not respecting the order they were submitted.
My question is, how do I change this behaviour, so that it always respect the order which was submitted on the admin site?
Django doesn't support ordering in M2M fields, you will need to alter the way your model is defined, specifically you will need to create a through table and use a custom ordering field for it.

In what situations are Django formsets used?

I am a beginner with Django. In what situations are Django formsets used? (In real applications.)
Please give some examples.
According to the documentation:
A formset is a layer of abstraction to working with multiple forms on the same page. It can be best compared to a data grid.
So any time you want to have multiple instances of a particular form displayed on a page for creation or updating. An example of this might be a Phonebook. Each Form is a single entry in the phonebook, but a Formset of Phonbook forms will allow you to create or edit multiple entries in one go.
One case is when ModelA have a foreign key to ModelB. you can say that one ModelB has many ModelA, so lets say that ModelB is a Invoice and ModelA is the ProductItem, one invoice has one or many product items.
In the practice now you can make a basic formset like that: http://help.mailchimp.com/img/addafieldoption.jpg where you can add more product items to a invoice.

django admin inlines (and nested inlines) : how can I get this functionality?

I'm a little confused as to why this sort of functionality isn't default in the admin, but maybe someone can give me a few hinters to how to go about it.
I have a projects application which keeps track of projects and is to be edited through the admin. Each project has numerous ForeignKey related models (links, flatpages, video, image etc.) that could be placed as inlines within the project admin.
(One or two models have nested inlines, so they don't display in the admin (this and this ticket deal with this) )
Instead of being able to edit these models inline on the project admin (which gets messy and difficult to use), I would love a list of all the current instances of that related model, and simple add/edit button for each model which opens a popup with that model's form.
Project Admin:
- Normal Fields
- Links:
-Link 1 (edit)
-Link 2 (edit)
+ add link <- popup
- Images:
-Image 1 (edit)
-Image 2 (edit)
+ add image <- popup
so on. How would I go about writing this? I only need to do it for one section/model of the admin panel so I don't think writing my own Crud backend is necessary.
Thanks
I implemented something like this in an application once, but since django-admin doesnt support nested inlines (by which i mean inlines within inlines), i followed a slightly different approach. The use case was that you had an invoice (with a few inline attributes) and u had reciepts (again with inline attributes). Reciepts had a foreign key to the invoice model (basically a reciept was part payment of the invoice).
I implemented it by adding a field to the invoice list view which linked to a filtered reciept list view.
So in the invoice admin, there would be:
def admin_view_receipts(self, object):
url = urlresolvers.reverse('admin:invoice_%s_changelist'%'receipt')
params = urllib.urlencode({'invoice__id__exact': object.id})
return 'Receipts' % (url, params)
admin_view_receipts.allow_tags = True
admin_view_receipts.short_description = 'Receipts'
This gives you a link in the list view that takes you to another list view, but filtered by foreignkey. Now you can have inlines for both models and easy access to the related models.

django admin hierarchical inline model edit

Consider a wiki application. There is a model Page, that has many Revisions and each revision has many blocks.
What is the simplest way to create an admin in which, you select a page and all the blocks of the latest revision appear; bonus points for letting change of revision by a dropdown (which is by default, sorted in reverse order anyway)
Is it absolutely necessary to create views, or can I extend some of those StackedInline forms, override save and mention some magic meta options, to get it all done automagically.
Have you tried something like this (in admin.py):
class RevInline(admin.TabularInline):
model = Revision
class PageAdmin(admin.ModelAdmin):
model = Page
inlines = (RevInline,)
admin.site.register(Page, PageAdmin)