Adding multiple model objects at a time in the Django admin - django

I would like to allow my django admin users to add multiple objects at a time for one of my models in addition to the one-object-at-a-time standard approach used by the django admin.
I am considering modifying the change_form.html template for the model so that it uses a formset (as suggested here) -- although I am not sure how to implement this yet.
Note that I am not adding multiple child objects so I cannot use inlines for this.
What is the best way to approach this?

Related

how can i replicate admin.TabularInline outside of the admin (on the user side?)

Given a mode A and a model B that has a field with a many to many relationship with model A, I am trying to allow users creating an object of model B to also create an object of model A inline/on-the-fly just like TabularInline allows you to do on the admin.
This is a very common problem and the solution is not trivial (at least for the moment). Django admin uses Javascript(jQuery) to do this task. Multiplication of a form requires lots of altering values and IDs etc. But recently people started doing this with htmx. The way it is done is explained in this article from JustDjango thoroughly. There is even a video tutorial about it. I personally like the way they do it. You can give it a try. It feels and looks like in the django admin. If you would like to do it purely in django, you can look up formset_factory

Django. Many forms have OneToOne to one specific model. Forms should always be saved with these relations. How to implement efficiently?

I have many models (Customer, Seller, Product etc.), each of them has a set of images (Gallery, OneToOne relationship).
Also, some models (Customer, Seller, Moderator, Administrator) has OneToOne with User that is used for storing credentials.
I want to create and update these related models together.
Of course, simplest way is to use a class-based view and override get, post and form_valid methods. But there are many models having Gallery and User and I intend to follow DRY and code reuse principles and not to alter each view in same way.
Ideally, solution is sophisticated form (or form set) and using of standard class-based views without method overriding. Other option is different form and class-based view mixin.
I thought few hours about mixins but didn't came up with solution. Now I'm trying to do something with some kind of form sets.
In the case of the gallery is recommended to create an app only for that purpose.
On the case of the user the implementation Here's my recommendation:
1 - Create a base User class with all the core functionality your looking for.
2 - Extend the User class for all the other cases with the functionality your looking for.

Creating Model Relationships Via Forms

What is the defacto way of creating model relationships in Django via frontend forms.
For example a user signs up for service using a form, they start a quote.
In getting a quote they can select and add products to their quote specifying variable such as sizes in this process.
This is modelled with relevant User, Quote, Product models and relevant relationships.
I am trying to work out the best way that these are linked together by frontend forms and views.
Would I load into the quote form a hidden field for the related user_id for example, which I can then process manually to form the one-to-many relationship.
I am just wondering if this is something accounted for within forms or if I have to manually create the forms to achieve my goal.
This is one of the more complicated things to try and achieve but there are several things in Django which will help you.
You're going to need a ManyToMany field on the Quote model to link the Products to it.
This can be displayed in forms simply via a ModelMultipleChoiceField:
https://docs.djangoproject.com/en/dev/ref/forms/fields/#modelmultiplechoicefield
... which is just renders a basic multiple select list of existing products.
The interface you want probably looks more like an inline formset however. The complication here is that they are designed for ForeignKey relations rather than ManyToMany.
Under the covers, a ManyToMany relation is actually just two ForeignKey relations, via an intermediate 'through' model. We can exploit this to build an inline formset on the through model, see this answer:
https://stackoverflow.com/a/10999074/202168
You'll note the caveat in that answer, the inline rows won't know which Quote they belong to unless you override some code.
You may like to look at some helper apps which provide custom widgets for ManyToMany fields:
https://code.google.com/p/django-ajax-filtered-fields/
http://django-autocomplete-light.readthedocs.org/en/latest/

Can I make Django admin reflect a hierarchy of models?

Assume a Django application with a few models connected by one-to-many relationships:
class Blog(models.Model):
...
class Post(models.Model):
blog = models.ForeignKey(Blog)
...
class Comment(models.Model):
post = models.ForeignKey(Post)
...
Conceptually, they form a hierarchy, a tree-like structure. I want the Django admin to reflect that. In particular:
in a changelist of posts, every post should have a link to the changelist of corresponding comments;
similarly, a post’s edit page should link to the changelist of comments from the top-right buttons area;
when I open that list of related comments, it needs to reflect the relationship in the breadcrumbs (something like: Posts › “Hello world” › Comments) and, ideally, also in the URL (post/123/comment/).
This should of course also apply to the other levels of the hierarchy.
Number 1 is pretty easy with a custom list_display entry and using the ?post__id= query to the comments changelist. But this is little more than a hack. Generally Django assumes my three models to be independent, top-level entities.
Is there a straightforward way to accomplish this? I guess I could override a bunch of templates and AdminModel methods, but perhaps there is a better solution for what seems like a common situation?
Are you sure you are not just looking at Django Admin Inline Models ?
There is no way that an automated admin will pick up your relationships, because in an RDBS there can be any number of foreign keys / one to one / many to many relations, and Django does not have a customized hierarchical behavior built in.
You can indeed edit the breadcrumb customizing an admin template if you want.
For relations you might also be interested into django MPTT that allows to make hierarchical model instances. Also see this question: Creating efficient database queries for hierarchical models (django) in that respect.
How is this a common situation? Consider the fact a model can have a virtually unlimited number of foreign key relationships, let alone visa versa. How would the admin 'know' how to represent this data the way a user requires without customizing things?
One would suggest you are used to work with content management systems rather than webframeworks (no pun intended). It's important to notice Django isn't a cms, but a webframework you can built on top of as you see fit. In a nutshell: 'Django is rather clueless and unaware of contextual requirements'.
Although the admin is quite a beast out-of-the-box, it can be hard to customize. There have been quite some discussions whether it should even be part of core. I can only suggest, if customizing things tends to get hacky, you should probably write your own 'admin', it's not that hard.

adding django admin many-to-many widget

In the django admin documentation, it says the following:
By default, admin widgets for many-to-many relations will be displayed on whichever model contains the actual reference to the ManyToManyField.
Is there a way to get a similar widget to appear on the admin page for the other model, the one where the relationship isn't defined?
There's a couple different ways to get the effect that you're after.
Here's one way, which will get you a similar (but not identical) effect, and probably requires the least coding. (Examples will use classes A and B, assuming that the former has the many to many relationship explicitly defined)
The quickest way: you can use an InlineModelAdmin object:
class AInline(admin.TabularInline):
model = A
class BAdmin(admin.ModelAdmin):
inlines = (AInline,)
admin.site.register(B, BAdmin)
If you want the exact effect of getting a <select multiple>, the way you can do it is to use a custom Form class, and assign it to BAdmin.form.