How to split form to two columns? - django

I have model:
class Post(models.Model):
path = 'images' + str(datetime.now().year) + '/' + str(datetime.now().month)
image = models.ImageField(upload_to=path, null=True)
recommended = models.BooleanField(default = False)
promoted = models.BooleanField(default = False)
title = models.TextField(blank = True)
intro = RichTextField(config_name='full_ck', blank = True)
text = RichTextField(config_name='full_ck', blank = True)
, form:
class Form(forms.ModelForm):
id = forms.ModelChoiceField(queryset=Post.objects.all(), widget=forms.HiddenInput())
class Meta:
model = Post
and template:
<table cellpadding="0" cellspacing="0">
<formset>
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
<div class="fieldWrapper">
{% if field.errors %}<div class="errorbox">{% endif %}
<p>{{ field.label_tag }}</p>
<p>{{ field }}{% block formextrafields %}{% endblock %}</p>
<p></p>
{% if field.errors %}<p>{{ field.errors }}</p></div>{% endif %}
</div>
{% endif %}
{% endfor %}
</formset>
</table>
But I want to divide form to two columns. In first may be intro, text and title fields and in second others. How to do it?

I use this in view:
form = list(form)
, in model I set order with:
class Meta:
model = Post
fields = (my fields in order)
and in template:
<!-- first -->
<table cellpadding="0" cellspacing="0">
<formset>
{% for field in form|slice:":3" %}
[...]
{% endfor %}
</formset>
</table>
<!-- second -->
<table cellpadding="0" cellspacing="0">
<formset>
{% for field in form|slice:"3:" %}
[...]
{% endfor %}
</formset>
</table>
And it works.

You could use crispy forms for the layout and to add css classes: https://github.com/maraujop/django-crispy-forms

Related

How can i display count of each column in django

Display
I would like to count the number of students for each subjects but currently it only displays the number of students for one subject. it only counts the number of student for one subject but i would like to count the number of students in each subject
Added the models.py. Ps still new to django
views.py
class SubjectView(TemplateView):
template_name='subjects.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
username=self.request.user.id
#filter subject taught by lecturer
classdets=ClassDetail.objects.all().filter(teacher=username).values_list('subject_id')
print(classdets)
#filters all subjects from the class details
subj=Subject.objects.filter(id__in=classdets)
print(subj)
#counts number of students
subjID=Subject.objects.values('id')
num_student=ClassDetail.objects.filter(id__in=subjID).count
print(num_student)
context['subjects'] = subj
context['no_students'] = num_student
return context
template
{% extends "base.html" %}
{% load static %}
{% block title %}Subjects{% endblock title %}
{% block sidenavbar %}
{% include 'partials/sidenavbar.html' %}
{% endblock %}
{% block navbar %}
{% include 'partials/navbar.html' %}
{% endblock %}
{% block subject %}
<div class="container-fluid">
<div class="col">
<div class="card bg-transparent">
<!-- Card header -->
<div>
<div class="card-header bg-transparent border-0">
<h3 class="mb-0" style="text-transform: uppercase">Current Subjects</h3>
{% comment %} View Students {% endcomment %}
</div>
</div>
<!-- Translucent table -->
<div class="table-responsive">
<table class="table align-items-center table-flush" id="datatable-buttons">
<thead class="thead-light">
<tr>
<th>Subject Name</th>
<th>Subject Code</th>
<th>Number of Students</th>
{% comment %} <th>Generate Attendance Code</th> {% endcomment %}
</tr>
</thead>
{% if user.is_authenticated %}
{% for subject in subjects %}
<tbody class="list" style="text-transform: capitalize">
<tr>
<th scope="row">
<div class="media align-items-center">
<a href="#" class="avatar rounded-circle mr-3">
{% if subject.thumbnail %}
<img alt="Logo" src="{{subject.thumbnail.url}}" />
{% endif %}
</a>
<div class="media-body">
<span class="name mb-0 text-sm">{{subject}}</span>
</div>
</div>
</th>
<td class="budget">{{subject.code}}</td>
<td>
<div class="d-flex align-items-center">
<span class="completion mr-2">{{no_students}}</span>
</div>
</td>
<td>
{% comment %}
<div class="d-flex align-items-center">
<span class="completion mr-2">{{attendace_code}}</span>
</div>
{% endcomment %}
</td>
</tr>
</tbody>
{% endfor %}
{% endif %}
</table>
</div>
</div>
</div>
</div>
{% endblock %}
models
def get_thumbnail(instance, filename):
path = f"static/assets/img/custom/{filename}"
return path
class Subject(models.Model):
code=models.CharField(max_length=8,unique=True,default="")
name=models.CharField(max_length=100,unique=True)
thumbnail=models.ImageField(blank=True,null=True,upload_to=get_thumbnail)
def __str__(self):
return f'{self.name}'
class Meta:
unique_together = ('name', 'code')
class ClassDetail(models.Model):
teacher=models.ForeignKey(UserProfile,on_delete=models.PROTECT)
subject=models.ForeignKey(Subject, on_delete=models.PROTECT, default="")
student=models.ManyToManyField(UserProfile,related_name="student")
def __str__(self):
return f'{self.subject}'
class Meta:
unique_together = ('teacher', 'subject')
userprofile
class UserProfile(AbstractUser):
ROLE_LECTURER = 'lecturer'
ROLE_STUDENT = 'student'
ROLE_ADMIN = 'admin'
ROLE_CHOICES = (
(ROLE_LECTURER, _('Lecturer')),
(ROLE_STUDENT, _('Student')),
(ROLE_ADMIN, _('Admin')),
)
STATUS_ACTIVE = 'active'
STATUS_INACTIVE = 'inactive'
STATUS_SUSPENDED = 'suspended'
STATUS_EXPIRED = 'expired'
STATUS_CHOICES = (
(STATUS_ACTIVE, _('Active')),
(STATUS_INACTIVE, _('Inactive')),
(STATUS_SUSPENDED, _('Suspended')),
(STATUS_EXPIRED, _("Expired")),
)
username = models.CharField(max_length=11, unique=True, verbose_name="Relevant ID")
status = models.CharField(_('status'), max_length=50, choices=STATUS_CHOICES, default=STATUS_ACTIVE)
role = models.CharField(_('role'), max_length=50, choices=ROLE_CHOICES, default="")
def __str__(self):
return f'{self.username} ({self.first_name})'
USERNAME_FIELD = 'username'
num_student =subjID.classdetail_set.all().count()
print(num_student)

Custom format an inline formset

I'm create a template in Django, adding a form and formset to the template, but I don't like how it's formatting the formset by default. I've tried .as_table and .as_ul, but it's not formatting it to my liking. I'd like to see the following from the formset:
Ingredient Percentage Delete
ingredient1 .55
ingredient2 .22
ingredient3 .33
I've tried the code in "https://stackoverflow.com/questions/17492374/how-to-render-formset-in-template-django-and-create-vertical-table" but when I implement it, I'm getting two extra column, "ID" and "Recipe Name". I don't know where those columns are coming from and I don't know how to get rid of them.
Example:
models.py
class Recipe(models.Model):
name = models.CharField(max_length=200, null=True)
description = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
return self.name
class Recipe_Ingredient(models.Model):
recipe_name = models.ForeignKey(Recipe, null=True, on_delete = models.SET_NULL)
ingredient = models.ForeignKey(Product, null=True, on_delete= models.SET_NULL)
recipe_percent = models.DecimalField(max_digits=8, decimal_places=5, blank=True)
views.py
def recipeUpdate(request, recipe_id):
RecipeIngredientFormSet2 = inlineformset_factory(Recipe, Recipe_Ingredient, extra=10, fields=('ingredient', 'recipe_percent'))
recipe = Recipe.objects.get(pk=recipe_id)
formset = RecipeIngredientFormSet2(instance=recipe)
context = {'formset' : formset}
return render(request, 'accounts/recipe_form.html', context)
recipe_form.html
{% extends 'accounts/main.html' %}
{% load static %}
{% block content %}
<div class="row">
<div class="col-md-6">
<div class="card card-body">
<form action="" method="POST">
{{ form }}
<p></p>
<!--{{ formset.as_table }}-->
<p></p>
{{ formset.management_form}}
<!--{% for form in formset %}
{{ form }}
{% endfor %}-->
<table>
<thead>
{% for form in formset %}
{% 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>
<input type="submit" name="Submit">
</form>
</div>
</div>
</div>
{% endblock %}
Found the answer. You've got to add the formset with a .management_form tag, then in table, loop through each form in form set. If it's the first loop, add the headers to the tables. In all other loops, add each field from the form that you want in the table.
The updated HTML that I'm using is below.
{% extends 'accounts/main.html' %}
{% load static %}
{% block content %}
<div class="row">
<div class="col-md-6">
<div class="card card-body">
<form action="" method="POST">
{% csrf_token %}
{{ form }}
{{ formset.management_form }}
<table>
{{ form.id }}
{% for p in formset %}
<tr>
{% if forloop.first %}
<td>{{ p.DELETE.label_tag }}</td>
<td>{{ p.ingredient.label_tag }}</td>
<td>{{ p.recipe_percent.label_tag }}</td>
<p></p>
{% endif %}
</tr>
<!--{{ p.id }}
{{ p.ORDER }}-->
<tr></tr>
<td>{{ p.DELETE }}</td>
<td>{{ p.ingredient }}</td>
<td>{{ p.recipe_percent }}</td>
</tr>
{% endfor %}
</table>
<input type="submit" name="Submit">
</form>
</div>
</div>
</div>
{% endblock %}

Django - How to change dropdown form into table

I'm creating an application in Django and I'm having an issue with iterating through options in a dropdown from a form in Django. I was wondering if anyone could be of assistance.
detail.html
{% for subject in subject_list %}
<form action="" method="POST">
{% csrf_token %}
<table class='table table-borderless table-hover'>
<tbody>
<tr>
<td>{{ subject.subjectname }}
{% for field in form %}
{{ field.hidden }}
{% endfor %}
</td>
</tr>
</tbody>
</table>
<button type="submit" id="login-btn" class="btn">Create a new evaluation</button>
</form>
{% endfor %}
forms.py
class CreateEvalForm(forms.ModelForm):
subjectname = ModelChoiceField(queryset=Subject.objects, label='', empty_label="Choose subject..")
class Meta:
model = Evaluation
fields = ['subjectname', ]
models.py
class Subject(models.Model):
id = models.AutoField(primary_key=True)
subjectname = models.CharField(max_length=255, help_text="Type the name of the subject.")
slug = models.SlugField(max_length=200, unique=True)
Ideally we want it to look like on the picture below:
Note that the picture is in danish and Fag = Subject, Opret ny evaluering = Create new evaluation and Se evaluering = View evaluation
we want this
we don't want this
I solved this with the help from the comments by changing my for loop and table to this:
<form action="" method="POST">
{% csrf_token %}
<table class='table table-borderless table-hover'>
{% for option in form.fields.fagnavn.choices %}
{% if not forloop.first %}
<tbody>
<tr>
<td>{{ option.1 }}</td>
<td><button value="{{ option.0 }}" name="fagnavn">Opret ny evaluering</button></td>
</tr>
</tbody>
{% endif %}
{% endfor %}
</table>
</form>
I gained access to the choices in the dropdown with form.fields.fagnavn.choices and excluded the default value of "choose value" with an if statement of {% if not forloop.first %}
And that's pretty much it.

Django formset for models without foreign key

I'm trying to use formset to create connections between my Neo4j nodes. These models have been constructed using the django-neomodel package. They aren't related using foreign keys, but since this isn't an inline formset that shouldn't matter, right?
models.py
class Person(DjangoNode):
uid = UniqueIdProperty()
name = StringProperty(max_length=50)
created_at = DateTimeProperty(default=datetime.now)
friends = RelationshipTo('Friend', 'FRIENDED', model=FriendRel)
# DjangoNode class must have a Meta class and documentation specifies 'django_node'
class Meta:
app_label = 'django_node'
class FriendRel(DjangoRel):
created_at = DateTimeProperty(default=datetime.now)
class Meta:
app_label = 'django_rel'
forms.py
class PersonForm(forms.ModelForm):
class Meta:
model = Person
# don't need fields for automatically assigned keys like `uid` and `created_at`
fields = ['name']
class FriendRelForm(forms.ModelForm):
class Meta:
model = FriendRel
exclude = () #"creating ModelForm without either 'fields' || 'exclude' attribute is prohibited"
FriendRelFormSet = formset_factory(FriendRelForm, extra=1)
form.html
<div>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<table class="table">
{{ friends.management_form }}
{% for form in friends.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle "row1" "row2" %} formset_row">
{% for field in form.visible_fields %}
<td>
<!-- Include the hidden fields in the form -->
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Save"/>
</form>
</div>
I'm expecting a "friend" formset to appear in the rendered form, but am not quite sure how to get it there. If I add the following I get an error:
class FriendRelForm(forms.ModelForm):
class Meta:
model = FriendRel
exclude = ()
fields = ['friends']
***ERROR*** django.core.exceptions.FieldError: Unknown field(s) (friends) specified for FriendRel

Display many to many relation relations in the template

First of all I will post all the possibly necessary code. My models:
class topic(models.Model):
learningObjectivesTopic = models.ManyToManyField(learningObjective, verbose_name = "Lernziel")
topic = models.TextField(verbose_name = 'Thema')
class learningObjective(models.Model):
learningObjectives = models.TextField(verbose_name = 'Lernziel')
My views:
#login_required(login_url='login')
def lernziel(request):
return render(request, 'lernziel.html', {'topic': topic.objects.all(), 'todo': todoList.objects.all()})
#login_required(login_url='login')
def create_lernziel(request):
neuesLernziel=learningObjective(learningObjectives=request.POST['Lernziel'])
neuesLernziel.save()
neuesLernziel_Topic=topic.objects.get(topic=request.POST['Thema'])
neuesLernziel_Topic.learningObjectivesTopic.add(neuesLernziel)
return render(request, 'lernziel.html', {'topic': topic.objects.all(), 'todo': todoList.objects.all()})
And the template I am using:
<html lang="{{ LANGUAGE_CODE|default:"de-de" }}" >
<head>
<h1 align = "center">Lernziele</h1>
</head>
<body>
<form action="{% url 'create_lernziel' %}" method="post">
{% csrf_token %}
<br>Hallo Benutzer: {{ user.username }}</br>
Lernziel: <textarea name="Lernziel" rows="3" cols="45" ></textarea>
<p>
<select name="Thema" size="5">
{% for topic_ in topic %}
<option>{{ topic_.topic }}</option>
{% endfor %}
</select>
</p>
<input type="submit" value="Absenden" />
</form>
{% comment %}
Here should be the table which displays learning objectives and the related topics
{% endcomment %}
</body>
</html>
Ok I know my question is a bit weird because I don't have directly wrong code that I am posting. But I tried it so many times to display what I want properly but I just don't get how to do it right. My aim is to have 2 columns/headers: [learning objective] and [topics]. For every learning objective I want to have a new row. And in every row, it is possible to display more topics in relation. If you need more information or want me to be more specific about my problem please post it in the comments :)
Edit my first thought of that structure was that one: I iterate through the learning objectives, create a row for each one and and list the learning objectives and topics in that row then. Apparently it's not working. The Table probably has to be dynamic so that my idea is working or I just had a wrong thought.
<table border="1">
<th>Lernziel</th>
<th>Thema</th>
{% for topic_ in topic %}
{% for lObj in topic_.learningObjectivesTopic.all %}
<tr><td>{{ lObj }}</td>
{% endfor %}
<td>{{ topic_.topic }}</td></tr>
{% endfor %}
</table>
There isn't anything complicated here. You already know that you can get from an objective to its related topics by doing my_objective.topic_set.all(). So you just need to do that while you iterate through each topic in the template (and since it's a template, you drop the parentheses):
<table>
{% for objective in objectives %}
<tr>
<td>{{ objective.learningObjectives }}</td>
<td>{% for topic in objective.topic_set.all %}
{{ topic.topic }}{% if forloop.last %},{% endif %}
{% endfor %}</td>
</tr>
{% endfor %}
</table>
models.py
class learningObjective(models.Model):
learningObjectives = models.TextField(verbose_name = 'Lernziel')
class topic(models.Model):
learningObjectivesTopic = models.ManyToManyField(learningObjective, verbose_name = "Lernziel")
topic = models.TextField(verbose_name = 'Thema')
if you want to put topic ahead,use " or ',that is "learningObjective"
class topic(models.Model):
learningObjectivesTopic = models.ManyToManyField("learningObjective", verbose_name = "Lernziel")
topic = models.TextField(verbose_name = 'Thema')
class learningObjective(models.Model):
learningObjectives = models.TextField(verbose_name = 'Lernziel')
<p>
<select name="Thema" size="5">
{% for topic_ in topic %}
<option>{{ topic_.topic }}</option>
{% for lo in topic_.learningObjectivesTopic.all %}
<option>{{ lo.learningObjectives }}</option>
{% endfor %}
{% endfor %}
</select>
</p>
If you want to get topic from learningObjective
lo = learningObjective.objects.all()[0]
lo.topic_set()
in templates,remove "()", I believe that you know how to use it in templates.