Django upload csv to DB via template with function - django

I made a function with "runscript" on Django. I wanna know how can I upload a CSV file via a template with my function.
this is my function:
def run():
df = pd.read_csv("scripts/Combination.csv", dtype=str)
df = df[pd.isnull(df["id"])]
def sub_budget_owner_found(v_BO, v_SBO):
try:
Employee.objects.get_or_create(name=v_BO)
v_BO_obj = Employee.objects.get(name=v_BO)
except:
v_BO_obj = Employee.objects.get(name="99999 No Budget Owner")
try:
Employee.objects.get_or_create(name=v_SBO)
v_SBO_obj = Employee.objects.get(name=v_SBO)
except:
v_SBO_obj = Employee.objects.get(name="99998 No Sub Budget Owner")
return SubBudgetOwner.objects.get_or_create(
budget_owner=v_BO_obj, sub_budget_owner=v_SBO_obj
)
for i, row in df.iterrows():
v_subsidiary = row["Subsidiary"]
v_department = row["Department"]
v_account = row["Account"]
v_sub_budget = row["Sub Budget"]
v_budget_owner = row["Budget Owner"]
v_sub_budget_owner = row["Sub Budget Owner"]
Combination.objects.get_or_create(
subsidiary=Subsidiary.objects.get_or_create(name=str(v_subsidiary))[0],
department=Department.objects.get_or_create(name=str(v_department))[0],
account=Account.objects.get_or_create(name=str(v_account))[0],
sub_budget=SubBudget.objects.get_or_create(name=str(v_sub_budget))[0],
budget_owner=sub_budget_owner_found(v_budget_owner, v_sub_budget_owner)[0],
)
print(i, row)
I use Django view classes. The purpose is to upload new data via CSV file in the GUI.
Thanks a lot

So I found a solution for this.
my urls.py
path("combinationimport/", views.import_combination, name="combination_import"),
in my views.py
def import_combination(request):
if "GET" == request.method:
return render(request, "budget/combination_import.html", {})
else:
excel_file = request.FILES["excel_file"]
wookbook = openpyxl.load_workbook(excel_file)
worksheet = wookbook.active
print(worksheet)
data = worksheet.values
# Get the first line in file as a header line
columns = next(data)[0:]
df = pd.DataFrame(data, columns=columns)
def sub_budget_owner_found(v_BO, v_SBO):
try:
Employee.objects.get_or_create(name=v_BO)
v_BO_obj = Employee.objects.get(name=v_BO)
except:
v_BO_obj = Employee.objects.get(name="99999 No Budget Owner")
try:
Employee.objects.get_or_create(name=v_SBO)
v_SBO_obj = Employee.objects.get(name=v_SBO)
except:
v_SBO_obj = Employee.objects.get(name="99998 No Sub Budget Owner")
return SubBudgetOwner.objects.get_or_create(
budget_owner=v_BO_obj, sub_budget_owner=v_SBO_obj
)
new_data_entry = []
excel_data = list()
# iterating over the rows and
# getting value from each cell in row
for row in worksheet.iter_rows():
row_data = list()
for cell in row:
row_data.append(str(cell.value))
excel_data.append(row_data)
for i, row in df.iterrows():
v_subsidiary = row["Subsidiary"]
v_department = row["Department"]
v_account = row["Account"]
v_sub_budget = row["Sub Budget"]
v_budget_owner = row["Budget Owner"]
v_sub_budget_owner = row["Sub Budget Owner"]
combo = Combination.objects.get_or_create(
subsidiary=Subsidiary.objects.get_or_create(name=str(v_subsidiary))[0],
department=Department.objects.get_or_create(name=str(v_department))[0],
account=Account.objects.get_or_create(name=str(v_account))[0],
sub_budget=SubBudget.objects.get_or_create(name=str(v_sub_budget))[0],
budget_owner=sub_budget_owner_found(v_budget_owner, v_sub_budget_owner)[
0
],
)
if combo[1] == True:
new_data_entry.append(f"Row #{i+2}: {combo[0]}")
return render(
request,
"budget/combination_import.html",
{"excel_data": excel_data, "new_data_entry": new_data_entry},
)
combination_import.html
XLSX FILE
<form action="{% url "budget:combination_import" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file"
title="Upload excel file"
name="excel_file"
style="border: 1px solid black; padding: 5px;"
required="required">
<p>
<br>
<input type="submit" value="Upload" style="padding:5px 15px;
background:#3CBC8D;
border:0 none;
cursor:pointer;
-webkit-border-radius: 5px;
border-radius: 5px;">
</form>
<hr>
<p>New Records:</p>
{% for q in new_data_entry %}
<p style="background-color:green; color:white">{{ q }}</p>
{% endfor %}
<hr>
<p>All Records:</p>
{% for row in excel_data %}
{% for cell in row %}
{{ cell }}
{% endfor %}
<br>
{% endfor %}
I hope it will help.

Related

Django nested forms

I have trouble figuring out how to create nested forms. I have two models: Poll and Question (foreign key for Poll is inside Question model). I want it to be possible to add several questions for the poll dynamically inside one form. I've already tried making it work with inlineform_factory, but found troubles saving the form. Right now I have overcomplicated code that throws MultiValueDictError after saving the poll for the second time. I thought maybe there is some other way. Here's my code
models.py
class Question(models.Model):
type_choices = (
('text', 'Текстовый'),
('integer', 'Числовой'),
)
type = models.CharField(verbose_name=u'Тип вопроса', choices=type_choices, max_length=70)
text = models.CharField(verbose_name=u'Текст вопроса', max_length=255)
poll = models.ForeignKey('Poll', on_delete=models.CASCADE, related_name='questions')
class Poll(BaseFields):
objects = models.Manager()
published = PublishedManager()
title = models.CharField(verbose_name=u'Заголовок', max_length=70)
date_from = models.DateTimeField(u'Дата начала')
date_to = models.DateTimeField(u'Дата окончания')
status = models.IntegerField(choices=Status.choices, default=0)
def status_name(self):
return dict(Status.choices).get(self.status)
def update_url(self):
return reverse('poll_update', args=(self.id, ))
forms.py
QuestionInlineFormSet = inlineformset_factory(Poll, Question, extra=1, can_delete=False,
fields=('type', 'text', 'poll'),
widgets={
'type': w.Select(attrs={'class': 'form-control'}),
'text': w.TextInput(attrs={'class': 'form-control'}),
})
class PollForm(CommonForm):
class Meta(CommonForm.Meta):
model = Poll
views.py
class Create(BaseCreateView):
template_name = 'back/poll/poll.html'
page_title = 'Создание опроса'
model = Poll
form_class = PollForm
def form_valid(self, form):
result = super(Create, self).form_valid(form)
questions_formset = QuestionInlineFormSet(data=form.data, instance=self.object, prefix='questions_formset')
if questions_formset.is_valid():
questions_formset.save()
return result
def get_context_data(self, **kwargs):
context = super(Create, self).get_context_data(**kwargs)
context['questions_formset'] = QuestionInlineFormSet(prefix='questions_formset')
return context
class Update(BaseUpdateView):
template_name = 'back/poll/poll.html'
page_title = 'Редактирование опроса'
model = Poll
form_class = PollForm
def form_valid(self, form):
result = super(Update, self).form_valid(form)
questions_formset = QuestionInlineFormSet(data=form.data, instance=self.object, prefix='questions_formset')
if questions_formset.is_valid():
questions_formset.save()
return result
def get_context_data(self, **kwargs):
context = super(Update, self).get_context_data(**kwargs)
context['questions_formset'] = QuestionInlineFormSet(instance=self.get_object(), prefix='questions_formset')
return context
poll.html
{% extends 'back/base/form/base.html' %}
{% block form %}
{% include "back/includes/status_buttons.html" %}
<div class="row">
<div class="col-md-7">
<div class="row" style="margin-bottom: 15px;">
<div class="col-md-12">
{% include 'back/includes/status_label.html' %}
</div>
</div>
{% include "back/base/form/field.html" with field=form.title %}
{% include "back/base/form/datetime_field.html" with field=form.date_from %}
{% include "back/base/form/datetime_field.html" with field=form.date_to %}
{{ questions_formset.management_form }}
{% for question_form in questions_formset %}
{% include "back/poll/question.html" with form=question_form %}
{% endfor %}
<div style="float: right; margin-right: 45px">
<button class="btn btn-success add-form-row">Добавить вопрос</button>
</div>
</div>
</div>
{% endblock %}
question.html
<div class="questions">
<div class="row form-row">
<div class="form-group col-md-5{% if form.type.errors %} has-error{% endif %}">
<label>{{ form.type.label }}</label>
{{ form.type }}
<p class="help-block">{{ form.type.errors }}</p>
</div>
<div class="form-group col-md-5{% if form.text.errors %} has-error{% endif %}">
<label>{{ form.text.label }}</label>
{{ form.text }}
<p class="help-block">{{ form.text.errors }}</p>
</div>
<div class="col-md-2" style="margin-top: 25px">
<button type="button" class="btn btn-danger remove-form-row">✕</button>
</div>
</div>
</div>
<script>
function updateElementIndex(el, prefix, ndx) {
let id_regex = new RegExp('(' + prefix + '-\\d+)');
let replacement = prefix + '-' + ndx;
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function deleteForm(prefix, btn) {
let total = parseInt($('#id_' + prefix + '_formset' + '-TOTAL_FORMS').val());
if (total > 1) {
btn.closest('.form-row').remove();
let forms = $('.form-row');
$('#id_' + prefix + '_formset' + '-TOTAL_FORMS').val(forms.length);
for (let i = 0, formCount = forms.length; i < formCount; i++) {
$(forms.get(i)).find(':input').each(function () {
updateElementIndex(this, prefix, i);
});
}
}
}
function cloneMore(selector, prefix) {
let newElement = $(selector).clone(true);
let total = $('#id_' + prefix + '_formset' + '-TOTAL_FORMS').val();
newElement.find(':input:not([type=button]):not([type=submit]):not([type=reset])').each(function () {
let name = $(this).attr('name').replace('-' + (total - 1) + '-', '-' + total + '-');
let id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
});
newElement.find('label').each(function () {
let forValue = $(this).attr('for');
if (forValue) {
forValue = forValue.replace('-' + (total - 1) + '-', '-' + total + '-');
$(this).attr({'for': forValue});
}
});
total++;
$('#id_' + prefix + '_formset' + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
}
$(document).on('click', '.add-form-row', function (event) {
event.preventDefault();
cloneMore('.form-row:last', 'questions');
})
$(document).on('click', '.remove-form-row', function (event) {
event.preventDefault();
deleteForm('questions', $(this));
});
</script>
Here's a photo of what it should look like
Again, I want it to be possible to add questions, remove them, save the form. And after I click on the poll in the list of all polls and go to it's edit page I want already added questions to be there.
UPDATE
Found solution to MultiValueDictKeyError in this post
How to debug a Django MultiValueDictKeyError on Formset POST
Now the only problem I have is removing Questions from Poll. My delete button works, it removes the form from page, but after saving the document it reappears.

How submit a query redirecting a form on django

I'm trying to send a value from my index to a list page where I have some filters. I can send the value but it take a MultiValueDictKeyError.
I use Djagno 3.1.7, jQuery and Ajax for this exercise. I think the error is in the Ajax because it returns value "all" and the button value.
This is my index form html:
<form action="wallacar_app/lista/" method="GET" class="trip-form">
<label for="tipos">Tipo</label><br>
{% for tipo in tipos %}
<button name="type_car" value="{{ tipo.type_car }}" id="{{ tipo.type_car }}" class="form-control px-3 btn-primary btn">{{ tipo.type_car }}</option>
{% endfor %}
</form>
This is my list.html:
<div class="col-sm-2 col-2">
<div class="form-group">
<label for="type_car">TIPO DE COCHE</label>
<select class="form-control" id="type_car"
url = "{%url 'wallacar_app:get_type' %}">
<option value='all' selected>TODOS LOS TIPOS</option>
</select>
</div>
</div>
<table class="table table-bordered"
id="list_data" data-toggle="table" url = "{% url 'wallacar_app:listing' %}">
<thead>
<tr>
<th style="text-align: center;background-color: #007bff;" data-field="brand">RESULTADOS</th>
</tr>
</thead>
<tbody id="listing">
</tbody>
</table>
The Ajax code for list.html:
$('#type_car').on('change', function () {
// get the api data of updated variety
if(this.value)
send_data['type_car'] = this.value;
else
if(this.value == "all")
send_data['type_car'] = "";
else
send_data['type_car'] = this.value;
getAPIData();
});
function getType() {
// fill the options of provinces by making ajax call
// obtain the url from the provinces select input attribute
let url = $("#type_car").attr("url");
// makes request to getProvince(request) method in views
$.ajax({
method: 'GET',
url: url,
data: {},
success: function (result) {
type_option = "<option value='all' selected>TODOS LOS TIPOS</option>";
$.each(result["type_car"], function (a, b) {
type_option += "<option>" + b + "</option>"
});
$("#type_car").html(type_option)
},
error: function(response){
console.log(response)
}
});
}
My urls.py:
urlpatterns = [
path('lista/', CocheList),
path("listado_coches/", CocheListing.as_view(), name = 'listing'),
path("ajax/type/", getType, name = 'get_type'),
]
My views.py:
def CocheList(request):
return render(request,'wallacar_app/cars.html', {})
class CocheListing(ListAPIView):
pagination_class = StandardResultsSetPagination
serializer_class = CocheSerializers
def get(self, request):
if request.method == "GET" and request.GET['type_car']:
return render(request, 'wallacar_app/cars.html')
def get_queryset(self):
queryList = Coche.objects.all()
type_car = self.request.query_params.get('type_car',None)
if type_car:
queryList = queryList.filter(type_car = type_car)
def getBrand(request):
if request.method == "GET" and request.is_ajax():
brand = Coche.objects.order_by('brand').values_list('brand').distinct()
brand = [i[0] for i in list(brand)]
data = {'brand':brand}
return JsonResponse(data, status = 200)
def getType(request):
if request.method == "GET" and request.GET['type_car']:
type_car = Coche.objects.filter(type_car=request.GET['type_car']).order_by('type_car').values_list('type_car').distinct()
type_car = [i[0] for i in list(type_car)]
data = {'type_car':type_car}
#return JsonResponse(data,status=200)
return render(request, 'wallacar_app/cars.html', data)
elif request.method == "GET" and request.is_ajax() and not request.GET['type_car']:
type_car = Coche.objects.exclude(type_car__isnull=True).exclude(type_car__exact='').order_by('type_car').values_list('type_car').distinct()
type_car = [i[0] for i in list(type_car)]
data = {'type_car':type_car}
return JsonResponse(data,status=200)

django how to filter data before exporting to csv

I'm very beginner in django. Now I'm working on my first very simple application.
I have a working filter:
def filter_view(request):
qs = My_Model.objects.all()
index_contact_contains_query = request.GET.get('index_contact_contains')
nr_order_contains_query = request.GET.get('nr_order_contains')
user_contains_query = request.GET.get('user_contains')
date_min = request.GET.get('date_min')
date_max = request.GET.get('date_max')
if is_valid_queryparam(index_contact_contains_query):
qs = qs.filter(index_contact__icontains = index_contact_contains_query)
elif is_valid_queryparam(nr_order_contains_query):
qs = qs.filter(nr_order__icontains = nr_order_contains_query)
elif is_valid_queryparam(user_contains_query):
qs = qs.filter(nr_user = user_contains_query)
if is_valid_queryparam(date_min):
qs = qs.filter(add_date__gte = date_min)
if is_valid_queryparam(date_max):
qs = qs.filter(add_date__lt = date_max)
if export == 'on':
?????????????? - export file
context = {
'queryset':qs
}
return render(request,'filter.html',context)
I have also working function for export data to csv file:
def download_csv(request):
items = My_Model.objects.all()
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="export.csv"'
writer = csv.writer(response)
writer.writerow(['index_contact','nr_order','result','nr_user','tools','add_date'])
for obj in data:
writer.writerow([obj.index_contact, obj.nr_order, obj.result, obj.nr_user, obj.tools, obj.add_date])
return response
My question is... how to connect both functions and export csv file with filtered data.
I also have a request... Please give me a hint as for a beginner
Thanks for any suggestions
You can "inline" the logic from your download_csv view function:
def filter_view(request):
qs = My_Model.objects.all()
index_contact_contains_query = request.GET.get('index_contact_contains')
nr_order_contains_query = request.GET.get('nr_order_contains')
user_contains_query = request.GET.get('user_contains')
date_min = request.GET.get('date_min')
date_max = request.GET.get('date_max')
export = request.GET.get('export')
if is_valid_queryparam(index_contact_contains_query):
qs = qs.filter(index_contact__icontains = index_contact_contains_query)
elif is_valid_queryparam(nr_order_contains_query):
qs = qs.filter(nr_order__icontains = nr_order_contains_query)
elif is_valid_queryparam(user_contains_query):
qs = qs.filter(nr_user = user_contains_query)
if is_valid_queryparam(date_min):
qs = qs.filter(add_date__gte = date_min)
if is_valid_queryparam(date_max):
qs = qs.filter(add_date__lt = date_max)
if export == 'on':
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="export.csv"'
writer = csv.writer(response)
writer.writerow(['index_contact','nr_order','result','nr_user','tools','add_date'])
for obj in qs:
writer.writerow([obj.index_contact, obj.nr_order, obj.result, obj.nr_user, obj.tools, obj.add_date])
return response
context = {
'queryset':qs
}
return render(request,'filter.html',context)
The missing part here is that your are not preserving Form inputs, that is why you are getting the full items = My_Model.objects.all() downloaded because is_valid_queryparam(index_contact_contains_query) returns false (when you select input values and then click the filter button, the selected input values return to blank).
So in order to preserve Form inputs:
First, modifying Willem answer, pass all request.GET values as context:
def filter_view(request):
qs = My_Model.objects.all()
index_contact_contains_query = request.GET.get('index_contact_contains')
nr_order_contains_query = request.GET.get('nr_order_contains')
user_contains_query = request.GET.get('user_contains')
date_min = request.GET.get('date_min')
date_max = request.GET.get('date_max')
export = request.GET.get('export')
if is_valid_queryparam(index_contact_contains_query):
qs = qs.filter(index_contact__icontains = index_contact_contains_query)
elif is_valid_queryparam(nr_order_contains_query):
qs = qs.filter(nr_order__icontains = nr_order_contains_query)
elif is_valid_queryparam(user_contains_query):
qs = qs.filter(nr_user = user_contains_query)
if is_valid_queryparam(date_min):
qs = qs.filter(add_date__gte = date_min)
if is_valid_queryparam(date_max):
qs = qs.filter(add_date__lt = date_max)
if export == 'on':
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="export.csv"'
writer = csv.writer(response)
writer.writerow(['index_contact','nr_order','result','nr_user','tools','add_date'])
for obj in qs:
writer.writerow([obj.index_contact, obj.nr_order, obj.result, obj.nr_user, obj.tools, obj.add_date])
return response
context = {
'queryset':qs
'values': request.GET ### this way
}
return render(request,'filter.html',context)
Second, modify your filter.html inputs values and options depending on your input types:
For <input type="date"> and <input type="text"> inputs are pretty much straightforward:
<!-- Date input -->
<div class="form-group col-md-2 col-lg-2">
<label for="publishDateMin">Start date:</label>
<input type="date" class="form-control" id="publishDateMin"
name="date_min"
{% if values %}
value={{values.date_min}}
{% endif %}>
</div>
<!-- text input -->
<div class="form-group col-md-2 col-lg-2">
<label for="contactIndex">Contact index:</label>
<input type="text" class="form-control" id="contactIndex"
name="index_contact_contains"
{% if values %}
value={{values.index_contact_contains}}
{% endif %}>
</div>
For <select name="user_contains" class="form-control"><option value="...">...</option> is a bit different. Let's assume you want to select an user name from a list of user name options:
<!-- Select with options input -->
<div class="form-group col-md-2 col-lg-2">
<label for="userName">User name:</label>
<select name="user_contains" class="form-control" id="userName">
<option selected="true" disabled="disabled"> All users </option>
<!-- Looping through queryset to insert options -->
<!-- Here i am assuming you have an user_name column in My_Model -->
{% for s in queryset %}
<option value="{{s.user_name}}" {% if s.user_name == values.user_contains %} selected {% endif %}>
{{ s.user_name }}
</option>
{% endfor %}
</div>

Django: How can I combine 2 formsets as one so as to display as one inline table (of course with pagination) in template

Say I have 3 models: Groups, Answers, and Questions (Group as ForeignKey and models are broken for normalization). I have created corresponding formsets for Answers and Questions for these models.
On selection of a group, my goal is to display related Answers and Questions in a inline table on form. Something like this:
I am able to get formsets in a template and display them in separate sections, but not able to display them as one table (I don't want to do this using HTML-JS). Is there any way I can pass the answer and question formsets as one context object so that they can be displayed as one table in the template?
Note: there may be 5 questions but only 3 answers for a group, or vice versa.
Also, it would be nice to add pagination to this inline table (or the formsets).
urls.py:
from django.conf.urls import url
from .views import lists, load_questions
from django.urls import path
urlpatterns = [
url(r'lists', lists, name="lists"),
path('ajax/load_questions/', load_questions, name='load_questions'),
]
I have as of now:
models.py:
from django.db import models
from django.utils.timezone import now
class Groups(models.Model):
class Meta:
verbose_name_plural = "Groups"
group = models.CharField(max_length=30)
group_description = models.CharField(max_length=4000,default=None,null=True)
group_date = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.group
def save(self,*args,**kwargs):
if(self.group and self.group_date is None):
self.group_date=now()
super(Groups,self).save(*args,**kwargs)
class Questions(models.Model):
class Meta:
verbose_name_plural = "Questions"
question = models.CharField(max_length=30,verbose_name="Input Question")
question_description = models.CharField(max_length=4000 ,default=None)
question_date=models.DateTimeField(blank=True,null=True)
question_group = models.ForeignKey(Groups, on_delete=models.CASCADE)
def __str__(self):
return self.question
def save(self,*args,**kwargs):
if(self.question and self.question_date is None):
self.question_date=now()
super(Questions,self).save(*args,**kwargs)
class Answers(models.Model):
class Meta:
verbose_name_plural = "Answers"
answer = models.CharField(max_length=100,verbose_name="Your Answer")
answers_description = models.CharField(max_length=4000,default=None,help_text="",blank=True,null=True)
answer_date = models.DateTimeField(blank=True, null=True)
answer_group = models.ForeignKey(Groups, on_delete=models.CASCADE,blank=True)
#valid_question = models.ManyToManyField("Questions",related_name="answers")
print("Model Called")
def __str__(self):
return self.answer
def save(self,*args,**kwargs):
if(self.answer and self.answer_date is None):
self.answer_date=now()
super(Answers,self).save(*args,**kwargs)
forms.py:
from django.forms import inlineformset_factory,Textarea,BaseFormSet
from django.forms.models import modelformset_factory
from .models import Groups,Questions,Answers
from django import forms
class groupForm(forms.Form):
group = forms.CharField(label="Group",max_length=100)
def choices(self):
a=[('','Select a Group')]
return a+[ (o.id, str(o)) for o in Groups.objects.all()]
def __init__(self, *args, **kwargs):
super(groupForm, self).__init__(*args, **kwargs)
print([(o.id, str(o)) for o in Groups.objects.all()])
print(type([(o.id, str(o)) for o in Groups.objects.all()]))
self.fields['group'] = forms.ChoiceField(
choices=self.choices(),
required=True,
)
#self.fields['group'].label = "Select Group"
from crispy_forms.helper import FormHelper, Layout
class questionForm(forms.ModelForm):
class Meta:
model = Questions
#fields = ['question', 'question_description',]
exclude = ()
questionFormSet = modelformset_factory(Questions, form=questionForm, extra=1)
class answerForm(forms.ModelForm):
class Meta:
model = Groups
exclude = ()
def add_fields(self, form, index):
"""A hook for adding extra fields on to each form instance."""
super(answerForm, self).add_fields(form, index)
# here call a custom method or perform any other required action
form.set_index(index)
#answerFormSet = modelformset_factory(Answers, form=answerForm, extra=1)
questionFormSet = inlineformset_factory(Groups, Questions,form=answerForm)
answerFormSet = inlineformset_factory(Groups, Answers,form=answerForm)
#myFormset=questionFormSet|answerFormSet
views.py:
from django.shortcuts import render, redirect
from .models import Answers, Questions, Groups
# Create your views here.
from .forms import groupForm,questionFormSet,answerFormSet
from django.http import JsonResponse
def lists(request):
if request.method == 'POST':
questionsform = questionFormSet(request.POST)
answersform = answerFormSet(request.POST)
groupsform = groupForm(request.POST)
print(answersform.is_valid())
print(answersform.errors.as_data())
if answersform.is_valid() and groupsform.is_valid() and questionsform.is_valid():
print("in views")
print(answersform.cleaned_data)
print(type(groupsform.cleaned_data))
a=Answers(answer=answersform.cleaned_data['answer'],
answers_description="",
answer_group=Groups(groupsform.cleaned_data['group']))
a.save()
q = Questions(question=questionsform.cleaned_data['question'],
question_description="",
question_group=Groups(groupsform.cleaned_data['group']))
q.save()
return redirect('lists')
else:
return redirect('chatbot_welcome')
else:
context = {
'groups': groupForm,
'questions': questionFormSet,
'answers': answerFormSet,
}
return render(request, 'lists.html', context)
def load_questions(request):
group_id = request.GET.get ('groupId')
data = {
"Table": {
"TR": [
]
}
}
if group_id is not None:
questions = (Questions.objects.filter(question_group=group_id).values("question", "question_group"))
answers = (Answers.objects.filter(answer_group=group_id).values("answer", "answer_group"))
l_len = len(questions) if len(questions) >= len(answers) else len(answers)#lambda can be used here
for i in range(l_len):
try:
if list(questions)[i]["question"]:
q=list(questions)[i]["question"]
except:
q=''
try:
if list(answers)[i]["answer"]:
a=list(answers)[i]["answer"]
except:
a=''
data["Table"]["TR"].append({
"row": i+1,
"group": group_id,
"question": q,
"Answer": a
})
print(data)
return JsonResponse(data)
else:
return JsonResponse(data)
Template:
{% extends "base.html" %}
{% load staticfiles %}
{% block content %}
{% load crispy_forms_tags %}
<form method="post" id="groupform" data-group-url="{% url 'load_questions' %}">
{% csrf_token %}
<div class="panel-group" id="accordion18" style="display: block;">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion18" href="#accBody20" id="accHeading20" class="">Groups</a>
</h4>
</div>
<div class="panel-collapse collapse in" id="accBody20" style="height: auto;">
<div class="panel-body">
<div class="row"><div class="col-md-12"><div class="form-group">
<div class="form-group">
{{ groups }}
Create a New Group
</div></div></div></div>
</div>
</div>
</div>
</div>
<div class="panel-group" id="accordion21" style="display: block;">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion21" href="#accBody23" id="accHeading23" class="">Questionnaires</a>
</h4>
</div>
<div class="panel-collapse collapse in" id="accBody23" style="height: auto;">
<div class="panel-body">
<div class="row"><div class="col-md-12"></div></div><div class="row"><div class="col-md-12"><div class="form-group">
<div class="panel-body">
<span>{{groups.group.name|title }}</span>:<span id="group">None</span>
{{questions.forms}}
{% for form in questions.forms %}
{% for field in form %}
field={{field}}
{% endfor %}
{% endfor %}
<table>
<thead>
{% for form in questions.forms %}
{% if forloop.first %}
{% for field in form %}
<th>{{ field.label_tag }}</th>
{% endfor %}
{% endif %}
</thead>
<tbody>
<tr>
{% for field in form %}
<td>{{ field }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<table>
<thead>
{% for form in answers.forms %}
{% if forloop.first %}
{% for field in form %}
<th>{{ field.label_tag }}</th>
{% endfor %}
{% endif %}
</thead>
<tbody>
<tr>
{% for field in form %}
<td>{{ field }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<!--
<form action="" method="post">
{% csrf_token %}
{% crispy questions %}{% crispy answers %}
</form>
-->
<input type="button" class="add-row" value="Add Row">
<button type="button" class="delete-row">Delete Row</button>
</div>
<div class="panel-body">
<div class="tbl_user_data"></div>
</div>
<button id="button40" type="submit" value="Submit" class="btn btn-primary">Submit</button></div></div></div></div>
</div>
</div>
</div>
</form>
<script>
var groupId=0;
$("#id_group").change(function () {
var url = $("#groupform").attr("data-group-url"); // get the url of the `load_cities` view
groupId = $(this).val(); // get the selected country ID from the HTML input
$('#group').text(groupId);
$.ajax({ // initialize an AJAX request
url: url,
//data: $("#groupform").serialize(),
dataType: 'json',// set the url of the request (= localhost:8000/hr/ajax/load-cities/)
data: {
'groupId': groupId // add the country id to the GET parameters
},
success: function (data) { // `data` is the return of the `load_cities` view function
var data1={
"Table": {
"TR": [
{
"row": 1,
"group": 1,
"question": "heyy",
"Answer": "hey"
},
{
"row": 2,
"group": 1,
"question": "y",
"Answer": "heyy"
},
{
"group": 1,
"row": 3,
"question": "How are you",
"Answer": "Fine"
}
]
}
}
//questions_list=JSON.parse(data.questions)[0].question;
//alert(questions_list)
//answers_list=JSON.parse(data.answers)[0].answer;
//alert(answers_list)
writeintoTable(data)
//alert('done')
}
});
});
function runOnLoad(){
//alert(1)
}
var random_id = function ()
{
var id_num = Math.random().toString(9).substr(2,3);
var id_str = Math.random().toString(36).substr(2);
return id_num + id_str;
}
function writeintoTable(data){
/*
$.each(data.Table.TR, function( index, json ) {
//alert(index +" -- "+ data.Table.TR[index].question)
$("#setupbody").append('<tr><td>'
+data.Table.TR[index].row+
'</td><td>'
+data.Table.TR[index].group+
'</td><td>'
+data.Table.TR[index].question+
'</td><td>'
+data.Table.TR[index].Answer+
'</td></tr>');
});*/
/*
for (i=0;i<=data.Table.TR;i++)
{
$("#setupbody").append('<tr><td></td><td>1</td><td>Hi</td><td>Hello</td></tr>');
}*/
var tbl = '';
tbl +='<table class="table table-hover">'
//--->create table header > start
tbl +='<thead>';
tbl +='<tr>';
tbl +='<th>Select</th>';
tbl +='<th>Row</th>';
tbl +='<th>Group</th>';
tbl +='<th>Question</th>';
tbl +='<th>Answer</th>';
tbl +='<th>Options</th>';
tbl +='</tr>';
tbl +='</thead>';
//--->create table header > end
//--->create table body > start
tbl +='<tbody>';
//--->create table body rows > start
$.each(data.Table.TR, function(index, val)
{
//you can replace with your database row id
var row_id = random_id();
//loop through ajax row data
tbl +='<tr row_id="'+row_id+'">';
tbl +='<td><input type="checkbox" value="" name="record" id="cb'+val['row']+'"></td>'
tbl +='<td ><div class="row_data" edit_type="click" col_name="rnum">'+val['row']+'</div></td>';
tbl +='<td ><div class="row_data" edit_type="click" col_name="fname">'+val['group']+'</div></td>';
tbl +='<td ><div class="row_data" edit_type="click" col_name="lname">'+val['question']+'</div></td>';
tbl +='<td ><div class="row_data" edit_type="click" col_name="email">'+val['Answer']+'</div></td>';
//--->edit options > start
tbl +='<td>';
tbl +='<span class="btn_edit" > <a href="#" class="btn btn-link " row_id="'+row_id+'" > Edit</a> </span>';
//only show this button if edit button is clicked
tbl +='<span class="btn_save"> Save | </span>';
tbl +='<span class="btn_cancel"> Cancel | </span>';
tbl +='</td>';
//--->edit options > end
tbl +='</tr>';
});
//--->create table body rows > end
tbl +='</tbody>';
//--->create table body > end
tbl +='</table>'
//--->create data table > end
//$("#dataTable").append(tbl);
$(document).find('.tbl_user_data').html(tbl);
$(document).find('.btn_save').hide();
$(document).find('.btn_cancel').hide();
}
//--->make div editable > start
$(document).on('click', '.row_data', function(event)
{
event.preventDefault();
if($(this).attr('edit_type') == 'button')
{
return false;
}
//make div editable
$(this).closest('div').attr('contenteditable', 'true');
//add bg css
$(this).addClass('bg-warning').css('padding','5px');
$(this).focus();
})
//--->make div editable > end
//--->save single field data > start
$(document).on('focusout', '.row_data', function(event)
{
event.preventDefault();
if($(this).attr('edit_type') == 'button')
{
return false;
}
var row_id = $(this).closest('tr').attr('row_id');
var row_div = $(this)
.removeClass('bg-warning') //add bg css
.css('padding','')
var col_name = row_div.attr('col_name');
var col_val = row_div.html();
var arr = {};
arr[col_name] = col_val;
//use the "arr" object for your ajax call
$.extend(arr, {row_id:row_id});
//out put to show
$('.post_msg').html( '<pre class="bg-success">'+JSON.stringify(arr, null, 2) +'</pre>');
})
//--->save single field data > end
//--->button > edit > start
$(document).on('click', '.btn_edit', function(event)
{
event.preventDefault();
var tbl_row = $(this).closest('tr');
var row_id = tbl_row.attr('row_id');
tbl_row.find('.btn_save').show();
tbl_row.find('.btn_cancel').show();
//hide edit button
tbl_row.find('.btn_edit').hide();
//make the whole row editable
tbl_row.find('.row_data')
.attr('contenteditable', 'true')
.attr('edit_type', 'button')
.addClass('bg-warning')
.css('padding','3px')
//--->add the original entry > start
tbl_row.find('.row_data').each(function(index, val)
{
//this will help in case user decided to click on cancel button
$(this).attr('original_entry', $(this).html());
});
//--->add the original entry > end
});
//--->button > edit > end
//--->button > cancel > start
$(document).on('click', '.btn_cancel', function(event)
{
event.preventDefault();
var tbl_row = $(this).closest('tr');
var row_id = tbl_row.attr('row_id');
//hide save and cacel buttons
tbl_row.find('.btn_save').hide();
tbl_row.find('.btn_cancel').hide();
//show edit button
tbl_row.find('.btn_edit').show();
//make the whole row editable
tbl_row.find('.row_data')
.attr('edit_type', 'click')
.removeClass('bg-warning')
.css('padding','')
tbl_row.find('.row_data').each(function(index, val)
{
$(this).html( $(this).attr('original_entry') );
});
});
//--->button > cancel > end
//--->save whole row entery > start
$(document).on('click', '.btn_save', function(event)
{
event.preventDefault();
var tbl_row = $(this).closest('tr');
var row_id = tbl_row.attr('row_id');
//hide save and cacel buttons
tbl_row.find('.btn_save').hide();
tbl_row.find('.btn_cancel').hide();
//show edit button
tbl_row.find('.btn_edit').show();
//make the whole row editable
tbl_row.find('.row_data')
.attr('edit_type', 'click')
.removeClass('bg-warning')
.css('padding','')
//--->get row data > start
var arr = {};
tbl_row.find('.row_data').each(function(index, val)
{
var col_name = $(this).attr('col_name');
var col_val = $(this).html();
arr[col_name] = col_val;
});
//--->get row data > end
//use the "arr" object for your ajax call
$.extend(arr, {row_id:row_id});
//out put to show
$('.post_msg').html( '<pre class="bg-success">'+JSON.stringify(arr, null, 2) +'</pre>')
});
//--->save whole row entery > end
$(".add-row").click(function(){
var question = $("#id_question").val();
//var group = $("#group").val();
var answer = $("#id_answer").val();
if (question=='' || question=='undefined'||answer=='' || answer=='undefined' )
{
alert('row not complete to add')
return false;
}
//var markup = "<tr><td><input type='checkbox' name='record'></td><td>" + name + "</td><td>" + email + "</td></tr>";
var tbl = '';
//you can replace with your database row id
var row_id = random_id();
//loop through ajax row data
tbl +='<tr row_id="'+row_id+'">';
tbl +='<td><input type="checkbox" value="" name="record" id="cb'+100+'"></td>'
tbl +='<td ><div class="row_data" edit_type="click" col_name="rnum">'+100+'</div></td>';
tbl +='<td ><div class="row_data" edit_type="click" col_name="fname">'+groupId+'</div></td>';
tbl +='<td ><div class="row_data" edit_type="click" col_name="lname">'+question+'</div></td>';
tbl +='<td ><div class="row_data" edit_type="click" col_name="email">'+answer+'</div></td>';
//--->edit options > start
tbl +='<td>';
tbl +='<span class="btn_edit" > <a href="#" class="btn btn-link " row_id="'+row_id+'" > Edit</a> </span>';
//only show this button if edit button is clicked
tbl +='<span class="btn_save"> Save | </span>';
tbl +='<span class="btn_cancel"> Cancel | </span>';
tbl +='</td>';
//--->edit options > end
tbl +='</tr>';
$("table tbody").append(tbl);
$(document).find('.btn_save').hide();
$(document).find('.btn_cancel').hide();
});
// Find and remove selected table rows
$(".delete-row").click(function(){
var r = confirm("Selected Row will be deleted.");
if (r == true) {
$("table tbody").find('input[name="record"]').each(function(){
if($(this).is(":checked")){
$(this).parents("tr").remove();
}
});
} else {
$("table tbody").find('input[name="record"]').each(function(){
if($(this).is(":checked")){
$(this).prop('checked', false);
}
});
alert("Row(s) not Deleted!");
}
});
</script>
{% endblock %}

django dynamic add form fields

Based on this i want to write a dynamic template, where i can dynamicly add forms with choosen width.
Models:
class TodoList(models.Model):
SEC = 'section'
DIV = 'div'
SECCHOICES = (
(SEC, "Section"),
(DIV, "Div"),
)
tag = models.CharField(max_length=20, choices=SECCHOICES, default=SEC)
def __unicode__(self):
return self.name
class TodoItem(models.Model):
COL16 = '16'
COL25 = '25'
COL33 = '33'
COL50 = '50'
COL66 = '66'
COL75 = '75'
COL100 = '100'
CHOICES = (
(COL16, "16%"),
(COL25, "25%"),
(COL33, "33%"),
(COL50, "50%"),
(COL66, "66%"),
(COL75, "75%"),
(COL100, "100%"),
)
width = models.CharField(max_length=3, choices=CHOICES, default=COL100)
list = models.ForeignKey(TodoList)
def __unicode__(self):
return self.name + " (" + str(self.list) + ")"
View:
def post_list(request):
posts = TodoItem.objects.order_by('id')
return render(request, 'blog/post_list.html', {'posts': posts})
Template:
{% for post in posts %}
<{{ post.list.tag }}>
<div class="column{{ post.width }}" >
</div>
</{{ post.list.tag }}>
{% endfor %}
Output is:
Section: col, Section: col, Section: col, Section: col
And i wish:
Section: col, col, col, col
Happy about any Ideas, Sorry if something is too stupid – im very new to django/python
You can do that by doing this only?
<{{ post.list.tag }}>
{% for post in posts %}
<div class="column{{ post.width }}" >
</div>
{% endfor %}
</{{ post.list.tag }}>