django ListView with a form - python

I have a CBV that use ListView at first here my views.py
class InventoryListView(ListView):
context_object_name = 'inventorys'
model = models.Inventory
and here my template_list.html
{% for inventory in inventorys %}
<tr>
<td>{{ inventory.name }}</td>
<td>{{ inventory.sn }}</td>
<td>{{ inventory.employee.name }}</td>
<td>{{ inventory.desc }}</td>
</tr>
{% endfor %}
it returns all the data as expected.
but I need add form with it. and then add some of code to my views.py
class InventoryListView(ListView):
template_name ='system/inventory_list.html'
context_object_name = 'inventorys'
model = models.Inventory
def get(self, request):
form = InventoryForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = InventoryForm(request.POST)
and here my forms.py
class InventoryForm(forms.ModelForm):
name = forms.CharField(max_length=255)
sn = forms.DecimalField(max_digits=20, decimal_places=0)
desc = forms.CharField(widget=forms.Textarea)
employee = forms.ModelChoiceField(queryset=Employee.objects.all(), to_field_name="id")
class Meta:
model = Inventory
fields = ('name', 'sn', 'desc', 'employee')
and here my template_list.html
{% for inventory in inventorys %}
<tr>
<td>{{ inventory.name }}</td>
<td>{{ inventory.sn }}</td>
<td>{{ inventory.employee.name }}</td>
<td>{{ inventory.desc }}</td>
</tr>
{% endfor %}
<form method="post" action="{% url 'system:inventory_create' %}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
now form working perfectly and checked on my DB its submitted. but list of data not showing like before, because I add:
def get(self, request):
form = InventoryForm()
return render(request, self.template_name, {'form': form})
to my views.py
so how to make both works, list of data & form.

Try to avoid overriding get or post for generic class-based-views. It's easy to end up duplicating existing functionality or having to repeat code.
In this case, you can add the form to the template context by overriding the get_context_data method.
class InventoryListView(ListView):
template_name ='system/inventory_list.html'
context_object_name = 'inventorys'
model = models.Inventory
def get_context_data(self, **kwargs):
context = super(InventoryListView, self).get_context_data(**kwargs)
context['form'] = InventoryForm()
return context
...

Send the form through get_context_data() method:
def get_context_data(self, **kwargs):
context = super(InventoryListView,self).get_context_data(**kwargs)
context['form'] = InventoryForm()
return context

I have a similar situation. I tried many things, and now using ListView with FormMixin.
First, I make FormListView inheriting ListView and FormMixin. Here's my code
from django.http import Http404
from django.views.generic import ListView
from django.views.generic.edit import FormMixin
from django.utils.translation import ugettext as _
class FormListView(FormMixin, ListView):
def get(self, request, *args, **kwargs):
# From FormMixin
form_class = self.get_form_class()
self.form = self.get_form(form_class)
# From ListView
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty and len(self.object_list) == 0:
raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.")
% {'class_name': self.__class__.__name__})
context = self.get_context_data(object_list=self.object_list, form=self.form)
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs)
As you see, I made my own get for FormMixin andListView` both.
And inheriting this, I make my own SomeFormListView, In your case InventoryFormListView.
class InventoryFormListView(FormListView):
template_name ='system/inventory_list.html'
context_object_name = 'inventorys'
model = models.Inventory
# FormListView
form_class = YourCustomModelForm
# your custom method

To save the state of the form
def get_context_data(self, **kwargs):
context = super(RecentChannels, self).get_context_data(**kwargs)
context['form'] = RecentChannelsForm(self.request.GET)
return context

Related

Django - Inline formset - How to set current user

-Objective-
I need to set, in a Inline Formset, the current user as automatic content of a field of the form. (Currently not working)
Version
Python 3.9.2 - Django 3.2
Context:
I've created a List, where I have some objects(Headers).
From the list I can create new headers and access to the detail-page(Detailview)for each of these by using a foreign-key(called by PK-primarykey).
In this page I can see more informations about 1 specific header.
Each header can have multiple lines of informations that need to be linked to it.
The lines are created or updated with (max 4 different) specific Inline Formsets.
-Issue and Error-
I created the forms that are correctly rendered, but I need to set for each line, a field that automatically gets "current user" as its content.
I can't save and receive instead"User cannot be null".
I'm unable to find a solutions and tried many things but stuck with this error.
Would kindly appreciate any help on how to solve this problem.
Thanks in advance,
Below some code:
URLS.PY
from django.urls import path, re_path
from fttlapp import views
app_name= 'fttlapps'
urlpatterns = [
path('fttlapphome2/', views.Fttlapphome2View.as_view(), name='fttlapphome2'),
path('fttlogheader/', views.HeadfttlogListView.as_view(), name='headfttlogs'),
path('fttlogheader/add/', views.HeadfttlogCreateView.as_view(), name='headfttlogcreate'),
path('fttlogheader/<int:pk>/', views.HeadfttlogDetailView.as_view(), name='headfttlogdetail'),
path('fttlogheader/<int:pk>/flights/edit/', views.HeadfttlogDeafttlogEditView.as_view(), name='head_flight_edit'),
]
FORMS.PY
from django import forms
from django.contrib.auth.models import User
from django.db.models.fields import CharField, DateField
from django.forms import ModelForm, widgets
from django.forms.fields import ChoiceField
from django.forms.models import ModelChoiceField
from django.utils import timezone
# Load necessary to manage Form in Form
from django.forms.models import inlineformset_factory
# Load Tables
from fttlapp.models import Headfttlog, Deafttlog, Debfttlog
###############################################################################
# Forms for Headfttlog #
###############################################################################
class HeadfttlogcreateForm(ModelForm):
class Meta:
model = Headfttlog
exclude = ['hea_creator', 'hea_modifier']
widgets = {
'hea_fttldate' : forms.TextInput(attrs={'type': 'date'}),
'hea_nxtcheckdate' : forms.TextInput(attrs={'type': 'date'}),
'hea_transfereddate' : forms.TextInput(attrs={'type': 'date'}),
}
## Calendar widget to work both with Create and Update needs to be TextInput with type date
## Calendar widget not compatible with localized_fields !
###############################################################################
# Forms for Headfttlog with Deafttlog details view Management #
###############################################################################
HeadfttlogDeafttlogFormset = inlineformset_factory(Headfttlog, Deafttlog,
fields=('dea_linetype', 'dea_fttlcode', 'dea_airportfrom', 'dea_airportto',
'dea_instrtimestart', 'dea_instrtimeend', 'dea_instrtimetot',
'dea_blocktimestart', 'dea_blocktimeend', 'dea_blocktimetot',
'dea_flighttimestart', 'dea_flighttimeend', 'dea_flighttimetot',
'dea_approach', 'dea_landing', 'dea_external', 'dea_fuel', 'dea_oil',
'dea_lessonnotes', 'dea_preflightsignature', 'dea_invoiceaccount',
'dea_transfered', 'dea_transfereddate',
'dea_reccanceled', 'dea_creator', 'dea_modifier'),
widgets={
'dea_instrtimestart' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
'dea_instrtimeend' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
'dea_instrtimetot' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
'dea_blocktimestart' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
'dea_blocktimeend' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
'dea_blocktimetot' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
'dea_flighttimestart' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
'dea_flighttimeend' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
'dea_flighttimetot' : forms.TimeInput(format= '%H:%M', attrs={'type': 'time'}),
'dea_reccanceled' : forms.HiddenInput,
'dea_creator' : forms.HiddenInput,
'dea_modifier' : forms.HiddenInput,
}, extra=1, max_num=8)
VIEWS.PY
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
# Load necessary view
from django.views.generic import (
TemplateView, ListView, CreateView, DetailView, FormView)
from django.views.generic.detail import SingleObjectMixin
# Load for security and access management
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import PermissionRequiredMixin
# Load functions and tools for search bar management
from fttlapp.filters import HeadfttlogFilter
import operator
from functools import partial, reduce
from django.db.models import Q
# Load functions for messages management
from django.contrib import messages
# Load Tables & Forms
from fttlapp.models import Headfttlog
from fttlapp.forms import HeadfttlogcreateForm
from fttlapp.forms import HeadfttlogDeafttlogFormset
###############################################################################
# FTTL home page management #
###############################################################################
#login_required
def fttlapphome(request):
context = {}
return render(request, 'fttlapp/fttlapphome.html', context)
###############################################################################
# FTTL home page 2 management #
###############################################################################
class Fttlapphome2View(TemplateView, LoginRequiredMixin):
template_name = 'fttlapp/fttlapphome2.html'
###############################################################################
# Headfttlog - List view Management #
###############################################################################
class HeadfttlogListView(ListView, LoginRequiredMixin, PermissionRequiredMixin):
permission_required = 'fttlapp.view_headfttlog'
model = Headfttlog
template_name = 'fttlapp/headfttlog_list.html'
paginate_by = 10
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['myFilter'] = HeadfttlogFilter(
self.request.GET, queryset=self.get_queryset())
return context
# Following redefintion necessary to obtain correct pagination after Filter plugin
def get_queryset(self):
queryset = super().get_queryset()
return HeadfttlogFilter(self.request.GET, queryset=queryset).qs
###############################################################################
# Headfttlog - Create view Management Headfttlog #
###############################################################################
class HeadfttlogCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
permission_required = 'fttlapp.add_headfttlog'
model = Headfttlog
template_name = 'fttlapp/headfttlogcreate_form.html'
form_class = HeadfttlogcreateForm
def form_valid(self, form):
form.instance.hea_creator = self.request.user
form.instance.hea_modifier = self.request.user
messages.add_message(
self.request,
messages.SUCCESS,
'The LOG has been created'
)
return super().form_valid(form)
###############################################################################
# Headfttlog - Detail view Management Headfttlog #
###############################################################################
class HeadfttlogDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
permission_required = 'fttlapp.view_headfttlog'
model = Headfttlog
template_name = 'fttlapp/headfttlogdetail.html'
###############################################################################
# Headfttlog with Deafttlog details view Management #
###############################################################################
class HeadfttlogDeafttlogEditView(LoginRequiredMixin, PermissionRequiredMixin, SingleObjectMixin, FormView):
permission_required = ('fttlapp.add_headfttlog','fttlapp.change_headfttlog',
'fttlapp.add_deafttlog', 'fttlapp.change_deafttlog')
model = Headfttlog
template_name = 'fttlapp/head_flight_edit.html'
### 1. Identification of the single Headfttlog we will work with
def get(self, request, *args, **kwargs):
self.object = self.get_object(queryset=Headfttlog.objects.all())
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object(queryset=Headfttlog.objects.all())
return super().post(request, *args, **kwargs)
### 2. FormSet creation - instance is the link to the above data.
def get_form(self, form_class=None):
return HeadfttlogDeafttlogFormset(**self.get_form_kwargs(), instance=self.object)
def formset_valid(self, form):
form.dea_creator = self.request.user
form.dea_modifier = self.request.user
form.save()
messages.add_message(
self.request,
messages.SUCCESS,
'Changes were saved.'
)
return HttpResponseRedirect(self.get_success_url())
def get_success_url(self):
return reverse('fttlapps:headfttlogdetail', kwargs={'pk': self.object.pk})
###############################################################################
# End of view Management #
###############################################################################
HTML
{% extends 'base/dibase3.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% crispy formset %}
{% block title %}Editing Flights and Instructions for {{ headfttlog.fttlcode }}{% endblock %}
{% block content %}
<style>
.box{
max-width: fit-content;
margin: auto;
}
</style>
</div>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<div class="text-start">
<a class="btn btn-outline-info " href="{% url 'fttlapps:headfttlogdetail' pk=headfttlog.pk %}">Back to Detail</a>
</div>
</div>
</nav>
<hr>
<div class="container">
<form action="" method="post" enctype="multipart/form-data">
{% for hidden_field in form.hidden_fields %}
{{ hidden_field.errors }}
{{ hidden_field }}
{% endfor %}
{% csrf_token %}
{{ form.management_form }}
{{ form.non_form_errors }}
<h3>Update Collection</h3>
{% for deafttlog_form in form.forms %}
<hr>
<h5>
{% if deafttlog_form.instance.id %}
Deafttlog: {{ deafttlog_form.instance.dea_linetype }}
{% else %}
{% if form.forms|length > 1 %}
Add another deafttlog
{% else %}
Add a deafttlog
{% endif %}
{% endif %}
</h5>
{% for hidden_field in deafttlog_form.hidden_fields %}
{{ hidden_field.errors }}
{% endfor %}
<table>
{{ deafttlog_form }}
</table>
{% endfor %}
<hr>
<p>
<button type="submit" value="Update Flight" class="btn btn-primary w-100 mb-3">Update Flight</button>
Return
</p>
</form>
{% endblock content %}
For audit fields like creator and modifier model fields I will usually set blank=True, null=True in the model field definition. Just by doing that your code will work, because you are already handling setting of dea_creator and dea_modifier in your views.
If you want to enforce this in the database like you are doing now, you will have to pass the request.user to your formset and set it as the initial value for the dea_creator field when initializing the forms.
Edit:
The alternative way I mentioned above, in your HeadfttlogDeafttlogFormset, instead of setting fields and widgets, create an actual form to use, for example DeafttlogForm, and set the fields and widgets there. Then in your formset, you set form=DeafttlogForm.
In the newly created DeafttlogForm, initialize the dea_creator field:
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(DeafttlogForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
if not instance.id and user:
self.initial['dea_creator'] = user
Then in HeadfttlogDeafttlogEditView, add a get_form_kwargs method:
def get_form_kwargs(self):
kwargs = super(HeadfttlogDeafttlogEditView, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs

Trying to make comments editable in django

I have a blog app and the comments can be added on the detail page of the blog, im having trouble implementing a way for users to edit comments they have already made. I have it so a url shows up on comments where only the person signed in can click the link to edit their comments on the post however im getting this error when I try to load the detail page now. Any help would be appreciated thank you
Reverse for 'update_comment' with arguments '(None,)' not found. 1 pattern(s) tried: ['posts(?P[0-9]+)/(?P[0-9]+)/(?P[0-9]+)/(?P[-a-zA-Z0-9_]+)/(?P<comment_id>[0-9]+)/update$']
edit:
I corrected my detail.html file and now im getting this error:
update_comment() missing 1 required positional argument: 'id'
models.py
from django.db.models.signals import pre_save
from Date.utils import unique_slug_generator
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
from django.conf import settings
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager,
self).get_queryset()\
.filter(status='cleared')
class Post(models.Model):
STATUS_CHOICES = (
('cleared','Cleared'),('UnderReview','Being Reviewed'),('banned','Banned'),)
title = models.CharField(max_length = 300)
slug = models.SlugField(max_length = 300, unique_for_date='publish')
author = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='forum_posts',null=True)
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=12,choices=STATUS_CHOICES,default='cleared')
objects = models.Manager()
cleared = PublishedManager()
class Meta:
ordering =('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('posts:post_detail', args=[self.publish.year, self.publish.month, self.publish.day, self.slug])
def slug_generator(sender, instance, *args, **kwargs):
if not instance.slug:
instance.slug = unique_slug_generator(instance)
pre_save.connect(slug_generator, sender=Post)
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.SET_NULL, related_name='comments',null=True)
name = models.ForeignKey(User, on_delete=models.SET_NULL,null=True)
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
class Meta:
ordering = ('created',)
def __str__(self):
return f'Comment by {self.name} on {self.post}'
urls.py
from . import views
from django.urls import path, include
from django.contrib.auth import views as auth_views
from .views import PostListView, PostCreateView,PostUpdateView
app_name = 'posts'
urlpatterns = [
path('', views.PostListView.as_view(), name='post_list'),
#path('<int:year>/<int:month>/<int:day>/<slug:post>/',views.PostDetailView.as_view(),name='post_detail'),
path('<int:year>/<int:month>/<int:day>/<slug:post>/',views.post_detail,name='post_detail'),
path('post/new/',PostCreateView.as_view(), name='post-create'),
path('<int:year>/<int:month>/<int:day>/<slug:post>/update/',PostUpdateView.as_view(), name='post-update'),
path('<int:year>/<int:month>/<int:day>/<slug:post>/<int:comment_id>/update',views.update_comment, name='update_comment'),
]
views.py
from django.shortcuts import render, get_object_or_404
from .models import Post, Comment
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.views.generic import ListView, CreateView, UpdateView
from .forms import CommentForm, PostForm
from django.contrib.auth.models import User
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib import messages
from django.urls import reverse
class PostListView(ListView):
queryset = Post.cleared.all()
context_object_name = 'posts'
paginate_by = 3
template_name = 'posts/post/list.html'
"""class PostDetailView(DetailView, Post):
queryset = Post.cleared.all()
model = Post
fields = ['title','body']
template_name = 'posts/post/detail.html'
form_class = CommentForm
def get_object(self, *args, **kwargs):
return get_object_or_404(
Post,
publish__year=self.kwargs['year'],
publish__month=self.kwargs['month'],
publish__day=self.kwargs['day'],
slug=self.kwargs['post'],
)
return post
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['comment'] = Comment.objects.all()
context['comment_form'] = CommentForm()
return context
def post(self, request, *args, **kwargs):
post = get_object_or_404(Post , slug=post, status='cleared',publish__year=year,publish__month=month,publish__day=day)
comment_form = self.form_class(request.POST)
if comment_form.is_valid():
return HttpResponseRedirect( post.get_absolute_url() )
return render(request, self.template_name, {'comment_form': comment_form})"""
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title','body']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UpdateView):
model = Post
fields = ['title','body']
template_name = 'posts/post-update.html'
def get_object(self, *args, **kwargs):
return get_object_or_404(
Post,
publish__year=self.kwargs['year'],
publish__month=self.kwargs['month'],
publish__day=self.kwargs['day'],
slug=self.kwargs['post'],
author=self.request.user
)
def get_success_url(self):
return reverse('posts:post_detail',
args=[
self.object.publish.year,
self.object.publish.month,
self.object.publish.day,
self.object.slug
]
)
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def post_detail(request, year, month, day, post, comment_id = None):
post = get_object_or_404(Post , slug=post, status='cleared',publish__year=year,publish__month=month,publish__day=day)
comments = post.comments.filter(active=True)
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
comment_form.instance.post = post
comment_form.instance.name = request.user
comment_form.save()
return HttpResponseRedirect( post.get_absolute_url() )
else:
comment_form = CommentForm()
return render(request,'posts/post/detail.html', {'post':post , 'comments': comments,'comment_form': comment_form, 'comment_id':comment_id })
def update_comment(request, year, month, day, post,id, comment_id = None):
post = get_object_or_404(Post , slug=post, status='cleared',publish__year=year,publish__month=month,publish__day=day, id=id)
comments = post.comments.filter(active=True)
comment_form = CommentForm
if comment_id:
comment_form = CommentForm(instance=Comment.objects.get(id=comment_id), data=request.POST)
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
comment_form.instance.post = post
comment_form.instance.name = request.user
comment_form.save()
return HttpResponseRedirect( post.get_absolute_url() )
else:
comment_form = CommentForm()
return render(request,'posts/update_comment.html', {'post':post , 'comments': comments,'comment_form': comment_form, 'comment_id':comment_id })
forms.py
from django import forms
from .models import Comment,Post
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('body',)
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields =('title','body',)
detail.html
{% extends "Main/Base.html" %}
{% block title %}{{ post.title }}{% endblock %}
{% block content %}
<h1>{{ post.title }}<h1>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|linebreaks }}
{% if user.is_authenticated and user == post.author %}
<h3>Update your post</h3>
{% endif %}
{% with comments.count as total_comments %}
<h2>
{{ total_comments }} comment{{ total_comments|pluralize }}
</h2>
{% endwith %}
{% for comment in comments %}
<div class="comment">
<p class="info">
Comment by {{comment.name }}
{{ comment.created }}
</p>
{{ comment.body|linebreaks}}
{% if user.is_authenticated and user == comment.name %}
<p>edit</p>
{% endif %}
</div>
{% empty %}
<p>There are no comments yet.</p>
{% endfor %}
{% if new_comment %}
<h2>Your comment has been added.</h2>
{% else %}
{% if request.user.is_authenticated %}
<h2>Add a new comment</h2>
<form method="post">
{{ comment_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Add comment"></p>
</form>
{% else %}
<h3>You need to be logged in to make a comment please log-in if you dont have an account register here now</h3>
{% endif %}
{% endif %}
{% endblock %}
update_comment.html
{% extends "Main/Base.html" %}
{% block content %}
<form method="POST" action="{% url 'posts:update_comment' post.publish.year post.publish.month post.publish.day post.slug comment.id %}">
{{ comment_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Add comment"></p>
</form>
{% endblock %}
Ive been trying a bunch of this to try and make it work so my code is a bit of a mess, there aren't many tutorials on making editable comments with django.

Django:Child Model Fields Not Rendering

All Foreign Keys,Booleans and Choices fields are not rendering on the form template.But their label tags are rendering.
For example:
This is a "Generated TimeTable" model of a school system.
The model
class GT(models.Model):
timetable_id = models.CharField(primary_key=True,max_length=200)
period_number = models.ForeignKey(Ref_Period,on_delete=models.CASCADE)
scheduled_date_and_time = models.ForeignKey(Ref_Calendar,on_delete=models.CASCADE)
schedule_id = models.ForeignKey(Planned_Timetable,on_delete=models.CASCADE)
subject = models.ForeignKey(Ref_Subject,on_delete=models.CASCADE)
teacher_id = models.ForeignKey(Teacher,on_delete=models.CASCADE)
def __str__(self):
return str(self.teacher_id)
I already imported the in the forms.py file
forms.py
class GTForm(ModelForm):
class Meta:
model = GT
fields = '__all__'
View:
#login_required(login_url = 'main:loginPage')
#allowed_users(allowed_roles=['admin'])
def dalltt(request):
gtform = GTForm()
if request.method == "POST":
gtform = GTForm(request.POST)
print(gtform)
if gtform.is_valid():
gtform.save()
print("saved")
return redirect('/')
else:
print(gtform.errors)
print(gtform)
context = {'gtform':gtform}
return render(request=request,template_name="main/dalltimetable.html",context=context)
The template(dalltimetable.html):
<form enctype="multipart/form-data" action="" method="POST" >
{% csrf_token %}
<table>
<tr>
<th>ID</th>
<th>Time</th>
<th>Day</th>
<th>Subject</th>
<th>{{ gtform.teacher_id.label_tag }} </th>
</tr>
<tr>
<td>{{ gtform.teacher_id }} </td>
<td>{{ gtform.teacher_id }}</td>
</tr>
</table>
<input class="btn btn-warning" type="submit" value="Update">
{{ form.name.errors }}
{{ form.non_field_errors }}
</form>
Give this a try:
#login_required(login_url = 'main:loginPage')
#allowed_users(allowed_roles=['admin'])
def dalltt(request):
if request.method == "POST":
gtform = GTForm(request.POST)
print(gtform)
if gtform.is_valid():
gtform.save()
print("saved")
return redirect('/')
else:
print(gtform.errors)
else:
gtform = GTForm()
return render(request, 'main/dalltimetable.html', {'gtform': gtform })
Also maybe try switching to class-based views to help with the boilerplate:
class dalltt(LoginRequiredMixin, FormView):
template_name = 'main/dalltimetable.html'
form_class = GTForm
success_url = '/'
login_url = 'main:loginPage'
def form_valid(self, form):
form.save()
return super().form_valid(form)
def form_invalid(self, form):
print(form.errors)

Django - filter drop down choices based on user group

i am trying to filter a forms drop down list based on a users group
To find the user group i am using a custom templatetag
template tag
from django import template
register = template.Library()
#register.filter(name='in_group')
def in_group(user,group_name):
try:
group=Group.objects.get(name=group_name)
except Group.DoesNotExist:
return False
return group in user.groups.all()
task.html
{% load group_check %}
<form method="post">
{% csrf_token %}
{% if user.is authenticated %}
{% if requset.user|in_group:'DEVELOPER' %}
#...DO SOMETHING
{{ form.as_p }}
<button type="submit">add task</button>
</form>
models
GOALS_TYPE= (('DT','Daily Task'),
('WT','Weekly Task'),
('V','Verified'),
('D','Done'),
)
class GoalStatus(models.Model):
title = models.CharField(max_length=254, null=True)
task_id=models.IntegerField(default=1,null=False)
description =models.CharField(max_length=254)
verified_by=models.ForeignKey('ScrumyUser', on_delete= models.CASCADE, null=True)
status=models.CharField(choices=GOALS_TYPE, max_length=2, default='DT')
def __str__(self):
return self.title
the template for the form is based on the forms.py
forms.py
class ChangeTaskForm(forms.ModelForm):
class Meta:
model = GoalStatus
fields = ('title', 'task_id','description','status', 'verified_by')
views.py
def move_goals(request,pk):
if request.method == 'POST':
form = ChangeTaskForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('/index/')
else:
form = ChangeTaskForm()
return render(request, 'oderascrumy/task.html', {'form': form})
urls.py
path('task/<pk>/', views.move_goals, name='move_goals')
so for example if the user is in group "developer", the drop down choices for status will be only verified and done
You can do like below
views.py
def move_goals(request,pk):
if request.method == 'POST':
form = ChangeTaskForm(request.POST, user=request.user)
if form.is_valid():
return HttpResponseRedirect('/index/')
else:
form = ChangeTaskForm(user=request.user)
return render(request, 'oderascrumy/task.html', {'form': form})
forms.py
class ChangeTaskForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ChangeTaskForm, self).__init__(*args, **kwargs)
if user.groups.filter(name='DEVELOPER').exists():
self.fields['status'].choices = (('V','Verified'), ('D','Done'),)
class Meta:
model = GoalStatus
fields = ('title', 'task_id','description','status', 'verified_by')
template.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">add task</button>
</form>
I think no need of template tag for this.

Django Class Based Views : Override form name

I'm new in Django. I try to build a class based view in order to create an object.
The default name of the form in the template is form and I want to change it to "ajoutersource" but I can't figure how.
views.py
class ajoutSource(CreateView):
model = Source
template_name = "pmd/ajouterSource.html"
form_class = AjouterSourceForm
success_url = reverse_lazy(ListerSources)
ajouterSource.html
{% for field in ajoutersource %}
<div class="row">
{% if field.errors %}
<div class="error">{{ field.errors }}</div>
{% endif %}
<div class="label">{{ field.label }}</div>
<div class="field">{{ field }}</div>
</div>
{% endfor %}
Override get_context_data():
class ajoutSource(CreateView):
model = Source
template_name = "pmd/ajouterSource.html"
form_class = AjouterSourceForm
success_url = reverse_lazy(ListerSources)
def get_context_data(self, **kwargs):
context = super(ajoutSource, self).get_context_data(**kwargs)
context["ajoutersource"]=context["form"]
return context
you can do it simply by following method
Method 1 (Model Form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['new_name'] = self.get_form()
return context
Method 2 (Simple Form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['new_name'] = context["form"]
return context
Method 1 is recommended
(Note: This is python 3.6+ syntax, change super() call for python 2.0+)
Override the get_context_data, context['form'] take from SomeForm, and change to form_1, you can use in template as form_1
class Something(generic.CreateView):
template_name = 'app/example.html'
form_class = forms.SomeForm
model = models.SomeModel
def get_context_data(self, **kwargs):
context = super(Something, self).get_context_data(**kwargs)
context["form_1"] = context["form"]
context["form_2"] = forms.SomeForm2(**self.get_form_kwargs())
return context

Categories