I need to dynamically add forms to my formset during runtime using ajax, for which I am referring to Dynamically adding a form to a Django formset with Ajax
I have multiple formsets on the same page with different prefixes.
My models are designed like so: A user can have many phones. A phone can have many lines (if details are needed) Accessing Many to Many "through" relation fields in Formsets
Once a user adds a new phone, I save the phone using ajax. The view is as follows
def addUserPhone(request, customer_id, location_id, user_id, **kwargs):
error_msg = u"No POST data sent."
context = {}
if request.is_ajax():
if request.method == "POST":
user = End_User.objects.get(id=user_id)
phone_client = PartialPhone_ClientForm(request.POST, prefix='new_client')
instance = phone_client.save()
#associate user to a phone
instance.end_user.add(user)
#Creating an empty lineFormset for a phone
LineFormSet = modelformset_factory(Line, form=Line_Form, can_delete=True)
client_lines = LineFormSet(queryset=Line.objects.none(), prefix='phone_client_'+str(instance.id))
# how to return the two objects instance and client_lines back to the template??
#format = 'json'
#mimetype = 'application/javascript'
#data = serializers.serialize(format, [instance])
#return HttpResponse(data)
#can we return as a context?? this gives me only a string "phoneline_set" in the template
context['phone'] = instance
context['line_set'] = client_lines
return HttpResponse(context)
else:
error_msg = u"Insufficient POST data (need 'Name ' and 'Telephone Number'!)"
else:
error_msg = "Non Ajax"
return HttpResponseServerError(error_msg)
What is the best way to now return the phone instance, and LineFormSet back to the view for rendering in the template??
If I just return a context, my view gets only string "phoneline_set". But I want to do something like
$.post("addUserPhone/",phoneData,function(data){
$('.scroll').append("<h2> {{ line_set }} </h2>")
});
If I serialize using Json and pass how can I pass the LineFormSet and use it in template? Currently if I try to serialize my client_lines formset I get the error AttributeError: 'LineFormFormSet' object has no attribute '_meta'
Any help is appreciated, Thanks!!
You don't send the context as the Ajax response, you send a rendered template fragment using that context. The template should just be the HTML containing the form that you want to insert into your div.
Just elaborating on Daniel's answer as requested in the comment.
Django is an MVC style framework. Models are used in order to store and access data. In Django controllers are called views, which have a job of getting a request from a user with a certain URL, get some data which might be associated with the url, and then push that data throught some tempalte which will use the data view gave it in order to fill in the placeholders inside of the template.
Here is a simple example which explains all the aspects. Imagine that there is a web site which has a database of books. So your model would store information relevant to each book - Title, Author, ISBN number, etc.
Now you want to add a URL
example.com/book/<id>/
which will display all of the information about the book with specified id. For that to happen, couple of things need to happen. First Django controller has to catch the url with this pattern. You specify the url pattern in the urls.py file.Since
urls.py
specify a mapping between url patterns and views, that tells Django that whenever user goes to a URL with the specified pattern, Django has to give the request to the viewbook
which will know what to do. Additionally Django will pass the book id to the view.So inside of the view, given the ID of the book, it uses models in order to look up the book from the database, and it case it is not found, it returns 404 error to the user. Then it populates a dictionary which I called
context
with some values which it will pass to the template. The job of the template is to take thiscontext
dictionary and use values inside of it in order to fill in some placeholders inside the template.So the template will take the context from the view and then use the
book
inside of the context in order to fill in the values inside{{ }}
.In your case you are trying to return a context to the user which does not make much sense. What you have to do is create a template which will take the that context
{ 'phone': instance, 'line_set': client_lines }
and according to it, will render some HTML which will be returned to the user. And that HTML you can pull using AJAX and then use it however you need it.Hopefully this clarifies some concepts for you.
Django documentation is excellent so I would recomment to also read the intro. It will explain all of the syntax and some of the shortcuts I have used in this answer (render_to_response, etc).