Django how does Django know which formset is which - python

Assuming I have a model that directly correspond to a ModelFormset.
Assuming three instances of the model are saved in the database.
Assuming I loaded the ModelFormset with initial data = the three instances
Now I render the ModelFormset on a page for users to modify.
After modification, users click on submit. How do I know which one of the ModelFormset correspond to which instance of the Model saved in the database?
Update:
I was reading this example: https://docs.djangoproject.com/en/1.9/topics/forms/formsets/#formsets-initial-data
In this example, the initial data was provide manually. Assuming if the the initial data was passed in like this:
article = Article.objects.get(pk=...)
formset = ArticleFormSet(initial=[
model_to_dict(article)
])
When this formset is sent to the template, is article's id preserved in the rendered HTML? If not, then how does Django know which article it should update if modifications to the article has been made and submitted?

If you have an existing instance in ModelForm (or in a set of them inside ModelFormset), then there's a hidden field with the value of the primary key for the record.
Each ModelForm has also a unique suffix for each the field, which helps distinguish which fields belongs to the same model.

Related

How to know which field is saved when only() has been used in Django?

I am using Django 1.11, in one of my models I have added actions when the model is saved.
However I don't want these actions to be done when only a part of the model is saved.
I know that update_fields=('some_field',) can be used to specify which field must be saved.
But, when the object has been fetched in the database using the methods only() or defer() I don't see any information about the fields updated in the save() method, update_fields is empty.
Thus my question: How can I get the fields saved by Django when only some fields have been fetched ?
When you use defer or only to load an instance, the get_deferred_fields() method returns a list of field names that have not been loaded; you should be able to use this to work out which ones will be saved.

Passing a model instance, not __unicode__ method in django

I've got a django form that contains a join via a foreign key. This is a foreign key to a very large table. On the form, to prevent loading up a massive select that tends to crash browsers, I've got a jQuery autocomplete, which on each keystroke sends off the entered text. This text is then searched in the table and suitable results are returned to be displayed. The id is then passed to a hidden CharField when one is selected. This hidden CharField is the widget for the ForeignKey relation. When I try to save the form, I get an error that I need to be passing a model instance for the related model, which is fair enough. I can't work out how to do this however. I can take that id and do a model.objects.get(pk=id_from_form), but if I replace the POST data with the result of this, I still get an error as I'm just passing the __unicode__ method of the model. I'm sure there's something I'm missing, but I can't see what it is.
Thanks.
Instead of using a CharField to store the id, try using a ModelChoiceField with the widget set as a HiddenInput. The field definition in your form would look something like:
mymodel = forms.ModelChoiceField(widget=forms.HiddenInput, queryset=MyModel.objects.all())

Generating custom forms from DB schema

I am a current web2py user, but find I still go back to Django once in a while (where I started). Specifically when working on projects where I want to make use of some specific django apps/plugins/extensions that don't yet exist in web2py.
One thing that I can't live without in web2py, which I am looking for a solution for in Django, is the way to create html forms from a db table and being able to then customize their look and layout in the view, without javascript.
Key things I am looking for:
Generate html form from a db table
Assign custom css classes/ids to each field in the generated html form (js disabled)
Place each form field/element in a pre-made html view via a method call in the view
i.e.
I have a table A. In web2py I can do (in controller):
def display_form():
form = SQLFORM(db.table_A)
#Can I do the following in Django? Assign custom CSS to each form field?
form.element(_name='email')['_class'] = = "custom_css_classes, list"
if form.accepts(request.vars, session):
response.flash = 'form accepted'
elif form.errors:
response.flash = 'form has errors'
else:
response.flash = 'please fill out the form'
return dict(form=form)
Then, in the View I can do:
form.custom.start
form.custom.widget.name
form.custom.widget.email
form.custom.widget.form_field_name
...
<div class="span-5 last"><input type="submit" class="register_btn" value="Sign Up"></input></div>
form.custom.end
The above takes a DB table, creates an HTML form, and then lets me stick each separate form field in any place in the pre-made HTML that I want (using those "custom" method calls on the passed "form" object. Including the custom css classes I assigned to each separate field of the generated html form.
See documentation for details on the above code:
http://web2py.com/book/default/chapter/06?search=define_table
http://web2py.com/book/default/chapter/07?search=sqlform#SQLFORM
http://web2py.com/book/default/chapter/05?search=#Server-side-DOM-and-Parsing
http://web2py.com/book/default/chapter/07?search=form.custom
How do I do the above in Django without dirtying my javascript with layout hacks. Assume javascript is disabled in the browsers where I need my app to run. Furthermore, I would love to make use of Django admin. Pylons solutions also welcome!
Links to articles/tutorials/howtos for this would be greatly appreciated.
Also, please make an equivalent result of the above code using the method you mention in your response...
Use ModelForm and override any field you wanna customize by explicitly declaring them.
If you want to set field attributes like class and id, you need to do something like this:
name = forms.CharField(
widget=forms.TextInput(attrs={'class':'special'}))
In case you are interested, you may change the order of the fields by specifying a fields sequence in your Meta class:
class Meta:
model = YourModel
fields = ('title', 'content')
You may read the full documentation here:
http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.attrs
If you haven't already, take a look at Django's ModelForm. I am assuming that you have models mapped to the tables in question. Vanilla ModelForm instances will work without JS. However ModelForms are usually defined ahead of time and not constructed on the fly. I suppose they can be created on the fly but that would be a bit tricky.

Django best practice for displaying mostly read-only form, one field writeable

I have a requirement where one user creates an 'instance' of an object via a ModelForm. Another user of a different group has access to read all of the fields of the form, but has to update only one field. Think of a student who creates an exam object. Then a teach pulls up the exam and just needs to put in a grade, the rest of the exam is read only.
What's the best way to do that? Should I just query for the object, and display each field individually, then create a form (not a ModelForm?) for just the one field?
Should I just query for the object, and display each field individually, then create a form (not a ModelForm?) for just the one field?
This is probably the best way to go about it. Note you can use a ModelForm for the teacher form, see the Django documentation on using a subset of fields on a model form. You will have to display all the other fields manually in your template, but you should probably have a separate template for this view (I would use separate views as well).
You could find some code for a read only field on Django Snippets, but generally it's better to be explicit about what fields you are updating from each view. This is likely to be more trouble than it's worth.

Form Validation in Admin with Inline formset and Model form

I have a model, OrderedList, which is intended to be a listing of content objects ordered by the user. The OrderedList has several attributes, including a site which it belongs to.
The content objects are attached to it via an OrderedListRow class, which is brought into OrderedList's admin via an inline formset in the admin.
class OrderedList(GenericList):
objects = models.Manager()
published = GenericListManager()
class OrderedListRow(models.Model):
list = models.ForeignKey(OrderedList)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveSmallIntegerField()
content_object = generic.GenericForeignKey("content_type", "object_id")
order = models.IntegerField('order', blank = True, null = True)
(OrderedList inherits the site field from the larger GenericList abstract).
Here's my problem; when the user saves the admin form, I want to verify that each content object mapped to by each OrderedListRow belongs to the same site that the OrderedList does (the list can only belong to 1 site; the content objects can belong to multiple).
I can override OrderedList's admin form's clean(), but it doesn't include the inline formset which contains the OrderedListRows, so it can't reach that data. I can override the OrderedListRows' inline formset's clean, but it can't reach the list. I need some way within the context of form validation to reach both the OrderedList's form data and the formset's form data so I can check all the sites of the OrderedListRow's content objects against the site of the OrderedList, and throw a validation error if there's a problem. So far I haven't found a function that the cleaned data for both OrderedRow and the OrderedListRows are contained in.
In the inline formset, self.instance should refer to the parent object, ie the OrderedList.
I am dealing with the same issue. And unfortunately I don't think the answer above covers things entirely.
If there are changes in both the inline formset and the admin form, accessing self.instance will not give accurate data, since you will base the validation on the database and then save the formset which overwrites that data you just used to validate things. Basically this makes your validation one save behind.
I suppose the real question here is which gets saved first. After digging int he source code, it seems like the admin site saved the form first. This means that, logically, doing validation on the formset and from there accessing the 'parent' instance should get consistent values.

Categories

Resources