Django: How to return model formset in ajax and us

2019-05-26 07:18发布

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!!

2条回答
干净又极端
2楼-- · 2019-05-26 07:26

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.

查看更多
劳资没心,怎么记你
3楼-- · 2019-05-26 07:37

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.

# models.py
class Book(models.Model):
    title = models.CharField(max_length=64)
    author = models.CharField(max_length=64)
    isbn = models.CharField(max_length=64)

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.

# urls.py
urlpattern('',
    url(r'^book/(?P<id>\d+)/$', views.book),
)

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 view book which will know what to do. Additionally Django will pass the book id to the view.

# views.py
def book(request, id):
    # get the book
    book = get_object_or_404(Book, pk=id)
    context = {
        'book': book
    }
    return render_to_response('book_template.html', context)

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 this context dictionary and use values inside of it in order to fill in some placeholders inside the template.

# book_template.html
<html>
<head>...</head>
<body>
   <h1>{{ book.title }}</h1>
   <p>Author: {{ book.author }}</p>
   <p>ISBN: {{ book.isbn }}</p>
</body>
</html>

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).

查看更多
登录 后发表回答