Django dynamic forms validation - django

So I am new to Django and I have created a View which uses a total of 8 forms dynamically. There is one base form which is always displayed and then there are 7 more forms that are displayed only if user selects that option from a drop down (drop down is in the HTML template).
I am now trying to validate the form fields and when I display all 8 forms statically, the validation (clean methods) for each of the forms work perfectly! However when I change that to dynamically display the forms based on user selection, the validation for the base form fails every time.
Any idea why that could be happening? I could provide instances of the forms/view if that would help!
Template:
<form0 id="BaseForm" action="/test_created/" method="post">
{% csrf_token %}
{{create_test_form.as_ul}} <br><br>
</form0>
<form1 id="vc1Form" action="" method="post" style="display:none">
{% csrf_token %}
{{vc1_form.as_ul}} <br><br>
</form1>
<form2 id="vc2Form" action="" method="post" style="display:none">
{% csrf_token %}
{{vc2_form.as_ul}} <br><br>
</form2>
<form3 id="vc3Form" action="" method="post" style="display:none">
{% csrf_token %}
{{vc3_form.as_ul}} <br><br>
</form3>
<form4 id="vc4Form" action="" method="post" style="display:none">
{% csrf_token %}
{{vc4_form.as_ul}} <br><br>
</form4>
<form5 id="vc5Form" action="" method="post" style="display:none">
{% csrf_token %}
{{vc5_form.as_ul}} <br><br>
</form5>
<form6 id="vc6Form" action="" method="post" style="display:none">
{% csrf_token %}
{{vc6_form.as_ul}} <br><br>
</form6>
<form7 id="vc7Form" action="" method="post" style="display:none">
{% csrf_token %}
{{vc7_form.as_ul}} <br><br>
</form7>
<div>
<select id="validation_classes_id" name="all_validation_classes" onchange="showForm()">
<option value="%">Choose the validation class</option>
{% for val_class in all_validation_classes %}
<option value="{{ val_class.id }}">{{ val_class.id}} {{val_class.name }}</option>
{% endfor %}
</select> <br> <br>
<form id="submit" action="" method="post">
{% csrf_token %}
<input type="submit" value="Submit" onclick=""/>
</form>
</div>
<br><br>
<script>
function showForm(){
if (validation_classes_id.value == 1){
console.log("Chose validation class 1");
var div = document.getElementById('vc1Form');
console.log(div)
div.style.display='block';
}
else if (validation_classes_id.value == 2){
console.log("Chose validation class 2");
var div = document.getElementById('vc2Form');
console.log(div)
div.style.display='block';
}
else if (validation_classes_id.value == 3){
console.log("Chose validation class 3");
var div = document.getElementById('vc3Form');
console.log(div)
div.style.display='block';
}
else if (validation_classes_id.value == 4){
console.log("Chose validation class 4");
var div = document.getElementById('vc4Form');
console.log(div)
div.style.display='block';
}
else if (validation_classes_id.value == 5){
console.log("Chose validation class 5");
var div = document.getElementById('vc5Form');
console.log(div)
div.style.display='block';
}
else if (validation_classes_id.value == 6){
console.log("Chose validation class 6");
var div = document.getElementById('vc6Form');
console.log(div)
div.style.display='block';
}
else if (validation_classes_id.value == 7){
console.log("Chose validation class 7");
var div = document.getElementById('vc7Form');
console.log(div)
div.style.display='block';
}
}
</script>
View:
def create_test(request):
context = {
'all_validation_classes': ValidationClass.objects.all(),
'create_test_form': CreateTestForm,
'vc1_form': VC1Form,
'vc2_form': VC2Form,
'vc3_form': VC3Form,
'vc4_form': VC4Form,
'vc5_form': VC5Form,
'vc6_form': VC6Form,
'vc7_form': VC7Form
}
if request.method == 'POST':
create_test_form = CreateTestForm(request.POST)
vc1_form = VC1Form(request.POST)
vc2_form = VC2Form(request.POST)
vc3_form = VC3Form(request.POST)
vc4_form = VC4Form(request.POST)
vc5_form = VC5Form(request.POST)
vc6_form = VC6Form(request.POST)
vc7_form = VC7Form(request.POST)
if create_test_form.is_valid():
print("This is where I am")
print("Create Test form looks valid")
vc_list = request.POST.getlist('validation_class', None)
selected_vc = ValidationClass.objects.filter(pk__in=vc_list)
global_val_class = selected_vc
if vc1_form.is_valid():
print("VC1Form is valid")
else:
print("Failing at VC1")
return HttpResponseRedirect('/test_not_created/')
if vc2_form.is_valid():
print("VC2Form is valid")
else:
print("Failing at VC2")
return HttpResponseRedirect('/test_not_created/')
if vc3_form.is_valid():
print("VC3Form is valid")
else:
print("Failing at VC3")
return HttpResponseRedirect('/test_not_created/')
if vc4_form.is_valid():
print("VC4Form is valid")
else:
print("Failing at VC4")
return HttpResponseRedirect('/test_not_created/')
if vc5_form.is_valid():
print("VC5Form is valid")
else:
print("Failing at VC5")
return HttpResponseRedirect('/test_not_created/')
if vc6_form.is_valid():
print("VC6Form is valid")
else:
print("Failing at VC6")
return HttpResponseRedirect('/test_not_created/')
if vc7_form.is_valid():
print("VC7Form is valid")
else:
print("Failing at VC7")
return HttpResponseRedirect('/test_not_created/')
return HttpResponseRedirect('/test_created/')
else:
print("Failing at create_test")
return HttpResponseRedirect('/test_not_created/')
else:
create_test_form = CreateTestForm()
vc1_form = VC1Form()
vc2_form = VC2Form()
vc3_form = VC3Form()
vc4_form = VC4Form()
vc5_form = VC5Form()
vc6_form = VC6Form()
vc7_form = VC7Form()
return render (request, 'create_test.html', context)
Forms:
class CreateTestForm(forms.ModelForm):
class Meta:
model = Test
fields = ['name', 'test_group', 'description', 'query_text', 'failure_condition', 'status']
def clean_status(self):
print("This is where I am")
print(self.cleaned_data)
def getKey(self):
return "create_test_form"
class VC1Form(forms.Form):
expected_relation = forms.ChoiceField(choices = [('<','<'), ('>','>'), ('=','='), ('<=','<='), ('>=','>='), ('!=','!=')], required = True, label = 'Expected Relation: ')
num_rows = forms.IntegerField(initial = 0)
def getKey(self):
return "vc1_form"
class VC2Form(forms.Form):
expected_relation = forms.ChoiceField(choices=[('<', '<'), ('>', '>'), ('=', '='), ('<=', '<='), ('>=', '>='), ('!=', '!=')], required=True, label='Expected Relation: ')
comparing_value_type = forms.ChoiceField(choices=[('Integer', 'Integer'), ('String', 'String')], required=True, label='Comparing Value Type')
comparing_value = forms.CharField(initial = 0)
def clean_comparing_value(self):
exp_rel = self.cleaned_data['expected_relation']
input_val_type = self.cleaned_data['comparing_value_type']
input_val = self.cleaned_data['comparing_value']
if (input_val_type == 'Integer'):
print("I am in integer")
try:
int(input_val)
print(int(input_val))
return input_val
except ValueError:
print("Getting a value error")
raise forms.ValidationError('Should be an Integer')
elif (input_val_type == 'String'):
print("I am in string")
if (exp_rel != '!=' and exp_rel != '='):
print("I am in here...")
raise forms.ValidationError('Must have either = or != as comparator for String')
try:
int(input_val)
print(int(input_val))
print("getting a value error")
raise forms.ValidationError('Should be a string')
except ValueError:
print("No value error")
return input_val
def getKey(self):
return "vc2_form"
class VC3Form(forms.Form):
comparing_value_2 = forms.CharField(label = 'Comparing Value', initial=" ") #Need to figure out if its needed to make this into an array?
# Not sure for now if there is a need to validate this data
def getKey(self):
return "vc3_form"
class VC4Form(forms.Form):
# # This is mostly not needed as we will only check the values in the first column of the query results (as per documentation)
wanted_value = forms.CharField(label = 'Name of corresponding column', initial=" ") #Need to figure out how the input will be an actual variable from the select query
acceptable_error_rate = forms.IntegerField(min_value = 0, max_value = 100, initial=0)
def getKey(self):
return "vc4_form"
class VC5Form(forms.Form):
expected_relation_2 = forms.ChoiceField(choices=[('<', '<'), ('>', '>'), ('=', '='), ('<=', '<='), ('>=', '>='), ('!=', '!=')], required=True,label='Expected Relation: ')
comparing_value_type_2 = forms.ChoiceField(choices=[('Integer', 'Integer'), ('String', 'String')], required=True, label='Comparing Value Type')
def clean_comparing_value_type_2(self):
expected_relation_choices = ('<', '>', '=', '<=', '>=', '!=')
exp_rel = self.cleaned_data['expected_relation_2']
input_val_type = self.cleaned_data['comparing_value_type_2']
print("This is the input val type")
print(input_val_type)
if (input_val_type == 'String'):
print("I get in here")
if (exp_rel != '=' and exp_rel != '!='):
raise forms.ValidationError('Must have either = or != as comparator for String')
return exp_rel
def getKey(self):
return "vc5_form"
class VC6Form(forms.Form):
expected_relation_3 = forms.ChoiceField(choices=[('<', '<'), ('>', '>'), ('=', '='), ('<=', '<='), ('>=', '>='), ('!=', '!=')], required=True, label='Expected Relation: ')
def getKey(self):
return "vc6_form"
class VC7Form(forms.Form):
expected_relation_one = forms.ChoiceField(choices=[('<', '<'), ('>', '>'), ('=', '='), ('<=', '<='), ('>=', '>='), ('!=', '!=')], required=True, label='Expected Relation to First Value: ')
comparing_value_one = forms.IntegerField(label = 'First comparing value', initial=0)
expected_relation_two = forms.ChoiceField(choices=[('<', '<'), ('>', '>'), ('=', '='), ('<=', '<='), ('>=', '>='), ('!=', '!=')], required=True, label='Expected Relation to Second Value: ')
comparing_value_two = forms.IntegerField(label = 'Second comparing value', initial=0)
def getKey(self):
return "vc7_form"

Related

Initialize a formset

I have two models connected by manytomany relationship and I am trying to use formset to create a dynamic form. I am able to save the form but the problem arise when I am trying to edit the saved instance, I don't know how to properly pass the instance to the formset such that it shows the instance data in form for editing
Here are the details:
Models.py
class Player(models.Model):
pname = models.CharField(max_length=50)
hscore = models.IntegerField()
age = models.IntegerField()
def __str__(self):
return self.pname
class Team(models.Model):
tname = models.CharField(max_length=100)
player= models.ManyToManyField(Player)
def __str__(self):
return self.tname
Forms.py
class PlayerForm(forms.ModelForm):
class Meta:
model = Player
fields = '__all__'
PlayerFormset= formset_factory(PlayerForm)
class TeamForm(forms.ModelForm):
player= PlayerFormset()
class Meta:
model = Team
fields = '__all__'
exclude = ["player"]
Views.py
def team(request):
if request.POST:
form = TeamForm(request.POST)
form.player_instances = PlayerFormset(request.POST)
if form.is_valid():
team= Team()
team.tname= form.cleaned_data['tname']
team.save()
if form.player_instances.cleaned_data is not None:
for item in form.player_instances.cleaned_data:
player = Player()
player.pname= item['pname']
player.hscore= item['hscore']
player.age= item['age']
player.save()
team.player.add(player)
team.save()
else:
form = TeamForm()
return render(request, 'packsapp/employee/new.html', {'form':form})
def updateTeam(request,pk):
team = Team.objects.get(id=pk)
form = TeamForm(instance=team)
// something here to initialize the formset ??
if request.method == "POST":
form = TeamForm(request.POST, instance=team)
if form.is_valid():
form.save()
context = {'form': form}
return render(request, 'packsapp/employee/new.html', context)
Html
<html>
<head>
<title>gffdfdf</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="/static/jquery.formset.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<form id="myForm" action="" method="post" class="">
{% csrf_token %}
<h2> Team</h2>
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% endfor %}
{{ form.player.management_form }}
<h3> Product Instance(s)</h3>
<table id="table-product" class="table">
<thead>
<tr>
<th>player name</th>
<th>highest score</th>
<th>age</th>
</tr>
</thead>
{% for player in form.player %}
<tbody class="player-instances">
<tr>
<td>{{ player.pname }}</td>
<td>{{ player.hscore }}</td>
<td>{{ player.age }}</td>
<td><input id="input_add" type="button" name="add" value=" Add More "
class="tr_clone_add btn data_input"></td>
</tr>
</tbody>
{% endfor %}
</table>
<button type="submit" class="btn btn-primary">save</button>
</form>
</div>
<script>
var i = 1;
$("#input_add").click(function () {
$("tbody tr:first").clone().find(".data_input").each(function () {
if ($(this).attr('class') == 'tr_clone_add btn data_input') {
$(this).attr({
'id': function (_, id) {
return "remove_button"
},
'name': function (_, name) {
return "name_remove" + i
},
'value': 'Remove'
}).on("click", function () {
var a = $(this).parent();
var b = a.parent();
i = i - 1
$('#id_form-TOTAL_FORMS').val(i);
b.remove();
$('.player-instances tr').each(function (index, value) {
$(this).find('.data_input').each(function () {
$(this).attr({
'id': function (_, id) {
console.log("id", id)
var idData = id;
var splitV = String(idData).split('-');
var fData = splitV[0];
var tData = splitV[2];
return fData + "-" + index + "-" + tData
},
'name': function (_, name) {
console.log("name", name)
var nameData = name;
var splitV = String(nameData).split('-');
var fData = splitV[0];
var tData = splitV[2];
return fData + "-" + index + "-" + tData
}
});
})
})
})
} else {
$(this).attr({
'id': function (_, id) {
console.log("id", id)
var idData = id;
var splitV = String(idData).split('-');
var fData = splitV[0];
var tData = splitV[2];
return fData + "-" + i + "-" + tData
},
'name': function (_, name) {
console.log("name", name)
var nameData = name;
var splitV = String(nameData).split('-');
var fData = splitV[0];
var tData = splitV[2];
return fData + "-" + i + "-" + tData
}
});
}
}).end().appendTo("tbody");
$('#id_form-TOTAL_FORMS').val(1 + i);
$("tbody tr:last :input").each(function () {
$(this).attr({
'id': function (_, id) {
return id.replace(/\d/g, i)
},
'name': function (_, name) {
return name.replace(/\d/g, i)
},
})
})
i++;
});
</script>
</body>
</html>
update:
Use modelformset_factory in the views directly:
def post(request):
tform = TeamForm()
pform = modelformset_factory(Player, form=PlayerForm, extra = 1)
pform = pform(request.POST or None, queryset = Player.objects.filter(id__isnull = True))
if request.method == 'POST':
t = Team()
tform = TeamForm(request.POST, instance=t)
if tform.is_valid() and pform.is_valid():
tform.save()
instances = pform.save(commit=False)
for i in instances:
player = Player()
player.pname = i.pname
player.hscore = i.age
player.age = i.hscore
player.save()
t.player.add(player)
t.save()
return redirect('/exams/dashboard/')
else:
print('invalid data')
return render(request, 'team/team_create.html', {'exform': tform, 'exformset': pform})
def update(request, pk = None):
team = Team.objects.get(id = pk)
tform = TeamForm(instance = team)
pform = modelformset_factory(Player, form=PlayerForm, extra=0)
print("players", Player.objects.filter(team=team))
pform = pform(request.POST or None, queryset=Player.objects.filter(team=team))
if request.method == 'POST':
tform = TeamForm(request.POST, instance=team)
print("tform ", tform)
print("pform ", pform)
if tform.is_valid() and pform.is_valid():
tform.save()
instances = pform.save(commit=False)
for i in instances:
player = Player()
player.pname = i.pname
player.hscore = i.age
player.age = i.hscore
player.save()
t.player.add(player)
t.save()
return redirect('/exams/dashboard/')
else:
print('invalid data')
return render(request, 'team/team_create.html', {'exform': tform, 'exformset': pform})
The TeamForm has to set the queryset of the PlayerFormset.
The following shows how.
class TeamForm(forms.ModelForm):
player= PlayerFormset()
class Meta:
model = Team
fields = '__all__'
exclude = ["player"]
def __init__(self,*args, **kwargs):
super(TeamForm,self).__init__(*args,**kwargs)
self.player = PlayerFormSet(queryset=Players.objects.filter(team=self.instance)
Information from the documentation:
https://docs.djangoproject.com/en/2.2/topics/forms/modelforms/#changing-the-queryset
maybe also worth a look:
https://stackoverflow.com/a/34323401/13168118
EDIT:
your PlayerFormset should be created with a modelformset_factory like:
PlayerFormset = modelformset_factory(Player, form=PlayerForm)
modelformset documentation: https://docs.djangoproject.com/en/2.2/ref/forms/models/#modelformset-factory

How to open an uploaded file in another template - Django?

my django app acts as an emailing service, emails that are sent are view-able and it's possible to send html emails. How do I display the html emails on the view-mail page rather than just displaying the name of the file ? (the following is the mail-view for an html email):
How would I display the actual html in the body of this page?
This is my views.py:
def outbox(request):
#Mail_Item.objects.all().delete()
if request.method == "POST" and request.POST.get('Username', False)!=False:
username = request.POST.get('Username')
password = request.POST.get('Password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
print(username + " has logged in")
messages = Mail_Item.objects.filter(user=request.user.username)
args = {'messages':messages}
return render(request, 'outbox.html', args)
else:
return render(request, '404.html')
elif request.POST.get('Username', False) == False and request.POST.get('mail_body_field', False) == False:
pass
elif request.method == "POST" and request.POST.get('mail_subject_field')!=False:
subject = request.POST.get('mail_subject_field')
body = request.POST['mail_body_field']
file = ""
try:
file = request.FILES['filename']
except:
pass
print("sending mail:")
for i in range(1, len(Res)+1):
y = Res['ID' + str(i)].email
print("sent to " + y )
msg = EmailMessage(subject, body, 'email#example.com', [y])
msg.content_subtype = "html"
if (str(file)) != "" and (str(file))[-4:] != 'html':
msg.attach_file(str(file))
obj = Mail_Item(subject=subject, body=body, user=request.user.username, file_name=(str(file)))
obj.save()
print("email stored in database")
elif (str(file)) != "" and (str(file))[-4:] == 'html' :
uploaded_file = file
fs = FileSystemStorage()
fs.save((str(file)), uploaded_file)
html_message = render_to_string((str(file)), {'context': 'values'})
plain_message = strip_tags(html_message)
from_email = 'From <email2#example.com>'
mail.send_mail(subject, plain_message, from_email, [y], html_message=html_message)
obj = Mail_Item(subject=subject, body=body, user=request.user.username, file_name=(str(file)))
obj.save()
else:
obj = Mail_Item(subject=subject, body=body, user=request.user.username, file_name='None')
obj.save()
print("email stored in database")
#msg.send()
i += 1
messages = Mail_Item.objects.filter(user=request.user.username)
args = {'messages':messages}
return HttpResponseRedirect('../templates/outbox.html', args, request)
else:
print("pleeeeeaassee")
return render(request, '404.html')
messages = Mail_Item.objects.filter(user=request.user.username)
args = {'messages':messages}
return render(request, 'outbox.html', args)
def login_page(request):
if request.method == "POST":
username = request.POST['sign-up-name']
email = request.POST['sign-up-email']
password = request.POST['sign-up-password']
user = User.objects.create_user(username, email, password)
user.save()
print(username + " has been added to the user database.")
else:
pass
return render(request, 'login.html')
def signup_page(request):
return render(request, 'signup.html')
def mail_view(request, id=None):
if id:
email = Mail_Item.objects.get(id=id)
args = {'email':email}
else:
pass
return render(request, 'mail-view.html', args)
def log_out(request):
logout(request)
return render(request, 'log-out.html')
def delete(request):
Mail_Item.objects.filter(id=id).delete()
messages = Mail_Item.objects.filter(user=request.user.username)
args = {'messages':messages}
return render(request, 'outbox.html', args)
This is the code for my mail-view template where I'd like to place the html that is being sent:
<div class="mail-view">
<h4 class="m-0">{{ email.subject }}</h4>
<div class="divid"></div>
<div class="media">
<div class="media-left">
<div class="avatar avatar-lg avatar-circle">
<img class="img-responsive" src="{% static '../static/assets/images/221.jpg' %}" alt="avatar"/>
</div><!-- .avatar -->
</div>
<div class="media-body">
<div class="m-b-sm">
<h4 class="m-0 inline-block m-r-lg">
Access Bank
</h4>
</div>
<p><b>Attachment: </b>{{ email.file_name }}</p>
</div>
</div>
<div class="divid"></div>
<div class="row">
<div class="col-md-12">
<div class="m-h-lg lh-xl">
<p>{{ email.body }}</p>
</div>
</div>
</div>
</div>
Models.py:
from django.db import models
class Details(models.Model):
email = models.CharField(max_length=200)
def __str__(self):
return self.email
class Mail_Item(models.Model):
subject = models.CharField(max_length=200)
body = models.CharField(max_length=300)
time = models.DateTimeField(auto_now=True)
user = models.CharField(max_length=15)
file_name = models.CharField(max_length=100, null=True, default=None)
def __str__(self):
template = '{0.subject} {0.body} {0.time} {0.user} {0.file_name}'
return template.format(self)

Django - Nested loops and template rendering with Forms

Is there a way to set a variable after a return statement?
I am trying to execute a for loop with a if clause. At first the if clause is False and after the for loop is executed completely it should render a template with a form and then set the variable to True afterwards. Then the for loop gets executed again but this time it should execute the if statement and submit the Form which is something like ("Are you sure?" and then Continue or Cancel). I tried it with using nested loops (for loop inside a while loop) but the return render statement to render the template with the request is not working with setting the variable afterwards.
This is my views.py
def file_upload(request):
if request.method == "POST":
# Wenn CSV Datei valide ist --> Datei hochladen
csv_file = request.FILES['file']
csv_file.seek(0)
decoded_file = csv_file.read().decode('utf-8').splitlines()
reader = csv.reader(decoded_file)
updated_list = list()
created_list = list()
s = False
form2 = ConfirmationForm(request.POST, request.FILES)
while (True):
for row in reader:
count += 1
try:
datet = datetime.now().date()
datum = datet.strftime("%d.%m.%Y")
row[7] = datum
row[8] = str(request.user)
#d = [row[0], row[1], row[2], row[3], row[4]]
dataset1 = CSV5.objects.filter(gebaeudebereich=row[0],
gebaeudenummer=row[1], ebene=row[2],
raum=row[3], dose=row[4])#.values_list("gebaeudebereich", "gebaeudenummer",
# "ebene", "raum", "dose")
dataset2 = CSV5.objects.filter(switch_ip=row[5], switch_port=row[6])#.values_list("switch_ip", "switch_port")
ds1 = CSV5.objects.values_list("gebaeudebereich", "gebaeudenummer", "ebene",
"raum", "dose")
ds2 = CSV5.objects.values_list("switch_ip", "switch_port")
#print("ds1: ", ds1)
print("count: ", count)
print("dataset1: ", dataset1)
print("dataset2: ", dataset2)
print("dataset1: ", dataset1.exists())
print("dataset2: ", dataset2.exists())
print("s: ", s)
if (dataset1.exists() and not dataset2.exists()):
#instance = get_object_or_404(CSV5, id=count)
print("Fall 1")
ins = CSV5.objects.filter(gebaeudebereich=row[0],
gebaeudenummer=row[1], ebene=row[2],
raum=row[3], dose=row[4])
#liste.append(ins.values_list())
#print("liste: ", liste)
print ("instance: ", ins)
if form2.is_valid() and s == True:
ins.update(switch_ip=row[5], switch_port=row[6], datum = row[7], akteur = row[8])
else:
updated_list.append(ins)
updated_obj += 1
elif not dataset1.exists() and dataset2.exists():
print("Fall 2")
ins = CSV5.objects.filter(switch_ip=row[5], switch_port=row[6])
print("instance: ", ins)
if form2.is_valid() and s == True:
ins.update(gebaeudebereich = row[0], gebaeudenummer = row[1], ebene = row[2], raum = row[3],
dose = row[4], datum = row[7], akteur = row[8])
else:
updated_list.append(ins.values_list())
print("dat2: ", dataset2)
updated_obj += 1
elif (dataset1.exists() and dataset2.exists()):
print("Fall 3")
#liste.append(dataset1)
#print("liste: ", liste)
duplicate_obj += 1
elif not (dataset1.exists() and dataset2.exists()):
print("Fall 4")
if form2.is_valid() and s == True:
ins = CSV5.objects.get_or_create(id=CSV5.objects.count() + 1, gebaeudebereich=row[0],
gebaeudenummer=row[1], ebene=row[2],
raum=row[3], dose=row[4], switch_ip=row[5], switch_port=row[6],
datum=row[7], akteur=row[8])
created_list.append(ins)
ins.save()
created_obj += 1
except IndexError:
print("IndexError")
break
except IntegrityError:
duplicate_obj += 1
print("IntegrityError")
if s != False:
messages.success(request, "objects created: %s " % created_obj)
messages.success(request, "objects updated: %s " % updated_obj)
messages.success(request, "duplicate objects: %s " % duplicate_obj)
break
elif s == False:
messages.success(request, "Einträge die neu hinzugefügt werden: %s " % created_list)
messages.success(request, "Einträge die überschrieben werden: %s " % updated_list)
messages.success(request, "Duplikate: %s " % duplicate_obj)
form = ConfirmationForm()
return render(request, "appp/confirmation.html", {'form' : form})
s = True
form = UploadFileForm()
return render(
request, "appp/file_upload.html", {"form": form}
)
Here is my ConfirmationForm:
class ConfirmationForm(forms.Form):
class Meta:
model = CSV5
fields = ('gebaeudebereich', 'gebaeudenummer', 'ebene', 'raum', 'dose',
'switch_ip', 'switch_port', 'datum', 'akteur',)
confirmation.html
{% extends 'appp/base.html' %}
{% block body %}
<h2>Bestätigung</h2>
{% if user.is_authenticated %}
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" onclick="return confirm('Sollen die angezeigten Daten in der Datenbank gespeicher werden?')">Speichern</button>
</form>
<a href = "{% url 'appp:index' %}">
<button>Cancel</button>
</a>
{% endif %}
{% endblock %}
And finally my models.py
class CSV5(models.Model):
gebaeudebereich = models.CharField(max_length=100, blank=True, null=True)
gebaeudenummer = models.CharField(max_length=100, blank=True, null=True)
ebene = models.CharField(max_length=100, blank=True, null=True)
raum = models.CharField(max_length=100, blank=True, null=True)
dose = models.CharField(max_length=100, blank=True, null=True)
switch_ip = models.CharField(max_length=100, blank=True, null=True)
switch_port = models.CharField(max_length=100, blank=True, null=True)
datum = models.CharField(max_length=100)
akteur = models.CharField(max_length=100)
class Meta:
unique_together = (("gebaeudebereich", "gebaeudenummer", "ebene", "raum", "dose"), ("switch_ip", "switch_port"))
So the for loop iterates through every entry and since s is False. It is doing the validation without actually querying the DB. After the for loop has been executed I use a ConfirmationForm where the data that is about to be changed is displayed to the user and then s is set to True. However because I use a return statement, setting the variable to True is not working.
Any help would be appreciated.

How to refresh the selection box when new option is added in Django?

I have a form with a selection box related to a foreign key (for example, category). And on the same page, I have another link that opens a new page to add a new instance of the foreign key. Once the new instance is added, how can I update the current form to add the new option, and preserve the text in the text field (just like how the admin page behaves)?
Here are some of my code snippets:
update_post.html:
...
<form method="post" novalidate action='.'>
{% csrf_token %}
{% include 'base_form.html' with form=form %}
# button to add a category
{% trans "Add category" %}
<button type="submit" class="btn btn-primary" name="publish" value={% trans 'Publish' %}>{% trans 'Publish' %}</button>
</form>
...
create_category.html:
...
<form action="./{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" method="post" novalidate>
{% csrf_token %}
{% include 'base_form.html' with form=form %}
<button type="submit" class="btn btn-primary" value={% trans 'Create' %}>{% trans 'Create' %}</button>
</form>
...
views.py:
...
class PostUpdate(UpdateView):
template_name = 'update_post.html'
success_url = '/'
model = Post
fields = ['title', 'body', 'category']
class CategoryCreate(CreateView):
template_name = 'create_category.html'
model = Category
fields = ['name']
def get_success_url(self):
if 'next' in self.request.GET:
return self.request.GET.get('next')
else:
return reverse('index')
...
What I want to do is that when a new category is added, it becomes available in the update_post page right away, and any changes to the body field are preserved.
I have done this yesterday inspired by django admin ForeignKey popup window add.my condition is a goods has goodcategory and i can add/edit/delet goodscategory in goods's add/update view and the result add/edit/delet goodcategory will sync to goods's add/update view.Here is a demo,which popup is support by layui.
as you can see i can add\change\delete ForeignKey without refresh the parent page.
first custom a new Field to ForeignKey which will receieve add_url\update_url\delete_url:
class ForeignKeyWidget(Select):
template_name = 'widgets/foreign_key_select.html'
def __init__(self, url_template, *args, **kw):
super(ForeignKeyWidget, self).__init__(*args, **kw)
# Be careful that here "reverse" is not allowed
self.url_template = url_template
def get_context(self, name, value, attrs):
context = super(ForeignKeyWidget, self).get_context(name, value, attrs)
context['add_url'] = self.url_template
context['update_url'] = self.url_template
context['delete_url'] = self.url_template + 'lang_delete/'
return context
second is custom a widget for your custom field which can popup add/update category windows and use ajax to delete category:
foreign_key_select.html:
{% include "django/forms/widgets/select.html" %}
<style>
#{{ widget.attrs.id }}_add, #{{ widget.attrs.id }}_change, #{{ widget.attrs.id }}_delete {
margin-top: 10px;
padding: 0 10px;
height: 25px;
line-height: 25px;
}
</style>
<a class="layui-btn layui-btn-mini" id="{{ widget.attrs.id }}_add">
add
</a>
<a class="layui-btn layui-btn-mini layui-btn-disabled" id="{{ widget.attrs.id }}_change">
change
</a><a class="layui-btn layui-btn-mini layui-btn-disabled" id="{{ widget.attrs.id }}_delete">
delete
</a>
<script>
$('#{{ widget.attrs.id }}_add').click(function () {
var index = layui.layer.open({
title: "add_category",
type: 2,
area: ['700px', '500px'],
content: "{{ add_url }}" + '?popup=1&to_field={{ widget.attrs.id }}',
success: function (layer, index) {
}
});
});
$("#{{ widget.attrs.id }}_change").click(function () {
var id = $('#{{ widget.attrs.id }}').val();
if (id) {
var index = layui.layer.open({
title: "change_category",
type: 2,
area: ['700px', '500px'],
content: '{{ update_url }}' + id + '?popup=1&to_field={{ widget.attrs.id }}',
success: function (layer, index) {
}
});
}
});
$("#{{ widget.attrs.id }}_delete").click(function () {
var id = $('#{{ widget.attrs.id }}').val();
var value = $('#{{ widget.attrs.id }} option[value=' + id + ']').text();
var indexGood = value.lastIndexOf('>');
var valueN = indexGood > 0 ? value.substring(indexGood + 1, value.length) : value;
if (id) {
layer.confirm('corform delete' + valueN + ' ?', {icon: 3, title: 'delete'}, function (index) {
$.ajax({
type: "POST",
data: {},
url: '{{ delete_url }}' + id + '/',
beforeSend: function (xhr) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
success: function (data, textStatus) {
layer.close(index);
$('#{{ widget.attrs.id }} option[value=' + data.id + ']').remove();
$("#{{ widget.attrs.id }}_change,#{{ widget.attrs.id }}_delete").addClass('layui-btn-disabled');
return false;
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
layer.alert('delete failed' + XMLHttpRequest.responseText)
}
});
});
}
});
function {{ widget.attrs.id }}_isDisabled() {
if ($('#{{ widget.attrs.id }}').val()) {
$("#{{ widget.attrs.id }}_change,#{{ widget.attrs.id }}_delete").removeClass('layui-btn-disabled');
} else {
$("#{{ widget.attrs.id }}_change,#{{ widget.attrs.id }}_delete").addClass('layui-btn-disabled');
}
}
$('#{{ widget.attrs.id }}').change(function () {
{{ widget.attrs.id }}_isDisabled();
});
{{ widget.attrs.id }}_isDisabled();
</script>
third is use your custom field for category in your forms.py:
class GoodsForm(ModelForm):
def __init__(self, *args, **kwargs):
super(GoodsForm, self).__init__(*args, **kwargs)
self.fields['category'].widget.attrs.update({'class': 'form-control'})
self.fields['title'].widget.attrs.update({'class': 'form-control'})
self.fields['content'].widget.attrs.update({'class': 'form-control'})
class Meta:
model = Goods
fields = ['category', 'title', 'content']
widgets = {
'category': ForeignKeyWidget(url_template=reverse_lazy('goods_category_ajax_create')),
}
and new a goodcategory form is forms.py
class GoodsCategoryForm(TranslatableModelForm):
def __init__(self, *args, **kwargs):
super(GoodsCategoryForm, self).__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({'class': 'form-control'})
self.fields['cover'].widget.attrs.update({'class': 'form-control'})
self.fields['parent'].widget.attrs.update({'class': 'form-control'})
class Meta:
model = GoodsCategory
fields = ['name', 'cover', 'parent']
four is handle request in your views.py:
class GoodsCategoryAjaxCreateView(BaseContextMixin, IsStaffUserMixin, CreateView):
form_class = GoodsCategoryForm
template_name = 'goods_category_ajax/create.html'
def get_context_data(self, **kwargs):
if 'to_field' in self.request.GET:
kwargs['to_field'] = self.request.GET['to_field']
return super(GoodsCategoryAjaxCreateView, self).get_context_data(**kwargs)
def form_valid(self, form):
self.object = form.save()
context = {'op': 'create', 'id': self.object.id, 'value': self.object.__str__()}
if 'to_field' in self.request.GET:
context['to_field'] = self.request.GET['to_field']
return TemplateResponse(self.request, 'goods_category_ajax/success.html', context=context)
class GoodsCategoryAjaxUpdateView(BaseContextMixin, IsStaffUserMixin, UpdateView):
model = GoodsCategory
form_class = GoodsCategoryForm
slug_field = 'id'
context_object_name = 'goods_category'
template_name = 'goods_category_ajax/update.html'
def get_context_data(self, **kwargs):
if 'to_field' in self.request.GET:
kwargs['to_field'] = self.request.GET['to_field']
return super(GoodsCategoryAjaxUpdateView, self).get_context_data(**kwargs)
def form_valid(self, form):
self.object = form.save()
context = {'op': 'create', 'id': self.object.id, 'value': self.object.__str__()}
if 'to_field' in self.request.GET:
context['update'] = self.request.GET['to_field']
return TemplateResponse(self.request, 'goods_category_ajax/success.html', context=context)
class GoodsCategoryAjaxLangDeleteView(BaseContextMixin, IsStaffUserMixin, FakeDeleteView):
model = GoodsCategory
slug_field = 'id'
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
data = {'op': 'delete', 'id': self.object.id, 'value': self.object.__str__()}
self.object.delete()
return JsonResponse(data=data)
urls.py:
url(r'^ajax/$', GoodsCategoryAjaxCreateView.as_view(), name='goods_category_ajax_create'),
url(r'^ajax/(?P<slug>\d+)/$', GoodsCategoryAjaxUpdateView.as_view(), name='goods_category_ajax_update'),
url(r'^ajax/lang_delete/(?P<slug>\d+)/$', GoodsCategoryAjaxLangDeleteView.as_view(),
name='goods_category_ajax_lang_delete'),
five is your add popup windows will open url handle by GoodsCategoryAjaxCreateView and the return template is:
{% extends "manage/base.html" %}
{% block main %}
<form id='goods_category_ajax_create' class="form-horizontal" enctype="multipart/form-data"
action="{% url 'goods_category_ajax_create' %}{% if to_field %}?to_field={{ to_field }}{% endif %}"
method="post">
{% include 'manage/widgets/form.html' %}
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<input class="layui-btn layui-btn-normal" type="submit" value="add_category"/>
</div>
</div>
</form>
{% endblock %}
you submit a new category with modelform and createview,when the form is_vaild a success.html will be return by TemplateResponse(as you can see in GoodsCategoryAjaxCreateView form_valid),and the point is success.html is nothing but a script that can close popup window and insert new option to the to_field element in parent window.here is success.html:
{% extends "manage/base.html" %}
{% block main %}
<script>
var to_field = '#{{ to_field }}', op = '{{ op }}', id = '{{ id }}', value = '{{ value }}';
if (to_field) {
switch (op) {
case 'create':
if (id) {
var index = parent.layer.getFrameIndex(window.name); //get current iFrame index
parent.layer.close(index); //close
$option = '<option value=' + id + ' selected>' + value + '</option>';
$(to_field, window.parent.document).append($option);
$(to_field + '_change,' + to_field + '_delete', window.parent.document).removeClass('layui-btn-disabled');
}
break;
case 'update':
if (id) {
var index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
$(to_field + ' option[value=' + id + ']', window.parent.document).html(value);
}
break;
}
}
</script>
{% endblock %}

This field is required error on Django using formset

I have three forms, forms.py:
class HotelForm(forms.Form):
rooms = forms.IntegerField(label=(u'Rooms'), min_value=1)
class TouristsForm(forms.Form):
adult = forms.IntegerField(label=(u'Adults'), min_value=1, initial=1)
children = forms.IntegerField(label=(u'Children'), min_value=0, initial=0, required=False)
class ChildrenAgeForm(forms.Form):
children_age = forms.IntegerField(label=(u'Children Age'), min_value=2, max_value=10, initial=2, required=False)
That's how i realize formset and validation in views.py:
def bookingForm(request):
TouristsFormSet = formset_factory(TouristsForm, extra = 1, max_num = 15)
ChildrenAgeFormSet = formset_factory(ChildrenAgeForm, extra = 1, max_num = 20)
if request.method == 'POST':
booking_form = HotelForm(request.POST, prefix='booking_form')
tourists_formset = TouristsFormSet(request.POST, prefix='tourists')
childrenage_formset = ChildrenAgeFormSet(request.POST, prefix='childrenage')
if booking_form.is_valid() and tourists_formset.is_valid() and childrenage_formset.is_valid():
rooms = booking_form.cleaned_data['rooms']
for i in range(0, tourists_formset.total_form_count()):
tourists_form = tourists_formset.forms[i]
tourists = tourists_form.cleaned_data
for n in range(0, childrenage_formset.total_form_count()):
childrenage_form = childrenage_formset.forms[n]
childrenage = childrenage_form.cleaned_data
template = get_template("booking/result.html")
context = Context({'tourists_formset':tourists_formset, 'childrenage_formset':childrenage_formset })
html = template.render(context)
return HttpResponse( html )
else:
booking_form = HotelForm()
tourists_formset = TouristsFormSet(prefix='tourists')
childrenage_formset = ChildrenAgeFormSet(prefix='childrenage')
return render(request, 'booking/booking.html', { 'booking_form' : booking_form, 'tourists_formset' : tourists_formset, 'childrenage_formset' : childrenage_formset })
And this is how i realize html file:
{{ tourists_formset.management_form }}
{% for tourists in tourists_formset %}
{{ tourists }}
{% endfor %}
{{ childrenage_formset.management_form }}
{% for childrenage in childrenage_formset %}
{{ childrenage }}
{% endfor %}
Every time when i fill all fields in the form i have an error 'This field is required' for the HotelForm form. I can't understand why it is happen. Thanks for help
You are using a prefix when handling the POST request.
booking_form = HotelForm(request.POST, prefix='booking_form')
You need to use the same prefix for the GET request.
booking_form = HotelForm(prefix='booking_form')