django formset template loop through fields disables delete featuer - python

Thank you for being here.
I am not able to delete objects in django formset While i am looping through the fields in templates the.
I can see the deletion box but when i hit submit the page refreshes and the object is exist.
template.html
{% for form in request_equipment_form %}
<div class="card" style="width: 100% ">
<div class="card-body">
<div class="d-flex flex-row" style="width:100%">
{{form.equipment}}
{{form.quantity}}
{{form.DELETE}}
{{form.ORDER}}
</div>
</div>
{% endfor %}
But when i do not loop through the fields the delete feature works like charm
{% for form in request_equipment_form %}
<div class="card" style="width: 100% ">
<div class="card-body">
<div class="d-flex flex-row" style="width:100%">
{{form.as_p}}
</div>
</div>
{% endfor %}
views.py
if formset.is_valid():
instances = formset.save(commit=False)
for d_obj in formset.deleted_objects:
d_obj.delete()
if not instances:
return redirect(request.META.get('HTTP_REFERER'))
for instance in instances:
instance.user = request.user
instance.flight = flight
instance.station = flight.station
instances = formset.save(commit=False)
for instance in instances:
instance.save()
print(instance.date)
return redirect(request.META.get('HTTP_REFERER'))

When you loop through forms in a formset you need to include the the management form for things to work:
<form method="post">
{{ formset.management_form }}
{% for form in formset %}
{% for field in form %}
{{ field.label_tag }} {{ field }}
{% endfor %}
{% endfor %}
</form>
Also, you should consider using the CSRF token ({% csrf_token %}) to secure your form.

Related

Django form fields not rendering when grouping fields

I am using Django 4.0.3 with a bootstrap webinterface.
For layout reasons I want my fields in a ModelForm to be grouped and I'm doing it with:
class UserForm(ModelForm):
template_name = "container/form.html"
field_groups = [["email", "company"], ["last_name", "first_name"]]
grouped_fields = []
class Meta:
model = MyUser
fields = ["email", "company", "first_name", "last_name"]
__init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
def group_fields(self):
for group in self._field_groups:
group_entry = []
for entry in group:
group_entry.append(self.fields[entry])
self.grouped_fields.append(group_entry)
in the view I initialize my form and the regroup the fields:
def user_form(request):
form = UserForm()
form.group_fields()
render(request, "page.html, {"form", form})
The page.html looks like this:
<body>
<div id="form-wrapper">
{{ form }}
</div>
</body>
and the form.html looks like this:
<form action="" method="POST">{% csrf_token %}
{% for field_group in form.grouped_fields %}
<div class="row">
{% for field in field_group %}
<div class="col">
<label>{{ field.label }}</label> {{ field }}
</div>
{% endfor %}
</div>
{% endfor %}
However the rendered fields are displayed as string representations of the field objects:
Email <django.forms.fields.EmailField object at 0x7f98c00e03a0>
Company <django.forms.fields.CharField object at 0x7f98c00e0250>
Last name <django.forms.fields.CharField object at 0x7f98c00e0790>
First name <django.forms.fields.CharField object at 0x7f98c00e10c0>
Whereas a common call renders as expected a form with input fields, but not with the desired layout.
{% for field in form %}
<div class="row">
<div class="col">
{{ field.label_tag }} {{ field }}
</div>
</div>
{% endfor %}
I also tried to move the call of the group_fields method to the form init but had no success.
Is there a way to render the fields, that are stored in my grouped_fields container correctly?
After quiet a time of trying this and that I ended up writing a wrapper for ModelForm, define my field_groups there and rendered it in the template.
It is not nice, but it does the trick.
<form action="" method="post">
{% for fieldgroup in form.field_groups %}
<div class="row fieldgroup">
{% for fieldname in fieldgroup %}
{% for field in form %}
{% if field.name == fieldname %}
<div class="col pt-2">
<label class="form-label">{{ field.label }}</label>
{{ field }}
</div>
{% endif %}
{% endfor %}
{% endfor %}
</div>
{% endfor %}
<button type="submit">Submit</button>
</form>

Filter templates by ChoiceField - Django

consider this model on Django:
class My_model(models.Model):
my_choices = { '1:first' 2:second'}
myfield1=CharField()
myfield2=CharField(choices=my_choices)
Then on my form:
class My_form(forms.ModelForm):
class Meta:
model = My_model
fields = ['myfield1', 'myfield2']
My views:
def get_name(request):
if request.method == 'POST':
form = My_form(request.POST)
if form.is_valid():
return HttpResponseRedirect('/')
else:
form = My_form()
return render(request, 'form/myform.html', {'form': form})
On my template:
{% extends "base.html" %}
{% block content %}
<form action="/tlevels/" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{% endblock %}
On my base.html, I will load this template like this:
{% extends "base.html" %}
{% block content %}
{% load crispy_forms_tags %}
<div class="p-3 mb-2 bg-info text-white" style="margin-left:20px; margin-bottom:20px;">Status</div>
<div class="form-row" style="margin-left:20px; margin-bottom:20px; margin-top:20px;">
<div class="form-group col-md-6 mb-0">
{{ form.myfield1|as_crispy_field }}
</div>
<div class="form-group col-md-6 mb-0">
{{ form.myfield2|as_crispy_field }}
</div>
</div>
<input type="submit" class="btn btn-primary" value="Submit" style="margin-left:20px;">
</form>
{% endblock %}
What I want, is to have 2 other different templates, with whatever difference on them, and load them depending on the choice made on the ChoiceField, I guess that one way could be on the view, by adding some kind of conditional, and load a different template (html file).
Any ideas?
It is possible to use {% include %} with a variable.
def some_view_after_post(request):
# ... lookup value of myfield2 ...
return render(request, "path/to/after_post.html", {'myfield2: myfield2})
The in the after_post.html template:
<!-- include a template based on user's choice -->
<div class="user-choice">
{% include myfield2 %}
</div>
You'll want to make sure there is no possible way the user can inject an erroneous choice. For example, make sure the value of myfield2 choice is valid before adding it to the context.

Django: redirect user two pages back

I have a list of multiple objects from my database (named "plp's"), arranged in a table. Next to each "plp" element I have a button "Edit" to modify that particular entry.
Next, I redirect the user to a new url, where I pass the id of that "plp", and show the form to edit it, with a "save" button.
After pressing the "save", which is request.POST, I want to redirect the user back to the first url, with the list of all the "plp" objects in one list. That means to the site, where he first pressed "Edit".
Can I somehow save the url of where the "Edit" was clicked, and pass it to my views.py?
Thank you
listdns.html:
<td>
Uredi
</td>
urls.py:
rl(r'^(?P<plp_id>\d+)/uredi$', plp_list_uredi,name="plpuredi")
views.py:
def plp_list_uredi(request, plp_id=None):
moj_plp=PLPPostavka.objects.get(id=plp_id)
form=PLPPostavkaForm(request.POST or None,request=request,dns=moj_plp.dns, instance=moj_plp)
context ={
'plp':moj_plp,
'form':form,
}
if request.POST:
if form.is_valid():
plp = form.save()
return redirect(request.path)
return render(request, "plp_pos/uredi.html",context)
uredi.html
<form action="" method="POST">
{% csrf_token %}
<div class="box">
<div class="box-header">
<h4 class="box-title">
Urejanje PLP Postavke
</h4>
</div>
<div class="box-body">
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}" class="col-md-2 control-label detail">{{ field.label }}</label>
<div class="col-md-10">
{% if field|field_type == "datefield" %}
{% render_field field class+="form-control dateinput" %}
{% else %}
{% render_field field class+="form-control" %}
{% endif %}
</div>
</div>
{% endfor %}
</div>
<div class="box-footer">
<div class="box-tools pull-right">
<input type="submit" value="Shrani" class="btn btn-primary" />
</div>
</div>
Don't you only have 1 page to edit all the elements? Then you could perhaps hardcode the link e.g.
return HttpResponseRedirect(my_edit_url)
If this doesn't work and you need to go 2 pages back take a look at this post:
How to redirect to previous page in Django after POST request

Django user selects multiple images from gallery and saves it as strings in database backend

Im trying to create a form where the user selects from a gallery of images and it saves it to the database. The code below currently renders some radio buttons in the html output. Is there anyway I can change these to images i have saved in a static directory so the user can click on images instead? Would be great if I could change what it saves in the database to what I needed instead of image urls as well. Theres lots of documentation on uploading images but not much I could find on selecting images. Im using django 1.9.7 and python 3.5
models.py
client_choices = (('client1', 'Client 1'),
('client2', 'Client 2'),
('client3', 'Client 3'),
('client4', 'Client 4'),
('client5', 'Client 5'))
class ClientSelect(models.Model):
client = MultiSelectField(choices=client_choices)
forms.py
from app.models import ClientSelect
class ClientSelectForm(forms.ModelForm):
class Meta:
model = ClientSelect
fields = '__all__'
views.py
class FormWizard(SessionWizardView):
template_name = "app/clientchoices.html"
#define what the wizard does when its finished collecting information
def done(self, form_list, **kwargs):
form_data = process_form_data(form_list)
return render_to_response('app/about.html', {'form_data': form_data})
urls.py
url(r'^clientchoices$', FormWizard.as_view([ClientSelectForm]) , name='clientchoices'),
clientchoices.html
{% load staticfiles %}
{% block content %}
<section class="content">
<div class="container">
<div class="fit-form-wrapper">
<h2>Client Choices</h2>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
{% for field in form %}
{{field.error}}
{% endfor %}
<form action="{% url 'clientchoices' %}" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button class="btn btn-brand" name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">"First Step"</button>
<button class="btn btn-brand" name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"Previous Step"</button>
{% endif %}
<input class="btn btn-brand" type="submit" value="Submit" />
</form>
</div>
</div>
</section>
{% endblock %}
Any help is appreciated thank you

Create a custom html template using forms in Django

I've been going over the docs and some StackOverflow examples but I'm still having a little trouble. In Django I created a form, the view renders it and I have it displayed as form.as_p in the HTML template. This works perfectly, but I would like to be able to customize my HTML template instead of having it displayed as form.as_p. Any examples on how to do so?
So far I have the following.
View:
#login_required
def register(request):
info = Content.objects.get(id=request.user.id)
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES, instance=info)
if form.is_valid():
info = form.save(commit=False)
info.save()
return HttpResponseRedirect('/portal/register')
else:
form = UploadFileForm(instance=info)
return render(request, 'portal/register.html', {'form': form, 'gallery': info})
Form:
class UploadFileForm(ModelForm):
logo = forms.ImageField(required=False)
image1 = forms.ImageField(required=False)
terms = forms.CharField(required=False)
class Meta:
model = Content
fields = ['user', 'logo', 'image1', 'terms']
Model:
class Content(models.Model):
user = models.ForeignKey(User)
logo = models.ImageField(upload_to=content_file_name, null=True, blank=True)
image1 = models.ImageField(upload_to=content_file_name, null=True, blank=True)
terms = models.CharField(max_length="256", blank=True)
def __unicode__(self):
return self.title
HTML Template:
<form method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
{% if gallery.logo %}
<img class="img-responsive" id="logo" src="/media/{{ gallery.logo }}" alt="">
{% else %}
<img class="img-responsive" id="logo" src="/media/images/placeholder.png" alt="">
{% endif %}
</a>
<input type="file" name="logo" id="logo" multiple>
</div>
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<a class="thumbnail" href="#">
{% if gallery.image1 %}
<img class="img-responsive" id="image1" src="/media/{{ gallery.image1 }}" alt="">
{% else %}
<img class="img-responsive" id="image1" src="/media/images/placeholder.png" alt="">
{% endif %}
</a>
<input type="file" name="image1" id="image1" multiple>
</div>
<div class="form-group">
<input type="text" name="terms" id="terms" class="form-control input-sm" placeholder="terms" value="{{ gallery.terms }}">
</div>
<input type="submit" value="Submit" />
</form>
Yes you can loop on the form fields by doing the following
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
<label>
{{ field.label_tag }}
</label>
<div>
{{ field }}
</div>
</div>
{% endfor %}
Then you can add class to the div and label tags and style the form fields
You can also use Django Widget Tweaks to add classed to the form fields.
Click here to read in more details
By using widget tweaks you simply find the field in which you want to add the class by doing this
{% load widget_tweaks %}
{{ form.name|add_class:"inputContact volunteer" }}
You can render the fields manually:
We don’t have to let Django unpack the form’s fields; we can do it
manually if we like (allowing us to reorder the fields, for example).
Each field is available as an attribute of the form using {{
form.name_of_field }}, and in a Django template, will be rendered
appropriately.
Example from the documentation:
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="{{ form.subject.id_for_label }}">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="{{ form.message.id_for_label }}">Your message:</label>
{{ form.message }}
</div>
As I said in the comments, see also Django Crispy Forms. You can achieve the same without so much markup.

Categories

Resources