Django automatically add number in table - python

I would like when I add a file in the table it automatically adds a number from 1. I cannot use the primary key in the model because I already use it. anyone have a solution. thank you.
====Page.html====
<h5>Documents</h5>
</div>
<div class="row">
<div class="col-md">
<div class="card card-body">
<table class="table table-sm">
<tr>
<th>#</th>
<th>Nom du fichier</th>
<th>Fichier</th>
<th></th>
</tr>
{% for d in document %}
<tr>
<td>{{d.Number}}</td>
<td>{{d.Description}}</td>
<td><a download href="{{d.Fichier.url}}">{{d.Fichier}}</a></td>
<td><a class="btn btn-outline-danger" href="{% url 'supprimerdocument' d.id %}">Supprimer</a>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
====view.py====
# Button to add docs
#login_required(login_url='loginpage')
#allowed_users(allowed_roles=['admin', 'livraison'])
def createDocument(request):
forms = documentForm()
if request.method == 'POST':
forms = documentForm(request.POST, request.FILES)
if forms.is_valid():
forms.save()
return redirect('/employe')
context = {'forms':forms}
return render(request, 'accounts/document_form.html', context)
====Models.py====
class Document(models.Model):
employe = models.ForeignKey(Employe, null=True, on_delete=models.SET_NULL)
Number = models.IntegerField(default=1)
Description = models.CharField(max_length=100, null=True)
Fichier = models.FileField(upload_to='documents/')
data_created = models.DateTimeField(auto_now_add=True, null=True)
====Form.py====
class documentForm(ModelForm):
class Meta:
model = Document
fields = '__all__'
exclude = ['Number']

You can use forloop.counter in your template to access the (1-indexed) iteration of the for loop
{% for d in document %}
<tr>
<td>{{ forloop.counter }}</td>
...
</tr>
{% endfor %}

It looks like you can do an AutoField as per How do I make an auto increment integer field in Django?
But as a fallback: You could just do an Integer field and override the modelform's .save() method and auto fill it like self.some_field = Document.objects.all().count()
..if you do that, best to add a flag for if it's an edit form or not.. I believe you can do that with if self.instance: if true, is edit form

use callable default
def get_next_number():
max_val = Document.objects.aggregate(models.Max('Number'))['Number__max'] or 0
return max_val + 1
class Document(models.Model):
Number = models.IntegerField(default=get_next_number)
...

Related

Django OneToOneField - Insert Record in another model

I am having the following models. The ItemSettings model has no records inserted initially. I have an HTML table with a link Rules to insert settings data for each item number in the ItemMaster. While adding ItemSettings details. The ItemSettings model will have its own view to edit the details of the settings, once inserted. I don't want the ItemNumber to be displayed as a select dropdown. There can be only one record in the ItemSettings model. I am unable to achieve adding the record in the ItemSettings models with the below code. What am I doing wrong?
Models.py:
class ItemMaster(models.Model):
project_name = models.ForeignKey(ProjectMaster, null=True, on_delete=models.SET_NULL)
item_number = models.CharField(max_length=15, unique=True, error_messages={
'unique': "This Item Number Already Exists!"})
item_type = models.ForeignKey(ItemType, null=True, on_delete=models.SET_NULL)
item_description = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return self.item_number
class ItemSettings(models.Model):
item_number = models.OneToOneField(ItemMaster, on_delete=models.CASCADE)
low_at = models.FloatField(default=0)
minimum_value = models.FloatField(default=0)
maximum_value = models.FloatField(default=0)
def __str__(self):
return str(self.item_number)
Views.py:
def itemsettings_edit(request, pkey):
item_master_data = ItemMaster.objects.get(id=pkey)
item_no = item_master_data.item_number
form = ItemSettingsForm()
if request.method == "GET":
return render(request, 'masters/edit.html', {'item_no': item_no})
elif request.method == 'POST':
try:
item_number = request.POST['item_no']
low_at = request.POST['low_at']
minimum_value = request.POST['minimum_value']
maximum_value = request.POST['maximum_value']
form = ItemSettingsForm(request.POST)
ItemSettings(item_number=item_number, low_at=low_at,
minimum_value=minimum_value, maximum_value=maximum_value).save()
messages.SUCCESS(request, 'Data Saved')
except Exception as e:
messages.SUCCESS(request, 'Data Already Added!!!')
return render(request, 'masters/edit.html', {'item_no': item_no, 'form': form})
edit.html:
<form action="" enctype="multipart/form-data" method="POST" novalidate>
{% csrf_token %}
<table>
<tr>
<td>Item No.</td>
<td><input name="item_number" readonly type="text" value="{{ item_no }}"></td>
</tr>
<tr>
<td>Low At</td>
<td><input name="low_at" type="text"></td>
</tr>
<tr>
<td>Minimum</td>
<td><input name="minimum_value" type="text"></td>
</tr>
<tr>
<td>Maximum</td>
<td><input name="maximum_value" type="text"></td>
</tr>
</table>
<div class="card-action">
<button class="btn waves-effect waves-light btn-small" name="action"
type="submit">Save
</button>
<a class="btn grey darken-3 waves-effect waves-light btn-small"
href="{% url 'itemMaster_list' %}">Cancel</a>
</div>
</form>
Maybe when you get data in this way.
item_number = request.POST['item_no']
is not get correctly, because when you want to save data with relations model you should save data as instance from model like this way:
ItemMaster.objects.get(id=request.POST['item_no'])
and pass the result to ItemSettings.item_number.
If you look at it correctly, the name for item_number field is item_number in HTML not item_no, so it should be:
item_number = request.POST['item_number'] #This is the right name.
...
...

Chained Dropdown in ModelFormset_Factory - Django

I want chained dropdown list in model formset.
I have 4 models in my app App_Prod - Category, Product, OrderInfo, Order
In my form, I used two views combinely. OrderInfo and Order
So the choice list of product field of the Order model should be dependent on the category field of the OrderInfo model. Like if I select Electronics category the choice list should return only laptop and mobile option instead of showing all. See the image for your better understanding.
Please suggest me what should I edit in my codes, or is there any other way to do so.
models.py
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.IntegerField()
category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
def __str__(self):
return self.name
class OrderInfo(models.Model):
category = models.ForeignKey(Category, related_name='orderInfo', on_delete=models.CASCADE)
date = models.DateField()
def __str__(self):
return self.category.name
class Order(models.Model):
info = models.ForeignKey(OrderInfo, related_name='orders', on_delete=models.CASCADE)
product = models.ForeignKey(Product, related_name='productName', on_delete=models.CASCADE, null=True)
quantity = models.IntegerField()
def __str__(self):
return self.product.name
forms.py
class OrderInfoForm(forms.ModelForm):
date = forms.DateField(widget=DateInput)
class Meta:
model = OrderInfo
fields = ["category","date",]
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ["product","quantity",]
widgets = {
'product': forms.Select(attrs={'class': 'formset-field form-control'}),
'quantity': forms.NumberInput(attrs={'class': 'formset-field form-control'}),
}
views.py
def order_create(request):
context = {}
OrderFormset = modelformset_factory(Order, form=OrderForm)
form = OrderInfoForm(request.POST or None)
formset = OrderFormset(request.POST or None, queryset=Order.objects.none(), prefix='productName')
if request.method == "POST":
if form.is_valid() and formset.is_valid():
try:
with transaction.atomic():
info = form.save(commit=False)
info.save()
for order in formset:
data = order.save(commit=False)
data.info = info
data.save()
except IntegrityError:
print("Error Encountered")
return redirect('App_Prod:order_create')
context['formset'] = formset
context['form'] = form
return render(request, 'App_Prod/order_create.html', context)
urls.py
urlpatterns = [
path('create/', views.order_create, name="order_create"),
]
order_create.html
<!DOCTYPE html>
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block body_block %}
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
<table class="table form-table table-bordered table-sm">
<thead class="text-center">
<tr>
<th>Product</th>
<th>Quantity</th>
<th></th>
</tr>
</thead>
<tbody>
{% for form_data in formset %}
<tr class="item">
<td>
{{ form_data.product }}
</td>
<td>
{{ form_data.quantity }}
</td>
<td>
<button type="button" class="btn btn-danger btn-sm remove-form-row"
id="{{ formset.prefix }}">
Delete
</button>
</td>
</tr>
{% endfor %}
<tr>
<td colspan="9"
style="border-left: none!important; border-right: none !important; border-bottom: none!important;">
<button type="button" class="btn btn-sm btn-success add-form-row"
id="{{ formset.prefix }}">
Add Activity
</button>
</td>
</tr>
</tbody>
</table>
{{ formset.management_form }}
<button class="btn btn-info" type="submit">Submit</button>
</form>
{% endblock %}
{% block extra_script %}
<script type="text/javascript" src="{% static 'js/formset.js' %}"></script>
{% endblock%}

django FilterView shows duplicated filter in template

I've got problem with showing filters in my template.
I have view in views.py as follows:
class SearchDocView(FilterView):
template_name = 'searchdoc.html'
context_object_name = 'founddocs'
filterset_class = FilterDoc
paginate_by = 5
def get_queryset(self):
queryset = super(SearchDocView, self).get_queryset()
queryset = FilterDoc(self.request.GET, queryset)
return queryset
I've created my own filter in filters.py:
class FilterDoc(django_filters.FilterSet):
usr_choices=(
('foo.user', 'foo.user'),
('test.user','test.user'),
)
class Meta:
model=Doc
fields = ['doc_application_id','doc_client_nip','user_id']
appid = django_filters.CharFilter(field_name='doc_application_id',lookup_expr='icontains')
nip = django_filters.CharFilter(field_name='doc_client_nip',lookup_expr='icontains')
usrid = django_filters.MultipleChoiceFilter(field_name='user_id', choices=usr_choices)
amd my template is:
<body>
<form method="get">
{{ filter.form.as_p }}
<button type="submit">Search</button>
</form>
{% if founddocs %}
<table>
<thead>
<tr>
<td>DOC APPLICATION ID</td>
...
</tr>
</thead>
<tbody>
<tr>
{% for doc in founddocs %}{#WZORZEC NAZWA MODELU + '_list'#}
<td>{{ doc.doc_application_id }}</td>
...
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>Nothing to see here!.</p>
{% endif %}
</body>
Filters works perfectly. The problem is every time I load the page I see duplicated filter fields. Like this:
Why is that? How can I drop duplicates.
Why user have two different widgets. The second one (combobox) is related with id not username. When I try choose something I got "Field 'id' expected a number but got 'test.user'"
Thanks to #Willem Van Onsem found the problem.
I've replaced fields with fields=[] cause this is nesseccary in Meta class. As to users I've replaced keys to user id according to admin panel
'''
usr_choices=(
(1, 'foo.user'),
(2, 'test.user'),
)
class Meta:
model=Doc
fields=[]
'''

django modelformset_factory raises form not valid: id Select a valid choice. That choice is not one of the available choices

i am trying to create a student attendance sheet in django using django modelformset_factory...but when i save the formset it thows me the id is not valid here is my implementation
i have two models one StudentAttendance and StudentClass:
1: the StudentAttendance model is responsible for stroring students
attendance data here is the example
class StudentAttendance(models.Model):
classroom_id = models.ForeignKey(ClassRoom, on_delete=models.CASCADE, related_name='student_attendance')
attendance_date = models.DateField()
student_id = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='student_attendance')
status = models.CharField(max_length=20, choices=ATTENDANCE_CHOICES)
comment = models.CharField(max_length=150, blank=True)
#signed_by = models.ForeignKey(Teacher, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.student_id)
2: the StudentClass model is a submodel that maps a student to his respective class
class StudentClass(models.Model):
"""
This is a bridge table to link a student to a class
when you add a student to a class we update the selected class capacity
"""
main_class = models.ForeignKey(ClassRoom, on_delete=models.CASCADE, related_name='class_student')
academic_year = models.ForeignKey(AcademicYear, on_delete=models.CASCADE)
student_id = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='student_class')
#property
def is_current_class(self):
if self.academic_year.is_current_session:
return True
return False
def __str__(self):
return str(self.student_id)
So my forms.py implementation is:
class StudentsAttendanceForm(forms.ModelForm):
class Meta:
model = StudentAttendance
fields = ('status', 'comment')
#exclude = [
#'siqned_by',
#]
On my views.py:
def student_attendance_manager(request):
"""
this function is responsible for querying the attendance parameters and present the student multiple attendance form
"""
if request.method == "POST":
# get the class name , the attendance date and present the attendance form
class_name = get_object_or_404(ClassRoom, pk=request.POST['class_name']) # class name
attendance_date = request.POST['date_field'] # date
# get the students in the class which is current active
student = StudentClass.objects.filter(main_class=request.POST['class_name'])
# modelform creation
AttendanceFormSet = modelformset_factory(StudentAttendance, form=StudentsAttendanceForm, extra=0)
# initiate the form and pass in the required parameters ie: classroom_id, attendance_date
list_formset = AttendanceFormSet(queryset=student)
# initialise the class_name and attendance date
#for form_inst in list_formset:
#form_inst.fields['classroom_id'].initial = class_name
#form_inst.fields['attendance_date'].initial = attendance_date
template = 'attendance/students_attendance_form.html'
context = {
'class_name':class_name,
'attendance_form': list_formset,
}
return JsonResponse({'html_form': render_to_string(template, context, request=request)})
template = 'attendance/students_attendance_manager.html'
class_date_selector_form = ClassroomDateQueryForm(request.GET or None)
context = {
'choice_form':class_date_selector_form
}
return render(request, template, context)
when the User Posts the form to be submited this is how i handle the form:
def student_attendance_register(request):
if request.method == "POST":
students = StudentClass.objects.filter(main_class=request.GET['class_id'])
StudentsAttendanceFormSet = modelformset_factory(StudentAttendance, form=StudentsAttendanceForm, extra=0)
list_formset = StudentsAttendanceFormSet(request.POST, queryset=students)
if list_formset.is_valid():
list_formset.save()
return HttpResponse('valid')
else:
return HttpResponse(list_formset.errors)
on my template i display the form in a table and this is my implementation:
form.html:
<form class="js-mark-attendance" method="post" action="{% url 'attendance:student_attendance_register' %}?class_id={{ class_name.id }}">
{% csrf_token %}
<table class="table-striped table table-bordered" id="Student_attendance_table">
<thead>
<tr>
<th>#</th>
<th>Admission Number</th>
<th>Name</th>
<th>Status</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
{{ attendance_form.management_form }}
{% for form_inst in attendance_form %}
{% for hidden in form_inst.hidden_fields %}
{{ hidden }}
{% endfor %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ form_inst.instance.student_id.admission_number }}</td>
<td>{{ form_inst.instance.student_id }}</td>
<td>{{ form_inst.status }}</td>
<td> {{ form_inst.comment }}</td>
{{ form_inst.classroom_id.as_hidden }}
{{ form_inst.attendance_date.as_hidden }}
{{ form_inst.student_id.as_hidden }}
</tr>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col-md-12 d-flex justify-content-center">
<input type="submit" value="Mark Attendance" class="btn btn-success">
</div>
</div>
</form>
and this is the error that django throws after the user has clicked submit button:
id
Select a valid choice. That choice is not one of the available choices.
so my question is ... how can i handle this post request form and or if their is an alternative way of doing my task:
any leads will be much upreciated
oops....I found my problem was the wrong usage of modelsfomset_factory...

django get value from html

I want to list all tables using my Crawledtables, and when i click table1 i need to pass in the table_id. With that table_id i need to get the table_name and list all the info inside that table. i m stuck at getting the table_id
this is my views.py
EDITED views.py
def table_base(request):
table_name = Crawledtables._meta.db_table
list_tables = Crawledtables.objects.order_by('id')
return render(request, 'tables/table_base.html', {'table_name': table_name,
'list_tables': list_tables})
class AboutDetail(DetailView):
model = Crawledtables
pk_url_kwarg = 'table_id'
template_name = 'tables/table_list.html'
def __init__(self, **kwargs):
super(AboutDetail, self).__init__(**kwargs)
def get_object(self, **kwargs):
if 'table_id' not in self.kwargs:
return Crawledtables.objects.get(id=1)
else:
id_table = Crawledtables.objects.get(id=self.kwargs['table_id'])
return id_table
# need to create another fuction and i need to pass on the table_id
# with this table_id i need to get the table_name
# need to use the table_name to get the content using
# Ex: test = AllTables.objects.all()
# i need to return the the content of the table id
this is my table_base.html
<br>
<div class="container">
<div class="jumbotron">
<h1> {{ table_name }} List</h1>
{% if list_tables %}
<table class="table table-bordered sortable">
<thead>
<th>Id</th>
<th>Name</a></th>
<th>Date</a></th>
<th>Search Button</th>
</thead>
{% for list in list_tables %}
<tr>
<td><pre><a href="#" >{{ list.id }}</a></pre></td>
{# this is where i get the id of the table in CrawledTables and i set it equal to table_id #}
<td><pre>{{ list.name }}</pre></td>
<td><pre>{{ list.date }}</pre></td>`
</tr>
{% endfor %}
</table>
{% else %}
<p> No Records Found</p>
{% endif %}
</div>
</div>
and this is what i have for now for table_list.html
<table class="table table-bordered sortable">
<thead>
<tr>
{{ context }}
<th>Id</th>
<th>Title</th>
<th>Url</th>
</tr>
</thead>
{# make a for loop here #}
<tr>
<td> </td> {# get the id #}
<td></td> {# get the title #}
<td></td> {# get the url #}
</tr>
{% endfor %}
</table>
I ve tried to figure out without using requests or forms...i did get it...but i got stuck at creating a search engine...so now i have to go back to do it the right way using request and/or forms...
Please help me i really don't know what command i need to put...and those django docs don't really help me because its more about users and passwd and emails...
Thank you in advance
UPDATE
models.py
#python_2_unicode_compatible
class Crawledtables(models.Model):
name = models.CharField(db_column='Name', unique=True, max_length=100)
date = models.CharField(db_column='Date', max_length=100)
class Meta:
managed = True
db_table = 'CrawledTables'
def __str__(self):
return self.name
def __unicode__(self):
return '%name' % {'name': self.name}
#python_2_unicode_compatible
class AllTables(models.Model):
title = models.TextField(db_column='Title', blank=True, null=True)
url = models.CharField(db_column='Url', unique=True, max_length=250, blank=True,
null=True)
created_at = models.DateTimeField(db_column='Created_at')
class Meta:
managed = False
def __str__(self):
return self.url
def __unicode__(self):
return self.title
forms.py
class TableIdForm(forms.Form):
class Meta:
fields = ('id', 'name','date')
model = Crawledtables
class AllTablesForm(forms.Form):
title = forms.CharField(label='title')
url = forms.CharField(label='url', max_length=250)
created_at = forms.DateTimeField(label='Created at')

Categories

Resources