I have a model with default values defined. When a model is created as an inline in the administration backend and the default values remain unchanged, the model doesn't save, but if any field is altered, then the model will save.
I havent overridden any save or clean methods on the model or form.
Is this expected behavior?
The problem here is that Django is trying to see which inlines you actually want to save. As the docs put it: "The formset is smart enough to ignore extra forms that were not changed." So if you use all default values it thinks you're not using those inlines.
You could try using empty_permitted as described in this answer, although I don't think it's officially documented. You'll also have to be careful that the initial formset only includes (via extra) the minimum number of inlines you require.
Related
I'm adding a per-user secret key to one of my Django models for internal usage, but I want to make sure that it is not accidentally exposed to the user. Obviously, I can check all the forms using that model today and ensure that they exclude the field, but that is not future proof. Is there any way I can mark a field so it is never rendered or sent to the client even if a form otherwise includes it?
You could use editable=False on your Model field as documented and here
If False, the field will not be displayed in the admin or any other
ModelForm. They are also skipped during model validation. Default is
True.
Note this works for ModelForms and if you are using regular Form you might consider extending it with custom implementation
ModelForm editable removal implementation source
I was just looking the documentation to be able to change the intermediate table but when I implement it, I get into trouble:
https://docs.djangoproject.com/en/2.0/topics/db/models/#extra-fields-on-many-to-many-relationships
The problem as such is that, although I can migrate the database and run the application, when I enter the administrator I do not visualize correctly the relationship of my models through the trough attribute (especially a field of my model called Tested).
Why does this happen and how can it be corrected?
This is by design. Django cannot automatically generate the widget for ManyToMany relations that use a through table because of the extra data needed (tested in your case). From Django docs:
When you specify an intermediary model using the through argument to a ManyToManyField, the admin will not display a widget by default. This is because each instance of that intermediary model requires more information than could be displayed in a single widget, and the layout required for multiple widgets will vary depending on the intermediate model.
However, we still want to be able to edit that information inline. Fortunately, this is easy to do with inline admin models.
Your best bet is to create an inline admin model as explained in the docs.
I'm working on a django project with a legacy DB, using formset to edit a set of rows. There are fields in that DB that I don't want django to update, although I need them in my model. In other words, I want them to be treated as READ-ONLY fields.
Thus, I was happy to read the documentation on saving model formsets, which states:
"When fields are missing from the form (for example because they have
been excluded), these fields will not be set by the save() method. You
can find more information about this restriction, which also holds for
regular ModelForms, in Selecting the fields to use."
https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#saving-objects-in-the-formset
Indeed, when forms.model.BaseModelForm.save() is invoked, it calls forms.model.save_instance(), nicely passing in all the form fields. BUT than then calls instance.save() WITHOUT passing along the update_fields!! And so ALL the model fields are included in the update query :-(
As a test, I modified forms.model.save_instance() to pass the fields:
instance.save(update_fields=fields)
and voila - the model only saves fields listed by its form.
I'm hoping someone more involved in the django project can tell me if this a bug, or a documentation issue? Should I submit a bug report? Am I missing something - is there some other way I should be enforcing "read only" on those fields?
Using django1.8 and python3.4
I'm not sure why you think this behaviour contradicts that documentation, or why it would need to pass along the fields to update. The instance already has the unchanged data; Django will update the rest of the fields from the form, and save the whole thing.
Just curious. What is the best practice for when to use form vs model validation?
From what I understand currently, form validation should be used for:
AJAX / HTTP requests params
Forms that do not correlate to a model?
Another question is: I have a HTML form that roughly correlates to a model instance, do I use a ModelForm for it?
Definitely use ModelForm, if your form resembles model object even in a tiny bit.
If there are some minor differences (e.g. you don't use some of the fields or you want to use different error messages etc.) it's much easier to customize ModelForm then to use Form and implement all this functionality from scratch.
For more reference regarding ModelForm please checkout PyDanny's Core Concepts of Django ModelForms.
I am also trying to understand what is the difference/relation between form and model validation and I would like to share my notes that are formed after reading several docs.
I am currently interested in Creating Forms from Models
#mariodev shared the document Core Concepts of Django ModelForms and this provided a good start.
ModelForms select validators based off of Model field definitions
The main story behind the scenes seems to be the DRY principal. This article explains very well what exactly is the case here.
All right, all this is fair. The question is "Where in the Django Documentation is this explained"?
I bumped on a very brilliant article where it states that:
The form.full_clean() method is called by django at the start of the validation process (by form.is_valid(), usually immediately after the view receives the posted data).
Correct me if I am wrong but that line reads that everytime I enter data and hit 'enter' the validation process begins!
OK, this is simple now:
The validation on a ModelForm begins when we hit 'enter'.
Django first validates the form by checking one by one every applicable validation method on Fields, Field Subclasses (This is the documentation for a model's field subclass, not for a form field subclass), Form Subclasses and ModelForm (since it is a ModelForm).
Finally, it validates the Model Instance.
This is how all this works theoretically. The only thing that remains is to implement it.
Django: what approaches are there to 'parametising' the display and editability of form fields.
I have several forms where I want some fields to be simply missing from the form display (dependent on the current user) and some fields to be uneditable, depending on the user.
This needs to be enforced on the server, so that a malicious user cannot break the security by manually constructing a post request with the missing parameter.
Likewise fields which are not displayed to the user, must still come back in the form results, so that fields which are not displayed to a user and not 'wiped-out' when the model is written back to the DB.
I also need to solve the same hiding problem for templates.
The app will have dozens of forms, with different immutability/hiding requirements, so this needs to be a generic system. Coding permissions inside each form would be too prone to error.
Any help appreciated.
Chris.
For hidding fields from form display, simple delete unneeded fields in form's __init__ method. Constructing post request by adding deleted fields, will not have influence on the form.
Regarding disabled or readonly fields, check this article and another question. Basically, cleaning field should set it to initial state.