When I render the empty form it is not attaching any media to it. i.e. the CKEditor is not displayed. The element looks like it is missing the css/js - it's like it doesn't get set up properly.
Note : the other sections are displayed correctly.
Where to start? Problem with Django's Empty Form method? Problem with CKEditor? Me :)
<div class="container">
<button type ="button" class="btn-info btn-lg" id="add_section">Add Section</button>
{{form.media }}
{{form|crispy }}
{{sections.media}}
<div>
{{sections.empty_form}}
</div>
<div id = 'section_management'> {{ sections.management_form }} </div>
{% for section in sections %}
{{ section|crispy }}
{% endfor %}
<button class="btn btn-info ml-2" type="submit">Update</button>
Cancel
</div>
Here's my Forms
class SectionForm(forms.ModelForm):
content = RichTextFormField()
class Meta:
model = Section
fields = ('content',)
empty_permitted=True
def __init__(self, *args, **kwargs):
print('section form called')
super().__init__(*args, **kwargs)
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ('title','category','span')
def __init__(self, *args, **kwargs):
self.is_superuser = kwargs.pop('is_superuser', None)
super().__init__(*args, **kwargs)
if self.is_superuser == False:
self.fields.pop("span")
view code
class ArticleUpdateView(LoginRequiredMixin,UserPassesTestMixin,UpdateView):
template_name = 'articles/ArticleUpdate.html'
form_class = ArticleForm
model = Article
SectionFormSet = inlineformset_factory(Article, Section, form=SectionForm, extra=0, can_delete=False, fields=('content',))
#if i always pass back at least 1 extra section form, I can grab the html for it in Jquery */
#if i do not pass back extra=0 how would i get the html in jquery for the extra form?
def test_func(self):
article = self.get_object()
if self.request.user == article.author or self.request.user.is_superuser :
return True
else:
return False
def get_context_data(self, **kwargs):
print('get context data called update view')
'''
section_form
'''
context = super().get_context_data(**kwargs)
if self.request.POST:
context['sections'] = self.SectionFormSet(self.request.POST,instance=self.object)
else:
context['sections'] = self.SectionFormSet(instance=self.object)
return context
def get_section_form(self): #we know we can access this in the template
return SectionForm()
def save_sections(self):
print('save sections called update view')
try:
context = self.get_context_data()
section_form = context['sections']
if section_form.is_valid():
# section_form.instance = self.object #if im passing instance in the factory, do I need it here to?
section_form.save()
except Exception as e:
print('failed to save section: ' + str(e))
def form_valid(self, form):
print('form valid called update view')
form.instance.author = self.request.user
response = super().form_valid(form) #save article form
self.save_sections()
return response
def get_success_url(self):
return reverse_lazy('index')
Basically, what I've done so far to overcome this problem is by accessing the form directly from the template, bypassing the inlineFormSet to get an empty form....(hope that makes sense).
I go directly to the view :
{{view.get_section_form}}
with this method in the view
def get_section_form(self): #we know we can access this in the template
return SectionForm()
I have subsequently found out I can do this in the template as well :
{{sections.media}}
{{sections.form}}
The above also passes an empty form - with the media filled in- as long as you pass the model form into the factory to start of with.
These are work-arounds for me currently, but would appreciate a proper answer as to why empty_form doesn't work properly.
My further investigation into this was basically comparing what is returned via accessing the formset to return an empty form, or using the modelForm directly.
Django docs :
empty_form¶
BaseFormSet provides an additional attribute empty_form which returns a form instance with a prefix of __prefix__ for easier use in dynamic forms with JavaScript.
If you replace prefix on the generated html -- everything works. No idea why. You can replace it with anything, i.e. prefix1
at which point CKEditor starts to display the formset correctly.
I created three files:
2- view.py :
class AddTeamView(View):
def get (self, request):
form = TeamForm()
context = {'form': form}
return render(request, 'add_team.html', context)
1-forms.py:
class TeamForm(forms.Form):
name = forms.CharField( max_length='100')
details = forms.CharField(max_length='250')
3-add_team.html:
-here there is another file called "base.html"
{% extends 'base.html' %}
{% block title %}
add team
{% endblock %}
{% block content %}
<form action="/add_team/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
{% endblock %}
and i went to cmd and entered the server "python manage.py runserver"
it appeared on the browser:
"This page isn’t working
If the problem continues, contact the site owner.
HTTP ERROR 405"
A view can support methods like GET, POST, PUT, etc. given the corresponding method exists, so the view should have a .get(..), .post(..), .put(..), etc. function.
Here you only implemented a def get(self, request), and so POST requests are not allowed.
Based on the data you however show, this looks like the typical usecase of a CreateView [Django-doc]. The idea of these views is to encapsulate common scenario's such that by overriding a few attributes, one creates a view that is tailored towards a specific case, like:
class AddTeamView(CreateView):
form_class = TeamForm
template_name = 'add_team.html'
success_url = '/some/success_url'
The TeamForm should probably be a ModelForm, or at least a Form where you override the .save(..) function to properly save your data to the database, since right now, the form is not doing anything (well it receives the data, but after validation, it throws it away).
You might want to override the form_valid(..) function in case you do not want to redirect to the success_url. Furthermore it is very common that the success_url is resolved lazily from a given view name, like:
class AddTeamView(CreateView):
form_class = TeamForm
template_name = 'add_team.html'
success_url = reverse_lazy('view_name')
So, we don’t need to do a conditional to check if the request is a POST or if it’s a GET:
Your views.py:
from django.views.generic import View
class AddTeamView(View):
def post(self, request):
form = TeamForm(request.POST)
if form.is_valid():
new_tm = TeamModel(name=form.cleaned_data['name'], details=form.cleaned_data['details'])
new_tm.save()
return redirect('team_list')
return render(request, 'add_team.html', {'form': form})
def get(self, request):
form = TeamForm()
return render(request, 'add_team.html', {'form': form})
Hope this help you...
I've been struggling with class views all day after starting on them yesterday. My issue is constantly getting 'str' object has no attribute 'visible_fields', so the 'form' item below is not really a form:
template-
<form action="" method="post">
{% csrf_token %}
{{form|bootstrap}}
<input type="submit" name="submit" value="Add new article"/>
</form>
view-
class ArticleCreateView(CreateView):
model = Article
template_name = 'index/add_article.html'
form_class = ArticleForm
def post(self, request, *args, **kwargs):
article_form = self.get_form()
if article_form.is_valid():
article = article_form.save(commit=False)
title = article_form.cleaned_data['title']
url = article_form.cleaned_data['url']
title = process_title(url)
article.title = title
article.save()
return redirect("index:article_list")
else:
form = ArticleForm()
print type(form)
print dir(self)
return render(request, 'index/add_article.html')
The worst part is printing type(form) shows it is <class 'index.forms.ArticleForm'>. I'm trying to just have it redirect to the list view if the form saved, and replay the form with the error (You already have an article with that URL) if the form is bad. I heard class views are easier to work with and huge projects I've read through use them, but they really seem worse than the old views. I assume that's because I'm not using them well
Every example I've seen has a template getting a "form" somehow, like
class RangeCreateView(CreateView):
model = Range
template_name = 'dashboard/ranges/range_form.html'
form_class = RangeForm
def get_success_url(self):
if 'action' in self.request.POST:
return reverse('dashboard:range-products',
kwargs={'pk': self.object.id})
else:
msg = render_to_string(
'dashboard/ranges/messages/range_saved.html',
{'range': self.object})
messages.success(self.request, msg, extra_tags='safe noicon')
return reverse('dashboard:range-list')
def get_context_data(self, **kwargs):
ctx = super(RangeCreateView, self).get_context_data(**kwargs)
ctx['title'] = _("Create range")
return ctx
then like magic in range_form.html:
{% include "dashboard/partials/form_fields.html" with form=form %}
My issue here is I need to process the title of the form, with
def process_title(url):
def _search_for_title(url):
try:
r = requests.get(url)
content = r.text
t = html.document_fromstring(content)
return t.find(".//title").text
except IOError:
return None
title = _search_for_title(url)
return title or 'None'
This kind of ruins the purpose of a class based view. It seems I should be processing the title by overriding 'clean' in the form itself?
Otherwise, how can I make this view pass a form object, render it in the template, and just re-render the template if the form didn't pass?
And how can I access the form in the template?
Thank you
You do it by following the example view, rather than overriding post instead as you are doing.
In your case, simply displaying and processing a form is the default behaviour of a CreateView. So there is no need to override any methods at all. Your view should just be:
class ArticleCreateView(CreateView):
model = Article
template_name = 'index/add_article.html'
form_class = ArticleForm
i have a listview of form:
class MatchsView(ListView):
model = Match2x1
template_name = 'matchs.html'
and the template render this:
{% for match in object_list %}
<form action="/apostar/" method="post">{% csrf_token %}
<p><input type="radio" name="{{match.id}}" value="{{match.team_a}}">{{match.team_a}}</input></p>
<input type="submit" value="Apostar"></input>
</form>
{% endfor %}
as you can see each form has two fields, i need to save in DB the values that the user choose, with FormView its easy, but since this time is a ListView im a little bit lose to save in DB from a form, i know that i have to create a view that handles the form, but really i dont know how to create the view that handles the post data of each form. For example lets says that i need to save the post data in a model called FormsMatchs, how can i do it?
i was trying with this:
class FormView(FormView):
form_class = FormMatch
success_url = '/'
template_name = 'matchs.html'
def post(self, request, *args, **kwargs):
hola = Country.objects.create(name=request.POST)
but is saving this:
<QueryDict: {u'csrfmiddlewaretoken': [u'tCIQuGlSXKJL0R5eo9R5w09ldeBt7zNW'], u'5': [u'River']}>
Your best bet if you want to have a simple list of a given model but also accept a Form is to use a FormView, and override get_context_data(self, **kwargs) to pass a queryset into the context, like so:
def get_context_data(self, **kwargs):
context = super(MatchsView, self).get_context_data()
context['object_list'] = Match2x1.objects.all()
return context
However, you can also use a FormMixin with a ListView, see an example here.
I have a template page expecting two forms. If I just use one form, things are fine as in this typical example:
if request.method == 'POST':
form = AuthorForm(request.POST,)
if form.is_valid():
form.save()
# do something.
else:
form = AuthorForm()
If I want to work with multiple forms however, how do I let the view know that I'm submitting only one of the forms and not the other (i.e. it's still request.POST but I only want to process the form for which the submit happened)?
This is the solution based on the answer where expectedphrase and bannedphrase are the names of the submit buttons for the different forms and expectedphraseform and bannedphraseform are the forms.
if request.method == 'POST':
if 'bannedphrase' in request.POST:
bannedphraseform = BannedPhraseForm(request.POST, prefix='banned')
if bannedphraseform.is_valid():
bannedphraseform.save()
expectedphraseform = ExpectedPhraseForm(prefix='expected')
elif 'expectedphrase' in request.POST:
expectedphraseform = ExpectedPhraseForm(request.POST, prefix='expected')
if expectedphraseform.is_valid():
expectedphraseform.save()
bannedphraseform = BannedPhraseForm(prefix='banned')
else:
bannedphraseform = BannedPhraseForm(prefix='banned')
expectedphraseform = ExpectedPhraseForm(prefix='expected')
You have a few options:
Put different URLs in the action for the two forms. Then you'll have two different view functions to deal with the two different forms.
Read the submit button values from the POST data. You can tell which submit button was clicked: How can I build multiple submit buttons django form?
A method for future reference is something like this. bannedphraseform is the first form and expectedphraseform is the second. If the first one is hit, the second one is skipped (which is a reasonable assumption in this case):
if request.method == 'POST':
bannedphraseform = BannedPhraseForm(request.POST, prefix='banned')
if bannedphraseform.is_valid():
bannedphraseform.save()
else:
bannedphraseform = BannedPhraseForm(prefix='banned')
if request.method == 'POST' and not bannedphraseform.is_valid():
expectedphraseform = ExpectedPhraseForm(request.POST, prefix='expected')
bannedphraseform = BannedPhraseForm(prefix='banned')
if expectedphraseform.is_valid():
expectedphraseform.save()
else:
expectedphraseform = ExpectedPhraseForm(prefix='expected')
I needed multiple forms that are independently validated on the same page. The key concepts I was missing were 1) using the form prefix for the submit button name and 2) an unbounded form does not trigger validation. If it helps anyone else, here is my simplified example of two forms AForm and BForm using TemplateView based on the answers by #adam-nelson and #daniel-sokolowski and comment by #zeraien (https://stackoverflow.com/a/17303480/2680349):
# views.py
def _get_form(request, formcls, prefix):
data = request.POST if prefix in request.POST else None
return formcls(data, prefix=prefix)
class MyView(TemplateView):
template_name = 'mytemplate.html'
def get(self, request, *args, **kwargs):
return self.render_to_response({'aform': AForm(prefix='aform_pre'), 'bform': BForm(prefix='bform_pre')})
def post(self, request, *args, **kwargs):
aform = _get_form(request, AForm, 'aform_pre')
bform = _get_form(request, BForm, 'bform_pre')
if aform.is_bound and aform.is_valid():
# Process aform and render response
elif bform.is_bound and bform.is_valid():
# Process bform and render response
return self.render_to_response({'aform': aform, 'bform': bform})
# mytemplate.html
<form action="" method="post">
{% csrf_token %}
{{ aform.as_p }}
<input type="submit" name="{{aform.prefix}}" value="Submit" />
{{ bform.as_p }}
<input type="submit" name="{{bform.prefix}}" value="Submit" />
</form>
Wanted to share my solution where Django Forms are not being used.
I have multiple form elements on a single page and I want to use a single view to manage all the POST requests from all the forms.
What I've done is I have introduced an invisible input tag so that I can pass a parameter to the views to check which form has been submitted.
<form method="post" id="formOne">
{% csrf_token %}
<input type="hidden" name="form_type" value="formOne">
.....
</form>
.....
<form method="post" id="formTwo">
{% csrf_token %}
<input type="hidden" name="form_type" value="formTwo">
....
</form>
views.py
def handlemultipleforms(request, template="handle/multiple_forms.html"):
"""
Handle Multiple <form></form> elements
"""
if request.method == 'POST':
if request.POST.get("form_type") == 'formOne':
#Handle Elements from first Form
elif request.POST.get("form_type") == 'formTwo':
#Handle Elements from second Form
Django's class based views provide a generic FormView but for all intents and purposes it is designed to only handle one form.
One way to handle multiple forms with same target action url using Django's generic views is to extend the 'TemplateView' as shown below; I use this approach often enough that I have made it into an Eclipse IDE template.
class NegotiationGroupMultifacetedView(TemplateView):
### TemplateResponseMixin
template_name = 'offers/offer_detail.html'
### ContextMixin
def get_context_data(self, **kwargs):
""" Adds extra content to our template """
context = super(NegotiationGroupDetailView, self).get_context_data(**kwargs)
...
context['negotiation_bid_form'] = NegotiationBidForm(
prefix='NegotiationBidForm',
...
# Multiple 'submit' button paths should be handled in form's .save()/clean()
data = self.request.POST if bool(set(['NegotiationBidForm-submit-counter-bid',
'NegotiationBidForm-submit-approve-bid',
'NegotiationBidForm-submit-decline-further-bids']).intersection(
self.request.POST)) else None,
)
context['offer_attachment_form'] = NegotiationAttachmentForm(
prefix='NegotiationAttachment',
...
data = self.request.POST if 'NegotiationAttachment-submit' in self.request.POST else None,
files = self.request.FILES if 'NegotiationAttachment-submit' in self.request.POST else None
)
context['offer_contact_form'] = NegotiationContactForm()
return context
### NegotiationGroupDetailView
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
if context['negotiation_bid_form'].is_valid():
instance = context['negotiation_bid_form'].save()
messages.success(request, 'Your offer bid #{0} has been submitted.'.format(instance.pk))
elif context['offer_attachment_form'].is_valid():
instance = context['offer_attachment_form'].save()
messages.success(request, 'Your offer attachment #{0} has been submitted.'.format(instance.pk))
# advise of any errors
else
messages.error('Error(s) encountered during form processing, please review below and re-submit')
return self.render_to_response(context)
The html template is to the following effect:
...
<form id='offer_negotiation_form' class="content-form" action='./' enctype="multipart/form-data" method="post" accept-charset="utf-8">
{% csrf_token %}
{{ negotiation_bid_form.as_p }}
...
<input type="submit" name="{{ negotiation_bid_form.prefix }}-submit-counter-bid"
title="Submit a counter bid"
value="Counter Bid" />
</form>
...
<form id='offer-attachment-form' class="content-form" action='./' enctype="multipart/form-data" method="post" accept-charset="utf-8">
{% csrf_token %}
{{ offer_attachment_form.as_p }}
<input name="{{ offer_attachment_form.prefix }}-submit" type="submit" value="Submit" />
</form>
...
This is a bit late, but this is the best solution I found. You make a look-up dictionary for the form name and its class, you also have to add an attribute to identify the form, and in your views you have to add it as a hidden field, with the form.formlabel.
# form holder
form_holder = {
'majeur': {
'class': FormClass1,
},
'majsoft': {
'class': FormClass2,
},
'tiers1': {
'class': FormClass3,
},
'tiers2': {
'class': FormClass4,
},
'tiers3': {
'class': FormClass5,
},
'tiers4': {
'class': FormClass6,
},
}
for key in form_holder.keys():
# If the key is the same as the formlabel, we should use the posted data
if request.POST.get('formlabel', None) == key:
# Get the form and initate it with the sent data
form = form_holder.get(key).get('class')(
data=request.POST
)
# Validate the form
if form.is_valid():
# Correct data entries
messages.info(request, _(u"Configuration validée."))
if form.save():
# Save succeeded
messages.success(
request,
_(u"Données enregistrées avec succès.")
)
else:
# Save failed
messages.warning(
request,
_(u"Un problème est survenu pendant l'enregistrement "
u"des données, merci de réessayer plus tard.")
)
else:
# Form is not valid, show feedback to the user
messages.error(
request,
_(u"Merci de corriger les erreurs suivantes.")
)
else:
# Just initiate the form without data
form = form_holder.get(key).get('class')(key)()
# Add the attribute for the name
setattr(form, 'formlabel', key)
# Append it to the tempalte variable that will hold all the forms
forms.append(form)
I hope this will help in the future.
view:
class AddProductView(generic.TemplateView):
template_name = 'manager/add_product.html'
def get(self, request, *args, **kwargs):
form = ProductForm(self.request.GET or None, prefix="sch")
sub_form = ImageForm(self.request.GET or None, prefix="loc")
context = super(AddProductView, self).get_context_data(**kwargs)
context['form'] = form
context['sub_form'] = sub_form
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
form = ProductForm(request.POST, prefix="sch")
sub_form = ImageForm(request.POST, prefix="loc")
...
template:
{% block container %}
<div class="container">
<br/>
<form action="{% url 'manager:add_product' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
{{ sub_form.as_p }}
<p>
<button type="submit">Submit</button>
</p>
</form>
</div>
{% endblock %}
Based on this answer by #ybendana:
Again, we use is_bound to check if the form is capable of validation. See this section of the documentation:
Bound and unbound forms
A Form instance is either bound to a set of data, or unbound.
If it’s bound to a set of data, it’s capable of validating that data and rendering the form as HTML with the data displayed in the HTML.
If it’s unbound, it cannot do validation (because there’s no data to validate!), but it can still render the blank form as HTML.
We use a list of tuples for form objects and their details allowing for more extensibility and less repetition.
However, instead of overriding get(), we override get_context_data() to make inserting a new, blank instance of the form (with prefix) into the response the default action for any request. In the context of a POST request, we override the post() method to:
Use the prefix to check if each form has been submitted
Validate the forms that have been submitted
Process the valid forms using the cleaned_data
Return any invalid forms to the response by overwriting the context data
# views.py
class MultipleForms(TemplateResponseMixin, ContextMixin, View):
form_list = [ # (context_key, formcls, prefix)
("form_a", FormA, "prefix_a"),
("form_b", FormB, "prefix_b"),
("form_c", FormC, "prefix_c"),
...
("form_x", FormX, "prefix_x"),
]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Add blank forms to context with prefixes
for context_key, formcls, prefix in self.form_list:
context[context_key] = formcls(prefix=prefix)
return context
def post(self, request, *args, **kwargs):
# Get object and context
self.object = self.get_object()
context = self.get_context_data(object=self.object)
# Process forms
for context_key, formcls, prefix in self.form_list:
if prefix in request.POST:
# Get the form object with prefix and pass it the POST data to \
# validate and clean etc.
form = formcls(request.POST, prefix=prefix)
if form.is_bound:
# If the form is bound (i.e. it is capable of validation) \
# check the validation
if form.is_valid():
# call the form's save() method or do whatever you \
# want with form.cleaned_data
form.save()
else:
# overwrite context data for this form so that it is \
# returned to the page with validation errors
context[context_key] = form
# Pass context back to render_to_response() including any invalid forms
return self.render_to_response(context)
This method allows repeated form entries on the same page, something I found did not work with #ybendana's answer.
I believe it wouldn't be masses more work to fold this method into a Mixin class, taking the form_list object as an attribute and hooking get_context_data() and post() as above.
Edit: This already exists. See this repository.
NB:
This method required TemplateResponseMixin for render_to_response() and ContextMixin for get_context_data() to work. Either use these Mixins or a CBV that descends from them.
If you are using approach with class-based views and different 'action' attrs i mean
Put different URLs in the action for the two forms. Then you'll have two different view functions to deal with the two different forms.
You can easily handle errors from different forms using overloaded get_context_data method, e.x:
views.py:
class LoginView(FormView):
form_class = AuthFormEdited
success_url = '/'
template_name = 'main/index.html'
def dispatch(self, request, *args, **kwargs):
return super(LoginView, self).dispatch(request, *args, **kwargs)
....
def get_context_data(self, **kwargs):
context = super(LoginView, self).get_context_data(**kwargs)
context['login_view_in_action'] = True
return context
class SignInView(FormView):
form_class = SignInForm
success_url = '/'
template_name = 'main/index.html'
def dispatch(self, request, *args, **kwargs):
return super(SignInView, self).dispatch(request, *args, **kwargs)
.....
def get_context_data(self, **kwargs):
context = super(SignInView, self).get_context_data(**kwargs)
context['login_view_in_action'] = False
return context
template:
<div class="login-form">
<form action="/login/" method="post" role="form">
{% csrf_token %}
{% if login_view_in_action %}
{% for e in form.non_field_errors %}
<div class="alert alert-danger alert-dismissable">
{{ e }}
<a class="panel-close close" data-dismiss="alert">×</a>
</div>
{% endfor %}
{% endif %}
.....
</form>
</div>
<div class="signin-form">
<form action="/registration/" method="post" role="form">
{% csrf_token %}
{% if not login_view_in_action %}
{% for e in form.non_field_errors %}
<div class="alert alert-danger alert-dismissable">
{{ e }}
<a class="panel-close close" data-dismiss="alert">×</a>
</div>
{% endfor %}
{% endif %}
....
</form>
</div>
Here is simple way to handle the above.
In Html Template we put Post
<form action="/useradd/addnewroute/" method="post" id="login-form">{% csrf_token %}
<!-- add details of form here-->
<form>
<form action="/useradd/addarea/" method="post" id="login-form">{% csrf_token %}
<!-- add details of form here-->
<form>
In View
def addnewroute(request):
if request.method == "POST":
# do something
def addarea(request):
if request.method == "POST":
# do something
In URL
Give needed info like
urlpatterns = patterns('',
url(r'^addnewroute/$', views.addnewroute, name='addnewroute'),
url(r'^addarea/', include('usermodules.urls')),
if request.method == 'POST':
expectedphraseform = ExpectedphraseForm(request.POST)
bannedphraseform = BannedphraseForm(request.POST)
if expectedphraseform.is_valid():
expectedphraseform.save()
return HttpResponse("Success")
if bannedphraseform.is_valid():
bannedphraseform.save()
return HttpResponse("Success")
else:
bannedphraseform = BannedphraseForm()
expectedphraseform = ExpectedphraseForm()
return render(request, 'some.html',{'bannedphraseform':bannedphraseform, 'expectedphraseform':expectedphraseform})
This worked for me accurately as I wanted. This Approach has a single problem that it validates both the form's errors. But works Totally fine.
I discovered a pretty interesting way to send TWO Forms from a single page using the same view. I tried many options but just wanted something that can just work. So here is something that I discovered. But it only works when there are just TWO Forms on a page.
I am using just try and except method to first try first form and if that doesnt works than try second form. This is quiet interesting to know that it works absolutely fine. Don't use it on scalable application as it can create troublesome or may risk the security of the application, else use Class based view to submit mutiple forms or create seperate views for each form.
def create_profile(request):
if request.method=='POST':
try:
biograph = Biography(name=name, email=email, full_name=full_name, slug_name=slug_name, short_bio=short_bio)
biograph.save()
except:
social = SocialMedia(twitter=twitter, instagram=instagram, facebook=facebook, linkedin=linkedin, github=github)
social.save()