I want to display countries and states in Django form, for that I am trying to get data from json, create form, pass json data to form and get state of the country on ajax request. I managed to write the process as far as I learned, but at last form is not rendered on Django template. How can I render Django form with following code structure?
My Model:
from django.db import models
class Address(models.Model):
country = models.CharField(null=True, blank=True, max_length=100)
state = models.CharField(null=True, blank=True, max_length=100)
def __str__(self):
return '{} {}'.format(self.country, self.state)
My Forms.py:
import json
def readJson(filename):
with open(filename, mode="r", encoding="utf-8") as fp:
return json.load(fp)
def get_country():
""" GET COUNTRY SELECTION """
filepath = './static/data/countries_states_cities.json'
all_data = readJson(filepath)
all_countries = [('-----', '---Select a Country---')]
for x in all_data:
y = (x['name'], x['name'])
all_countries.append(y)
return all_countries
def return_state_by_country(country):
""" GET STATE SELECTION BY COUNTRY INPUT """
filepath = './static/data/countries_states_cities.json'
all_data = readJson(filepath)
all_states = []
for x in all_data:
if x['name'] == country:
if 'states' in x:
for state in x['states']:
y = (state['name'], state['name'])
all_states.append(state['name'])
else:
all_states.append(country)
return all_states
class AddressForm(forms.ModelForm):
country = forms.ChoiceField(
choices = get_country(),
required = False,
label='Country / Region*',
widget=forms.Select(attrs={'class': 'form-control', 'id': 'id_country'}),
)
class Meta:
model = Address
fields = ['country']
My Form.html
<form class="" action="" method="post">
{% csrf_token %}
{% for error in errors %}
<div class="alert alert-danger mb-4" role="alert">
<strong>{{ error }}</strong>
</div>
{% endfor %}
<div class="row">
<div class="col-lg-6">
<div class="mb-4">
{{ form.country}}
</div>
</div>
<div class="col-lg-6">
<div class="mb-4">
<div class="form-group">
<label >Select a Province/State</label>
<select id="id_province" class="form-control" name="state">
<option value="-----">Select Province/State</option>
</select>
</div>
</div>
</div>
</div>
</form>
My Views:
def readJson(filename):
with open(filename, mode="r", encoding="utf-8") as fp:
return json.load(fp)
def return_state_by_country(country):
""" GET STATE SELECTION BY COUNTRY INPUT """
filepath = './static/data/countries_states_cities.json'
all_data = readJson(filepath)
all_states = []
for x in all_data:
if x['name'] == country:
if 'states' in x:
for state in x['states']:
y = (state['name'], state['name'])
all_states.append(state['name'])
else:
all_states.append(country)
return all_states
def getProvince(request):
country = request.POST.get('country')
provinces = return_state_by_country(country)
return JsonResponse({'provinces': provinces})
def processForm(request):
context = {}
if request.method == 'GET':
form = AddressForm()
context['form'] = form
return render(request, './ecommerce/checkout.html', context)
if request.method == 'POST':
form = AddressForm(request.POST)
if form.is_valid():
selected_province = request.POST['state']
obj = form.save(commit=False)
obj.state = selected_province
obj.save()
return render(request, './ecommerce/checkout.html', context)
My Ajax:
<script>
$("#id_country").change(function () {
var countryId = $(this).val();
$.ajax({
type: "POST",
url: "{% url 'ecommerce:get-province' %}",
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'country': country
},
success: function (data) {
console.log(data.provinces);
let html_data = '<option value="-----">Select Province/State</option>';
data.provinces.forEach(function (data) {
html_data += `<option value="${data}">${data}</option>`
});
$("#id_province").html(html_data);
}
});
});
</script>
I am trying to print form.country on template but its not working. What could be the problem?
With ModelForms I find that this type of configuration, in which everything falls under class Meta: works.
However im dubious about that get_country() method. If you share it I can take a deeper look and maybe even test it to make sure that it's not doing anything funky.
If your list of countries is somewhat static and not too long you might wanna consider using a TextChoices enum type in your model attribute to limit the choice selection. Django forms will automatically render a dropdown widget listing the items from your enum.
You can checkout this answer if you want to look into that, which further links to the django docs.
class AddressForm(forms.ModelForm):
class Meta:
model = Address
fields = ['country']
widgets = {
"country": forms.ChoiceField(
choices = get_country(),
attrs={
"class": "form-control",
"id": "id_country"
}
),
}
labels = {
"country" : "Company Country Location"
}
Related
I am trying to pass the values of form data through ajax .And getting method not allowed error. I am trying to add comment in a blog post.
This is my form which is inside blog_detail page
<form id="commentform" class="commentform" method="post">
{% csrf_token %}
{%with allcomments.count as total_comments%}
<p>
{{total_comments}} comment{{total_comments|pluralize}}
</p>
{%endwith%}
<select name="blog" class="d-none" id="id_blog">
<option value="{{blog.id}}" selected="{{blog.id}}"></option>
</select>
<label class="small font-weight-bold">{{comment_form.parent.label}}</label>
{{comment_form.parent}}
<div class="d-flex">
<img class="avatar_comment align-self-center" src="{% for data in avatar%}{{data.avatar.url}}{%endfor%}" alt="">
{{comment_form.content}}
</div>
<div class="d-flex flex-row-reverse">
<button value="commentform" id="newcomment" type="submit" class="newcomment btn btn-primary">Submit</button>
</div>
</form>
And when I click the button it should call the ajax
$(document).on('click','#newcomment',function(e){
e.preventDefault();
var button =$(this).attr("value");
var placement = "commentform"
if (button=="newcommentform"){
var placement = "newcommentform"
}
$.ajax({
type: 'POST',
url: '{% url "website:addcomment" %}',
data: $("#" + button).serialize(),
cache: false,
sucess: function(json){
console.log(json)
$('<div id="" class="my-2 p-2" style="border: 1px solid grey"> \
<div class="d-flex justify-content-between">By ' + json['user'] + '<div></div>Posted: Just now!</div> \
<div>' + json['result'] + '</div> \
<hr> \
</div>').insertBefore('#' + placement);
},
error: function(xhr,errmsg,err){
}
});
})
This is my urls.py
path('blog/<int:blog_id>', BlogDetails.as_view(), name="blog_detail"),
path('addcomment/',addcomment, name="addcomment"),
and my views.py is:
class BlogDetails(View):
def get(self, request, blog_id):
query = request.GET.get('query')
if query:
return redirect(reverse('website:search') + '?query=' + query)
blog = Blog.objects.get(id=blog_id)
total_comment = Comment.objects.filter(blog=blog).count()
allcomments = blog.comments.filter(status=True)
blog_list = Blog.objects.all()
comment_form = NewCommentForm()
data = {
'blog': blog,
'blog_list': blog_list,
'total_comment': total_comment,
'comment_form': comment_form,
'allcomments': allcomments
}
return render(request, "blog_detail.html", data)
def addcomment(request):
if request.method == 'post':
comment_form = NewCommentForm(request.POST)
print(comment_form)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
user_comment.user = request.user
user_comment.save()
result = comment_form.cleaned_data.get('content')
user = request.user.username
return JsonResponse({'result': result, 'user': user})
Please help me with this it is not calling addcomment view
If how I've interpreted your code is correct, it would probably work if changed your BlogDetails class to this:
class BlogDetails(View):
def get(self, request, blog_id):
query = request.GET.get('query')
if query:
return redirect(reverse('website:search') + '?query=' + query)
blog = Blog.objects.get(id=blog_id)
total_comment = Comment.objects.filter(blog=blog).count()
allcomments = blog.comments.filter(status=True)
blog_list = Blog.objects.all()
comment_form = NewCommentForm()
data = {
'blog': blog,
'blog_list': blog_list,
'total_comment': total_comment,
'comment_form': comment_form,
'allcomments': allcomments
}
return render(request, "blog_detail.html", data)
def post(self, request, *args, **kwargs):
return self.addcomment(request)
def addcomment(self, request):
comment_form = NewCommentForm(request.POST)
print(comment_form)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
user_comment.user = request.user
user_comment.save()
result = comment_form.cleaned_data.get('content')
user = request.user.username
return JsonResponse({'result': result, 'user': user})
Because you are trying to POST to a view that doesn't have a post method defined.
Then you would need to remove addcomment from the URL you are calling and just post to whatever URL you are currently at.
I'm using Django modelform and it's submitted by pressing the enter key. This is what I wanted, but I don't know why it works. I didn't add any JS codes related to keydown but other codes to practice Ajax. Also, I found out that when there's only one input inside the form, it's submitted with the enter key, but my form has two inputs.
What I'm doing is to add a comment on a post like instagram. I used Ajax to create a comment instance.
models.py
class Comment(models.Model):
parent_post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="comments")
author = models.CharField(max_length=10)
content = models.CharField(max_length=100)
forms.py
class CommentForm(ModelForm):
class Meta:
model = Comment
exclude = ["parent_post"]
HTML
{% for post in posts %}
<form method="POST" data-id="{{post.id}}" class="d-flex align-items-center w-100 mt-2">
{% load widget_tweaks %} <!-- this is a django package for easy CSS -->
{% csrf_token %}
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.author.errors }}
{{ form.author|add_class:"form__author"|attr:"placeholder:name" }}
</div>
<div class="fieldWrapper w-100">
{{ form.content.errors }}
{{ form.content|add_class:"form__content"|attr:"placeholder:content" }}
</div>
<button class="btn btn-sm btn-warning w-auto">Write</button>
</form>
{% endfor %}
JS (Here I didn't put the codes after getting JSON response from views.py)
const forms = document.querySelectorAll("form");
forms.forEach((value) => {
const post_id = Number(value.getAttribute("data-id"));
value.addEventListener("submit", (e) => {
e.preventDefault(); // prevents reload, still submits form data but views.py does nothing for this data
writeComment(post_id);
});
const requestWrite = new XMLHttpRequest();
const writeComment = (post_id) => {
const form = document.querySelector(`form[data-id="${post_id}"]`);
const author = form.querySelector(".form__author");
const content = form.querySelector(".form__content");
const url = "/write/";
if (author.value && content.value) {
requestWrite.open("POST", url, true);
requestWrite.setRequestHeader(
"Content-Type",
"application/x-www-form-urlencoded"
);
requestWrite.send(
JSON.stringify({
post_id: post_id,
author: author.value,
content: content.value,
})
);
author.value = null;
content.value = null;
}
};
views.py
#csrf_exempt
def write(request):
req = json.loads(request.body)
post_id = req["post_id"]
author = req["author"]
content = req["content"]
comment = Comment.objects.create(parent_post=get_object_or_404(Post, id=post_id), author=author, content=content)
return JsonResponse({"post_id":post_id, "comment_id":getattr(comment, "id"), "author":author, "content":content})
Thank you!
I'd like to choose an option in the first select dropdown list and based on the selected option, the ajax should load the second select dropdown list, how to do it?
This is my code:
Models:
class MaintenanceEquipment(models.Model):
equip_id = models.CharField(max_length=30, auto_created=False, primary_key=True)
line_nm = models.CharField(max_length=20, blank=True, null = True)
sequence = models.CharField(max_length=30, blank=True, null = True)
equip_model = models.CharField(max_length=30, blank=True, null = True)
def __str__(self):
return self.equip_id
Views:
from django.shortcuts import render
from maintenance.models import MaintenanceEquipment
def maintenanceIssueView(request):
equipment_list = MaintenanceEquipment.objects.all()
context = {'equipment_list':equipment_list}
return render(request, 'maintenance/maintenanceIssue.html', context)
def load_equipment(request):
if request.method == 'GET':
line = request.GET.get('line_nm')
equipment = MaintenanceEquipment.objects.filter(line_nm=line)
context = {'equipment': equipment}
return render(request, 'maintenance/maintenanceIssue.html', context)
urls:
urlpatterns = [
path('maintenanceIssueView/', views.maintenanceIssueView, name="maintenanceIssueView"),
path('ajax/load_equipment/', views.load_equipment, name="ajax_load_equipment"),
]
maintenanceIssue.html:
<form method="POST" id="maintenanceForm" data-equipment-url="{% url 'ajax_load_equipment' %}" novalidate>
{% csrf_token %}
<div style="text-align:left;" class="container-fluid">
<div style="text-align:left;" class="form-row">
<div class="form-group col-md-6">
<label for="line_nm" style="font-size:medium;">Line</label>
<select class="form-control" id="line_nm" name="line_nm" >
{% for instance in equipment_list %}
<option id="{{ instance.line_nm }}" value="{{ instance.line_nm }}">{{ instance.line_nm }}</option>
{% endfor %}
</select>
</div>
<div class="form-group col-md-6">
<label for="sequence" style="font-size:medium;">Machine</label>
<select class="form-control" id="sequence" name="sequence">
{% for instance in equipment %}
<option value="{{ instance.sequence }}">{{ instance.sequence }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
</form>
<script>
$("#line_nm").change(function () {
var url = $("#maintenanceForm").attr("data-equipment-url");
var line_nm = $(this).val();
$.ajax({
url: url,
data: {
'line_nm': line_nm
},
success: function (data) {
$("#sequence").html(data);
console.log(data);
}
});
});
</script>
The data is correctly sent to the view by GET, this is my terminal:
[21/Sep/2021 08:34:43] "GET
/maintenance/ajax/load_equipment/?line_nm=SMD-16 HTTP/1.1" 200 18644
This is the result of the console.log properly:
<select class="form-control" id="sequence" name="sequence">
<option name = "sequence" value="470">LOADER1</option>
<option name = "sequence" value="471">PRINTER1</option>
<option name = "sequence" value="472">PRINTER2</option>
<option name = "sequence" value="473">CARRIER JIG UNLOADER </option>
<option name = "sequence" value="474">P-AOI</option>
<option name = "sequence" value="475">P-AOI NG BUFFER</option>
<option name = "sequence" value="476">SHUTTLE1</option>
<option name = "sequence" value="477">MOUNTER1</option>
<option name = "sequence" value="478">MOUNTER2</option>
<option name = "sequence" value="479">MOUNTER3</option>
<option name = "sequence" value="480">MOUNTER4</option>
</select>
However, in my html select "sequence" is appearing empty, I've tried so many things, but not success for while.
Here is the general pattern:
template.html
<!-- first select populated with context variables -->
<select id='first-select'>
{% for instance in instances %}
<option value="{{ instance.id}}">
{{ instance.text }}
</option>
{% endfor %}
</select>
<!-- second select populated with response from ajax -->
<select id='second-select'></select>
script.js
$('#first-select').change(function() {
// send ajax request when the first select is changed:
$.ajax({
url : 'the-url',
type : 'POST',
data : {
instanceID : $(this).val()
},
success : function(response) {
// this function executes on receiving a successful response from the backend:
var secondSelect = $('#second-select');
secondSelect.empty();
// iterate over the instances in the response and add them to the second select
for (var instance in response.instances) {
secondSelect.append($('<option>', {
value : instance.id,
text : instance.text
}));
}
}
}
});
views.py
def render_template(request):
""" this method renders the template with context variables """
# set context variables:
context = {
"instances" : FirstModel.objects.all()
}
return render(request, 'template.html', context=context)
def get_instances(request):
""" this method returns json-friendly instances for the second select """
# unpack request:
instance_id = request.POST.get('instanceID')
# get instance:
instance = FirstModel.objects.get(id=instance_id)
# get instances
other_instances = SecondModel.objects.filter(first_model = instance)
# serialize data:
...
return JsonResponse({
"status_code" : 200,
"instances" : other_instances
})
I'm working on an assignment to use the fetch API to do some of the normal things we would have Python do in our views with JavaScript such as adding records or querying the database. One issue I'm running across is passing the normal properties we would see in Django, say a user or username, where it just shows up as a literal user id when I pull it from the sql database with the fetch API. With the views, html and JavaScript I have written now, how would I go about pulling the username with fetch in JavaScript that I can normally grab with a variable or view with a print statement in the Django console, instead of just viewing the user id from the database. I feel like I'm missing a step and I'm just not seeing it.
urls
app_name = "network"
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
# API Routes
path("addpost", views.post, name="post"),
path("<str:navbar_item>", views.viewposts, name="viewposts"),
]
models.py
class User(AbstractUser):
pass
class Profile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
bio = models.TextField(null=True, blank=True)
# pics
website = models.CharField(max_length=225, null=True, blank=True)
follower = models.ManyToManyField(
User, blank=True, related_name="followed_user") # user following this profile
# profile user that follows this profile
following = models.ManyToManyField(
User, blank=True, related_name="following_user")
def __str__(self):
return f"{self.user}'s' profile id is {self.id}"
def following_users(self):
for username in self.following:
return username
def get_absolute_url(self):
return reverse("network:profile-detail", args=[str(self.id)])
class Post(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="post_user")
body = models.TextField(max_length=1000)
timestamp = models.DateTimeField(auto_now_add=True)
likes = models.ManyToManyField(User, blank=True, related_name="post_likes")
def __str__(self):
return f"{self.created_by} posted {self.body}"
def get_absolute_url(self):
return reverse("network:post-detail", args=[str(self.id)])
def total_likes(self):
return self.likes.count()
class Meta:
ordering = ["-timestamp"]
views.py
def index(request):
if request.user.is_authenticated:
return render(request, "network/index.html", {})
else:
return HttpResponseRedirect(reverse("network:login"))
#login_required
def post(request):
# Composing a new post must be done via POST
if request.method != "POST":
return JsonResponse({"error": "You must POST your request."}, status=404)
try:
data = json.loads(request.body)
body = data.get("body", "")
user = request.user
print(user)
post = Post(created_by=user, body=body)
# post = Post(created_by=Profile.objects.get(user=user), body=body)
post.save()
except AttributeError:
return JsonResponse({"error": "AttributeError thrown."}, status=500)
return JsonResponse({"message": "Post created."}, status=201)
#login_required
def viewposts(request, navbar_item):
if navbar_item == "viewposts":
posts = Post.objects.all()
posts = posts.order_by("-timestamp")
json_post = serialize("json", posts)
print(posts)
return HttpResponse(json_post, content_type="application/json")
else:
return JsonResponse({"error": "Invalid page."}, status=400)
index.html
{% extends "network/layout.html" %}
{% load static %}
{% block body %}
<div class="container p-5">
{% if error %}
{{ error }}
{% endif %}
<h1 class="display-4">All Posts</h1>
<div class="form-group border rounded p-4">
<h2 class="diplay-3">New Post</h2>
<form id="addpost" class="form-group pt-5">
{% csrf_token %}
<div class="form-group">
<textarea class="form-control" id="body" placeholder="Add post here..."></textarea>
</div>
<input type="submit" class="btn btn-primary"/>
</form>
</div>
<div id="all-posts" class="all-posts">
</div>
</div>
{% endblock %}
{% block script %}
<script src="{% static 'network/main.js' %}"></script>
{% endblock %}
JavaScript
// Post on index page # API Routes /addpost
const addPost = () => {
const addPostUrl = '/addpost';
const csrftoken = getCookie('csrftoken');
const body = document.querySelector('#body').value;
// body needs to be passed into an object before using the stringify method
const bodyObject = { body };
fetch(addPostUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
},
body: JSON.stringify(bodyObject)
})
.then(response => response.json())
.then(result => {
console.log(result);
})
.catch(error => {
console.log(error);
});
return false;
};
// Load posts in index page # API Routes /navbar_item
function loadPosts(navItem, event) {
preventPageLoad(event);
const postUrl = `/${navItem}`;
// Send a GET request to the URL to retrieve all posts
fetch(postUrl)
.then(response => response.json())
.then(data => {
data.forEach(post => {
const { fields } = post;
const allPostsContainer = document.querySelector("#all-posts");
const element = document.createElement('div');
const postId = `#post-${fields.id}`;
element.style.textDecoration = 'none';
element.classList.add('HoverClass1');
element.setAttribute('id', `post-${fields.id}`);
element.classList.add('d-flex', 'flex-column' ,'justify-content-between', 'p-4', 'm-3', 'lead', 'border', 'rounded');
element.style.color = '#000000';
element.innerHTML =
// This is returning an id
`<div class="bd-highlight font-weight-bolder mr-5">${fields.created_by}</div>
<div class="bd-highlight">${fields.timestamp}</div>
<div class="flex-fill bd-highlight">${fields.body}</div>`;
console.log(fields);
allPostsContainer.append(element);
const linePost = document.querySelector(postId);
linePost.addEventListener('click', (event) => {
console.log(event);
});
});
})
.catch(error => {
console.log(error);
});
return false;
}
Images showing my admin console in Django versus the browser console and what fetch is pulling in JavaScript. You'll see in the admin console we can view the username, but in the browser console all I'm getting is the user id with fetch.
I figured out how to do this. I added a serialize method to the Post model to convert these properties to JSON.
def serialize(self):
return {
'id': self.id,
'created_by': self.created_by.username,
'body': self.body,
'timestamp': self.timestamp.strftime('%b %-d %Y, %-I:%M %p'),
'likes': self.total_likes()
}
Then in views.py, in my viewposts function, instead of my the HttpResponse, I used JsonResponse and passed the model's serialize method as an argument.
#login_required
def viewposts(request, navbar_item):
if navbar_item == "viewposts":
posts = Post.objects.all()
posts = posts.order_by("-timestamp")
return JsonResponse([post.serialize() for post in posts], safe=False)
else:
return JsonResponse({"error": "Invalid page."}, status=400)
This allowed me to not have to deconstruct anything in my JavaScript file. So I could pull any attributes from my query using dot notation directly off of the data model in fetch.
I have django app and problem with multiple images upload.
Everything was OK till add to Familymember model field image.
Now I can not create any item for FamilyMember.
Please for help.
Here is my model:
class Profile(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
created_date = models.DateTimeField(default=timezone.now)
def get_absolute_url(self):
return reverse('profile-update', kwargs={'pk': self.pk})
def __unicode__(self):
return "%s %s" % (self.first_name, self.last_name)
class FamilyMember(models.Model):
profile = models.ForeignKey(Profile)
name = models.CharField(max_length=100)
file = models.FileField(upload_to="localefile/")
relationship = models.CharField(max_length=100)
Here are forms:
class ProfileForm(ModelForm):
class Meta:
model = Profile
exclude = ()
class FamilyMemberForm(ModelForm):
file = forms.FileField(widget=forms.FileInput(attrs={'multiple': True}))
class Meta:
model = FamilyMember
exclude = ()
FamilyMemberFormSet = inlineformset_factory(Profile, FamilyMember,
form=FamilyMemberForm, extra=1)
Here are my views, to create.
class ProfileCreate(CreateView):
model = Profile
fields = ['first_name', 'last_name']
class ProfileFamilyMemberCreate(CreateView):
model = Profile
fields = ['first_name', 'last_name']
success_url = reverse_lazy('profile-list')
def get_context_data(self, **kwargs):
data = super(ProfileFamilyMemberCreate, self).get_context_data(**kwargs)
if self.request.POST:
data['familymembers'] = FamilyMemberFormSet(self.request.POST)
else:
data['familymembers'] = FamilyMemberFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
familymembers = context['familymembers']
with transaction.atomic():
self.object = form.save()
if familymembers.is_valid():
familymembers.instance = self.object
familymembers.save()
return super(ProfileFamilyMemberCreate, self).form_valid(form)
I also use a JavaScript code, from here:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'formset/jquery.formset.js' %}"></script>
<script type="text/javascript">
$('.formset_row').formset({
addText: 'add family member',
deleteText: 'remove',
prefix: 'familymember_set'
});
</script>
When you upload a file it's passed through request.FILES, so you must also pass it to you FormSet, e.g:
def get_context_data(self, **kwargs):
data = super(ProfileFamilyMemberCreate, self).get_context_data(**kwargs)
if self.request.POST:
data['familymembers'] = FamilyMemberFormSet(
data=self.request.POST,
files=self.request.FILES
)
else:
data['familymembers'] = FamilyMemberFormSet()
return data
Don't forget to add the enctype in your form:
<form enctype="multipart/form-data" ...>