adding django admin many-to-many widget - django

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.

Related

How to create separate form widgets for ModelMultipleChoiceField in Django

I have a ManyToMany relationship between two Django Models: Team and Member. A single Member can be part of multiple teams. I am able to successfully bind a Form class to a CreateView, and, using the standard ModelMultipleChoiceField,can successfully save the Form using the save_m2m method.
However, the default widget for the field is not suitable for my user experience. Instead of using a picklist, I would like to create a separate select box for each number of selectable Members per team. For example, if the Team can have 7 Members, I would like to show 7 select boxes, rather than one pick list that a user selects 7 different objects from.
I understand I may not get a complete answer, but would appreciate any pointers on if I should be looking into overriding the Field with a custom MultiWidget, or if using an inline formset might be a more appropriate route. Or, something else...
At the end of the day, I ultimately decided to stick with a single ModelForm for the Create Team form. Within this ModelForm, I dynamically create the number of fields I will need for the number of Member per team, and have created a function within the form that yields those fields.
I perform validation on those fields within the generic clean method of the ModelForm. I use the yield method within the Template to control displaying the individual fields.
I am sure it is not the most Django-y approach, as many people seem to use inlineformsets in theory, but this worked and the code does not seem overly hacky or unmaintainable.

How can one best mark a model field as required in Django?

In Django, I would like the ability to mark certain model fields as required at the model (or at least database) level, to make sure that I am specifying them explicitly (i.e. not relying on defaults) when creating objects.
Currently, Django lets you designate a model field as required at the forms level (by specifying blank=False in the model). However, it doesn't seem like there is a similar option to get this behavior at the model or database level.
It does seem like there are various hacks to achieve something similar though. For example, you can set the default to something that violates a database constraint. For example, you can do things like:
models.CharField(_('characters'), max_length=4, default=None)
or
models.CharField(_('characters'), max_length=4, default="abcdef")
The former example works when saving to the database since None violates the default not-null constraint of null=False (raising an IntegrityError). The latter works because a DataError is raised when saving. But I don't know if this is guaranteed to work across all databases, etc.
Am I missing something, or is there a better way?
If django models called full_clean() automatically on save(), your check would run at the model level without a form. I've been playing with making this the default behavior in my django projects by creating an auto-clean model subclass which does full_clean() on save(), then deriving my models off that.
If you want to learn why it isn't already like this: Why doesn't django's model.save() call full_clean()?

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/

Enforce at least one value in a many-to-many relation, in Django?

I have have a many-to-many relation in a Django(1.4) model.
class UserProfile(models.Model):
foos = models.ManyToManyField(Foo)
I want to enforce that each User(Profile) has at least one Foo. Foos can have zero-or-more User(Profiles)s.
I would love this to be enforced at the model and admin levels, but just enforcing it in the admin would be sufficient.
If I understand correctly, 'many' in Django-speak is zero-or-more.
I want a ManyToOneOrMore relation. How can I do this?
Thanks,
Chris.
You can't enforce this on at the model level as #Greg details, but you can enforce it on a form by simply making the field required. This won't prevent anyone with shell-level access from manually creating a UserProfile without a foo, but it will force anyone using a browser-based form method of creation.
Unfortunately, I don't think this is possible at the model level because ManyToMany data is saved separately from other model fields. You should be able to enforce it at the admin level by specifying a custom form, and writing a clean() method on the form.

Django Model field as formfield in templates

I guess this is a simple question, but I am not being able to find a definitive answer whether this is possible or not.
I have a Model object that is being passed to my template during rendering. While I use most of the Model fields to show their values, I came across a need to show a few of them as formfields (with their respective HTML element like rendered via ModelForms). Can ModelForm class usage be avoided here and simply use the Model's field to be rendered as formfield directly from template?
an example:
class MyModel(models.Model):
month = models.PositiveIntegerField(_('Month'), choices=MONTH_CHOICES)
year = models.PositiveIntegerField(_('Year'))
Now in template based on the above Model example I want to show the year as a value but month as a dropdown with selected current value?
Any pointer appreciated!
Use case:
Imagine a generic list_view like case where you are rendering a queryset. What you have there is object per iteration, however on the list view you want to allow your users to perform some quick editing of few object attributes to avoid forcing them to go to full edit mode (maybe via simple ajax).
No.
As canvassed in the comments, this is not possible. A model, and its fields do not know about forms - that is what forms, and modelforms are for.
The right way to do this is to wrap your model objects with a modelform, which you can adjust (using inheritance) to do whatever you want with the non-form fields, if you wish to make this more transparent.
Creating modelforms in the template means that you have nowhere to process the forms in django. Apparently you want to interface them with some kind of ajax interface, so perhaps this is not a problem for you, but in any case, I fail to see how it would be easier than simply creating the modelforms in the view.