Saving data from ModelForm - django

I am new to Django and I'm trying to save data using ModelForm. Template 'Vlozit' has a ModelForm and when submitted, I want the data saved in the DB and the redirect to base.html that actually loads the data from the DB and lists the output. The problem is that all works fine but the data is not saved. Please help me find what I am missing. Thank you.
Here's the model:
class Customer(models.Model):
Name = models.CharField(max_length=30)
Description = models.CharField(max_length=150)
Creation_Date = models.DateField(default=datetime.now)
Active = models.BooleanField(default=False)
def __unicode__(self):
return self.Name
Customers = models.Manager()
Here's the ModelForm:
class CustomerForm(forms.ModelForm):
Description = forms.CharField(widget=forms.Textarea)
class Meta:
model = Customer
Here's the view:
def vlozit(request):
if request.method == 'POST':
form = CustomerForm(request.POST, instance=Customer)
if form.is_valid():
form.save(True)
return HttpResponseRedirect(reverse('Base.html'))
else:
form = CustomerForm()
return render_to_response("Vlozit.html", {'form': form}, context_instance = RequestContext(request))
Here's the template 'Vlozit':
{% extends "base.html" %}
{% block head %}
{{ form.media }}
<script>
$(function() {
$( "#id_Creation_Date" ).datepicker();
});
</script>
{% endblock %}
{% block title %}{{block.super}} - Vlozit{% endblock %}
{% block content %}
<div id="content">
<form method="POST" action="{% url url_home %}">
{% csrf_token %}
<table>
<tr>
<td>Name</td>
<td>{{ form.Name }}</td>
</tr>
<tr>
<td>Description</td>
<td>{{ form.Description }}</td>
</tr>
<tr>
<td>Creation Date</td>
<td>{{ form.Creation_Date }}</td>
</tr>
<tr>
<td>Active</td>
<td>{{ form.Active }}</td>
</tr>
</table>
<input type="submit" value="Vlozit">
</form>
</div>
{% endblock content %}

As Timmy says in the comments, you don't catch the case where the form is not valid. Not only do you not show errors in the template, but you also don't even redisplay the template if form.is_valid() is False. Move the last line of the view back one indentation level, and add {{ form.errors }} to the template.

Related

How do I use django_tables2 with a filter?

I'm displaying data on a webpage, and I would like to migrate this code to use the table I created in tables.py. I can't figure out how to do it without breaking the filter.
views.py
def PlatListView(request):
queryset = Plat.objects.all().values('id', 'description','status', 'phase__number','phase','schedule_found').annotate(lot_count=Sum('phase__lot_count')).order_by('description')
f = PlatFilter(request.GET, queryset=queryset)
return render(request, 'blog/filtertable2.html', {'filter': f})
filters.py
class PlatFilter(django_filters.FilterSet):
community = ModelChoiceFilter(queryset=Community.objects.all())
tables.py
import django_tables2 as tables
class PlatTable(tables.Table):
id = tables.Column()
description = tables.Column()
status = tables.Column()
phase__number = tables.Column()
lot_count = tables.Column()
schedule_found = tables.Column()
class Meta:
ordering = 'description'
#model = Plat
filtertable2.html
{% extends "blog/base.html" %}
{% block content %}
{% load bootstrap4 %}
<form method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
<table>
<tr>
<th>Description</th>
<th>Status</th>
</tr>
{% for obj in filter.qs %}
<tr>
<td> {{ obj.description }}</td>
<td>{{ obj.status }}</td>
</tr>
{% endfor %}
</table>
{% endblock content %}
In your view you construct the table with the data from the filter:
def PlatListView(request):
queryset = Plat.objects.annotate(
lot_count=Sum('phase__lot_count')
).order_by('description')
f = PlatFilter(request.GET, queryset=queryset)
table = PlatTable(data=f.qs)
return render(request, 'blog/filtertable2.html', {'filter': f, 'table': table})
You can then render the table with:
{% extends "blog/base.html" %}
{% block content %}
{% load bootstrap4 %}
{% load render_table from django_tables2 %}
<form method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
{% render_table table %}
{% endblock content %}
I do not see any particular reason for using Values QuerySet, ie values(). You can simply annotate the value with queryset:
def plat_list_view(request): # using snake_case when defining a method name.
queryset = Plat.objects.annotate(lot_count=Sum('phase__lot_count')).order_by('description')
f = PlatFilter(request.GET, queryset=queryset)
return render(request, 'blog/filtertable2.html', {'filter': f})

How can I 'bound' a modelformset to an object, fill it and editing in the same page?

I m new in Django and development.
I have a items list, and when I clik on the result button of a test, I would like to have a modelformset for this specific test where i can fill it and editing in the same page.
The code I wrote is 'working' but the problem it's when I fill the form and submit it, it' s editing the same for all the test.
I hope you will understand my explanation( not english speaker)
Here my code:
model.py:
class ResultatTest(models.Model):
id = models.AutoField(primary_key=True)
test = models.ForeignKey('Test', on_delete=models.CASCADE)
services = models.CharField(max_length=30, choices=SERV_CHOICES)
notes = models.IntegerField(null=True)
comments = models.TextField()
def __str__(self):
return self.services
view.py:
def resultatTest(request, id):
id = get_object_or_404(Test, pk=id)
ResultatTestFormset = modelformset_factory(ResultatTest, fields=('test', 'services', 'notes', 'comments'),extra=1)
if request.method == "POST":
formset = ResultatTestFormset(request.POST)#queryset=form.object.filter(test=test_id)
if formset.is_valid():
instances = formset.save(commit= False)
for instance in instances:
instance.save()
else:
formset = ResultatTestFormset()
return render(request, "Portail/Details/resultat.html", {'id': id,'formset': formset})
items/test.html:
onclick ="window.location ='/resultat/{{test.id}}','_self';
url.py:
path('resultat/<int:id>/',resultatTest,name='resultat'),
resultat.html:
<form action="" method="post" id="resultatForm ">
{% csrf_token %}
<table id='supertable' border=1>
{{ formset.management_form }}
{% for form in formset %}
{% if forloop.first %}
<tr>
{% for field in form.visible_fields %}
<td style="background: cyan; line-height:1; white-space:nowrap;width:500px;" >{{ field.label_tag }}</td><
{% endfor %}
</tr>
{% endif %}
<tr>
{% for field in form.visible_fields %}
<td style="background: white; line-height:1; white-space:nowrap;" > {{ field}}</td>
{% endfor %}
</tr>
{ % endfor %}
I have tried and search a lot of things but I cannot solve my problem.

Queryset for current logged in user Django

I am doing queryset with my model. Now the queryset is displaying all the data in my html page. But I want to display only the logged in users data.
models.py
class Data(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Status = models.CharField(max_length=10, blank=False)
Date = models.DateField(blank=True, null=True)
views.py
#login_required
def search(request):
status_list = Data.objects.all()
status_filter = UserFilter(request.GET, queryset=status_list)
return render(request, 'users/data.html', {'filter': status_filter})
filters.py
class UserFilter(django_filters.FilterSet):
class Meta:
model = Data
fields = {
'Date': ['year','month', ], 'user': ['exact', ],
}
I tried with different views.py also but it didn't work.
#login_required
def search(request, user):
status_list = Data.objects.get(user=self.request.user).search(query)
status_filter = UserFilter(request.GET, queryset=status_list)
return render(request, 'users/data.html', {'filter': status_filter})
data.html
<!DOCTYPE html>
{% load django_tables2 %}
{% load staticfiles %}
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
{% block content%}
<form method="get">
{{ filter.form.as_table }}
</select>
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</form>
<ul>
{% for user in filter.qs %}
<li>{{ user.username }} - {{ user.get_full_name }}</li>
{% endfor %}
</ul>
<table id="datatable" style="margin-top: 20px" style="margin-
bottom:20px" class="table table-bordered" >
<thead>
<tr>
<th>user</th>
<th>EndDate</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for Data in filter.qs %}
<tr>
<td>{{ Data.user }}</td>
<td>{{ Data.EndDate }}</td>
<td>{{ Data.Status }}</td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content%}
</body>
Above I added my HTML code also.Please look into html code also.
There could be better ways to do this. As you are still learning below code does the trick.
#login_required
def search(request, *args, **kwargs):
status_list = Data.objects.get(user=request.user)
month = request.GET.get("month", None)
year = request.GET.get("year", None)
if month:
status_list = status_list.filter(Date__month=month)
if year:
status_list = status_list.filter(Date__year=year)
return render(request, 'users/data.html', {'filter': status_list})
You can simplify your code, django provides many helpers function to help to programmer.
in your views.py you can do:
#login_required
def search(request):
status_list = Data.objects.all()
status_filter = status_list.filter(user=request.user) //get current user id
return render(request, 'users/data.html', {'filter': status_filter})
status_list = Data.objects.get(user=self.request.user)
is wrong as self is only used in class based views. No wonder it did not work.
Please try with the below code instead
status_list = Data.objects.filter(user=request.user) or
status_list = Data.objects.get(user=request.user)
So, the final code will be like
#login_required
def search(request):
status_list = Data.objects.get(user=request.user)
render(request, 'users/data.html', {'filter': status_list})
Below code should work fine.
{% for data in filter %}
<li>{{ data.user.username }} - {{ data.user.get_full_name }}</li>
{% endfor %}
{% for Data in filter %}
<tr>
<td>{{ Data.user }}</td>
<td>{{ Data.Date }}</td>
<td>{{ Data.Status }}</td>
</tr>
{% empty %}
As you would not be using filters, so filters.py should be removed.
This will also not work. Make the changes as required.
{{ filter.form.as_table }}

Get ID of a ManyToManyField on ModelForm

I have a particular question envolving the editing of a model with a m2m field that i can't seem to find an answer anywhere. So i have a model, Equipment with an m2m relation to Tests.
models.py:
class Equipment(models.Model):
...
tests = models.ManyToManyField(Test, blank=True)
def __str__(self):
return '%s %s' % (self.manufacturer, self.model)
pass
forms.py:
class EquipmentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
modality = kwargs.pop('modality', None)
super (EquipmentForm, self).__init__(*args, **kwargs)
self.fields['tests'].widget = forms.CheckboxSelectMultiple()
self.fields['tests'].queryset = Test.objects.filter(modality=modality).order_by('group', 'number')
class Meta:
model = Equipment
fields = ['tests']
html:
...
<tbody>
{% for f in form.tests %}
<tr>
<td>{{ f }}</td>
<td>
<a data-toggle="modal" href="{% url 'app:modal' equipament_id=equipament_id test_id=f.id %}" data-target="#tests">See</a>
</td>
</tr>
{% endfor %}
</tbody>
As you can see i am trying to open a modal for each test field in the form so the user can see some information related to that test. This is where i am having trouble because i cant seem to get that f.id to pass it to a view that renders the modal dialog. Any ideas of how to do that? Please help.
First Attempt
{% for field in form.visible_fields %}
{% if field.name == "tests" %}
<table>
{% for choice in field.queryset %}
<tr>
<td><input value="{{choice.id}}" type="radio" name="tests" />{{choice.description}}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% endfor %}
This doesn't work because of the queryset. From the documentation it's not supported for a ModelMultipleChoiceField.
Second Attempt
<table>
<tbody>
{% for pk, choice in form.tests.field.choices %}
<tr>
<td>{{ choice }}</td>
<td><a data-toggle="modal" href="{% url 'SFM:modal' equipment_id=equipment_id test_id=pk %}" data-target="#tests">Ver</a></td>
</tr>
{% endfor %}
</tbody>
</table>
With this approach i am able to pass pk to the view and load the corresponding modal but i lost my form checkbox. If i manually render it i am not able to save any checkbox. This tells me that it is possible to pass the pk to view but maybe it should be acessible by querying the field form and not only in the choice. I am running out of ideas.

How to get the fields from object_list in django template

I am using this as Generci view
book_info = {
"queryset" : Book.objects.all(),
"template_name" : "book/book_lists.html",
}
Now in my template book_lists i have
{% for book in object_list %}
<tr>
<td>{{ book.name }}</td>
Is there any way i can loop through all like we have in form
{% for field in form %}
forn.label_tag and field
so that i can use it for all Models
so basically i want something like
{% for obj in object_list %}
<tr>
{% for fields in obj %}
<td> {{field.name}}:{{field}} </td>
You need to create a get_fields function in your model(s) which you can then use in the templates to access the fields and values generically. Here is a complete example.
books/models.py:
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=30)
author = models.CharField(max_length=30)
isbn = models.IntegerField(max_length=20)
published = models.BooleanField()
def get_fields_and_values(self):
return [(field, field.value_to_string(self)) for field in Book._meta.fields]
templates/books/book_list.html:
<table>
{% for obj in object_list %}
<tr>
{% for fld, val in obj.get_fields_and_values %}
<td>{{ fld.name }} : {{ val }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>