I have 2 models, Employee and Leave, where Employee is a foreign key in Leave. Now when an Employee is applying for a Leave, I want the Employee name option to be limited to only the logged-in user rather than all employees. Can I create a custom input with read-only and send user data using {{}}? I'm not able to retrieve data from input group to models.
Here is my code.
models.py:
class Employee(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
no_of_leaves = models.IntegerField(
null=False,
validators=[MinValueValidator(1), MaxValueValidator(24)],
default=24
)
def __str__(self):
return self.user.username
class Leave(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE, default="")
start_date = models.DateField(auto_now_add=False)
end_date = models.DateField(auto_now_add=False)
req_date = models.DateTimeField(default=datetime.datetime.now())
approved_by = models.CharField(max_length=100,blank=True)
STATUS_OPTIONS = (
("Approved","Approved"),
("Pending","Pending"),
("Declined","Declined"),
)
approved = models.CharField(max_length=10, choices=STATUS_OPTIONS, default='Pending')
def __str__(self):
return self.employee.user.username
#property
def date_diff(self):
return (self.end_date - self.start_date).days
forms.py:
class leaveForm(forms.ModelForm):
class Meta():
model = Leave
fields = ('employee', 'start_date', 'end_date')
# start_date = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'}))
widgets = {
'start_date': DateInput(attrs={'type': 'date'}),
'end_date': DateInput(attrs={'type': 'date'})
}
views.py:
#login_required
def applyforleave(request):
user=request.user
emp=Employee.objects.get(user=user)
submitted= False
if request.method == 'POST':
leave_form = leaveForm(data=request.POST)
emp_name=employee(data=request.POST)
if leave_form.is_valid() and emp_name.is_valid():
emp_name.save()
start_date = leave_form.cleaned_data.get("start_date")
end_date = leave_form.cleaned_data.get("end_date")
days = (end_date - start_date).days
days_checker = emp.no_of_leaves - days
if 0 < days_checker < emp.no_of_leaves:
leave = leave_form.save()
leave.set_employee
leave.save()
submitted = True
else:
print("error")
else:
print(leave_form.errors)
else:
leave_form = leaveForm()
return render(
request,
'leaveApp/leave.html',
{
'leave_form': leave_form,
'submitted': submitted,
'emp': emp
}
)
leave.html:
<div class="container">
<div class="jumbotron">
<form enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{ leave_form.as_p }}
<input type="submit" name="" value="Submit">
</form>
</div>
</div>
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
user= self.request.user
super(leaveForm, self).__init__(*args, **kwargs)
add the above init in forms.py
labels = {'employee': user}
statistics = forms.Field(
label=user,
)
this in your forms.py
and pass request from views.py
leave_form = leaveForm(request)
You can also check the docs for using the initial parameter
docs
Related
I have one model which name is Post. It has two one-two-many relationship with model "PostImages" and "PostFiles". I want to create only one form to handle this. Also I want files and images upload to be not required. And I did it but my code doesn't run validation process on "PostImagesForm" and "PostFilesForm", but it validate the "PostForm".
models.py (i am using FileTypeValidator form uload_validator package which works fine for thumbnail so there isn't problem with it)
class Post(models.Model):
title = models.CharField(max_length=60)
content = tinymce_models.HTMLField('content')
date = models.DateTimeField(default=timezone.now)
slug = AutoSlugField(populate_from='title', unique_with='date')
thumbnail_big = models.ImageField(upload_to='thumbnails/', validators=[FileTypeValidator(allowed_types=[VIEL])])
thumbnail_small = models.ImageField(upload_to='thumbnails/', blank=False, default=thumbnail_big)
def description(self):
return HTMLtoString(self.content)
def save(self, *args, **kwargs):
#THUMBNAIL COMPRESSION
#small thumbnail
if SizeOfImageGreaterThan(self.thumbnail_big, TQS.SMALL_THUMBNAIL_RESOLUTION):
thumbnail_compressed_small = Compress(self.thumbnail_big, TQS.SMALL_THUMBNAIL_RESOLUTION, TQS.SMALL_THUMBNAIL_QUALITY)
self.thumbnail_small = thumbnail_compressed_small
#big thumbnail
if SizeOfImageGreaterThan(self.thumbnail_big, TQS.BIG_THUMBNAIL_RESOLUTION):
thumbnail_compressed_big = Compress(self.thumbnail_big, TQS.BIG_THUMBNAIL_RESOLUTION, TQS.BIG_THUMBNAIL_QUALITY)
self.thumbnail_big = thumbnail_compressed_big
super(Post, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse("EatWell:Post", args=[self.slug])
class PostImages(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
big_image = models.ImageField(upload_to='images/', blank=True, null=True, validators=[FileTypeValidator(allowed_types=[VIEL])])
small_image = models.ImageField(upload_to='images/', blank=False, default=big_image)
def save(self, *args, **kwargs):
#IMAGE COMPRESSION
#small image
if SizeOfImageGreaterThan(self.big_image, IQS.SMALL_IMAGE_RESOLUTION):
small_image_compressed = Compress(self.big_image, IQS.SMALL_IMAGE_RESOLUTION, IQS.SMALL_IMAGE_QUALITY)
self.small_image = small_image_compressed
#big image
if SizeOfImageGreaterThan(self.big_image, IQS.BIG_IMAGE_RESOLUTION):
big_image_compressed = Compress(self.big_image, IQS.BIG_IMAGE_RESOLUTION, IQS.BIG_IMAGE_QUALITY)
self.big_image = big_image_compressed
super(PostImages, self).save(*args, **kwargs)
class PostFiles(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
file = models.FileField(upload_to='files/', blank=True, null=True)
forms.py (i am using crispy forms)
class PostCreationForm(forms.ModelForm):
class Meta:
model = models.Post
fields = ['title', 'content', 'date', 'thumbnail_big']
labels = {
'thumbnail_big': 'Thumbnail',
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form_method = 'POST'
self.helper = FormHelper(self)
self.helper.form_tag = False
self.helper.disable_csrf = True
self.helper.layout = Layout(
Fieldset(
'Create a post',
'title',
'content',
'date',
Field('thumbnail_big'), #accept=VIEL),
),
)
class PostImagesCreationForm(forms.ModelForm):
class Meta:
model = models.PostImages
fields = ['big_image']
labels = {'big_image' : ''}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form_method = 'POST'
self.helper = FormHelper(self)
self.helper.form_tag = False
self.helper.disable_csrf = True
self.helper.layout = Layout(
Fieldset(
'Upload images',
Field('big_image', multiple = True), #accept=VIEL),
),
)
class PostFilesCreationForm(forms.ModelForm):
class Meta:
model = models.PostFiles
fields = ['file']
labels = {'file' : ''}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form_method = 'POST'
self.helper = FormHelper(self)
self.helper.form_tag = False
self.helper.disable_csrf = True
self.helper.layout = Layout(
Fieldset(
'Upload files',
Field('file', multiple = True), #, accept = VEL
),
self.helper.add_input(Submit('submit','Submit')),
)
views.py
#login_required()
def PostCreationView(request):
post_form = forms.PostCreationForm()
images_form = forms.PostImagesCreationForm()
files_form = forms.PostFilesCreationForm()
if request.method == 'POST':
post_form = forms.PostCreationForm(request.POST, request.FILES)
files_form = forms.PostFilesCreationForm(request.FILES)
images_form = forms.PostImagesCreationForm(request.FILES)
images = request.FILES.getlist('big_image')
files = request.FILES.getlist('file')
if post_form.is_valid():
print('[INFO] PostCreationForm is valid')
post_form.save()
print('[INFO] PostCreationForm has been saved')
if images_form.is_valid(): #always returns True
print('[INFO] PostImagesCreationForm is valid')
for image in images:
models.PostImages.objects.create(post=post_form.save(), big_image=image)
print('[INFO] New table for image has been created')
else:
print('[THREAD] PostImagesCreationForm is not valid')
print(files_form.errors.as_data())
if files_form.is_valid(): #always returns True
print('[INFO] PostFilesCreationForm is valid')
for file in files:
models.PostFiles.objects.create(post=post_form.save(), file=file)
print('[INFO] New table for file has been created')
else:
print('[THREAD] PostFilesCreationForm is not valid')
print(files_form.errors.as_data())
return redirect('EatWell:Blog')
else:
print('[THREAD] PostFilesCreationForm is not valid')
print(post_form.errors.as_data())
context = {
'title' : 'Post Creation',
'tinymce' : True,
'post_form' : post_form,
'images_form' : images_form,
'files_form' : files_form
}
return render(request, 'postcreation/postcreation.html', context)
postcreation.html
{% extends 'postcreation/base.html' %}
{% load crispy_forms_tags %}
{% block body %}
<div class="container-sm border p-3">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{% crispy post_form %}
{% crispy images_form %}
{% crispy files_form %}
</form>
</div>
<div class="container-sm border p-3 m-3">
<button class="btn btn-danger mr-2" onclick="location.href = '{% url 'PostCreation:Logout' %}'" ;>Log out</button><button class="btn btn-info"onclick="location.href = '{% url 'HomePage' %}'" ;>Return to the home page</button>
</div>
{% endblock body %}
The way described up there works mainly as i want, but it doesn't validate the files and images in "PostFilesView" and in "ImageFileView" which user is uploading
in my form i want to select department from 2 options: some object(every time only one) and None.
my form.py
class TeamGoalForm(ModelForm):
def __init__(self, *args, **kwargs):
employees = kwargs.pop('employees')
department = kwargs.pop('department')
super().__init__(*args, **kwargs)
self.fields['employees'].queryset = employees
self.fields['department'].choices = [(1, department), (2, None)]
self.fields['department'].initial = [1]
class Meta:
model = TeamGoal
fields = ('team_goal_title','department','employees', 'team_goal_description', 'gpd_year','team_factor_0','team_factor_1','team_factor_2','team_factor_3','team_factor_weight')
widgets = {
'team_goal_title': forms.TextInput (attrs={'class':'form-control', 'placeholder':'Enter the title of goal'}),
'department': forms.Select (attrs={'class': 'form-control', 'placeholder':'Select department'}), }
in my view.py I have had:
if request.method == 'POST':
form = TeamGoalForm(request.POST, employees=employees, department=department)
if form.is_valid():
form.save()
Here my department is an object.
How to implement something like this, 'cos my solution does't work?
You are not showing much of the code, but here is more or less how the different files should look like, hope this helps:
**#models.py**
from django.db import models
class department(models.Model):
# department fields
pass
class TeamGoal(models.Models):
...
deparment = models.ForeignKey(department, on_delete=models.CASCADE)
...
**#forms.py**
from django.forms import ModelForm
from django import forms
class TeamGoalForm(ModelForm):
class Meta:
model = TeamGoal
fields = (
'team_goal_title',
'department',
'employees',
'team_goal_description',
'gpd_year',
'team_factor_0',
'team_factor_1',
'team_factor_2',
'team_factor_3',
'team_factor_weight'
)
deparments = deparment.objects.all()
widgets = {
'deparments': forms.Select(choices=deparments,
attrs={
'class': 'form-control',
'placeholder':'Select department'
})
**#views.py**
from .forms import TeamGoalForm
def AddTeamGoalForm(request):
context = {
'TeamGoalForm': TeamGoalForm,
}
if request.method == 'POST':
addTeamGoalForm = TeamGoalForm(request.POST)
if addTeamGoalForm.is_valid():
newTeamGoalForm = addTeamGoalForm.save()
return redirect('/')
else:
return render(request, '/TeamGoalForm.html', context)
**# TeamGoalForm.html**
<form method="POST">
{% csrf_token %}
{{ TeamGoalForm}}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
NOTE: you may need to adjust it based on the code you've already writen, but hopefully this leads close to a solution.
I have added like and dislike button to Song post When like object is not created if some click on like it is showing intigrity error if like object is already there then it is not rendering that to template.
models.py
Codes in models.py
class Song(models.Model):
song_title = models.CharField(max_length=25)
album = models.ForeignKey(Album, related_name='album_name', on_delete=models.CASCADE, blank=True)
singer = models.ManyToManyField(Singer, blank=True)
language = models.CharField(max_length=25)
class VoteManager(models.Manager):
def get_vote_or_unsaved_blank_vote(self,song,user):
try:
return Vote.objects.get(song=song,user=user)
except ObjectDoesNotExist:
return Vote(song=song,user=user)
class Vote(models.Model):
UP = 1
DOWN = -1
VALUE_CHOICE = ((UP, "👍️"),(DOWN, "👎️"),)
like = models.SmallIntegerField(choices=VALUE_CHOICE)
user = models.ForeignKey(User,on_delete=models.CASCADE)
song = models.ForeignKey(Song, on_delete=models.CASCADE)
voted_on = models.DateTimeField(auto_now=True)
objects = VoteManager()
class Meta:
unique_together = ('user', 'song')
views.py
Codes in views.py
class SongDetailView(DetailView):
model = Song
template_name = 'song/song_detail.html'
def get_context_data(self,**kwargs):
ctx = super().get_context_data(**kwargs)
if self.request.user.is_authenticated:
vote = Vote.objects.get_vote_or_unsaved_blank_vote(song=self.object, user = self.request.user)
if vote.id:
vote_url = reverse('music:song_vote_update', kwargs={'song_id':vote.song.id,'pk':vote.id})
else:
vote_url = reverse('music:song_vote_create', kwargs={'song_id':vote.song.id})
vote_form = SongVoteForm(instance=vote)
ctx['vote_form'] = vote_form
ctx['vote_url'] = vote_url
return ctx
class SongUpdateView(UpdateView):
form_class = SongVoteForm
queryset = Song.objects.all()
def get_object(self,queryset=None):
song = super().get_object(queryset)
user = self.request.user
return song
def get_success_url(self):
song_id = self.kwargs.get('song_id')
return reverse('music:song_detail', kwargs={'pk':song_id})
class SongVoteCreateView(View):
form_class = SongVoteForm
context = {}
def post(self,request,pk=None,song_id=None):
vote_obj,created = Vote.objects.get_or_create(pk=pk)
song_obj = Song.objects.get(pk=song_id)
vote_form = SongVoteForm(request.POST, instance=vote_obj)
if vote_form.is_valid():
new_vote = vote_form.save(commit=False)
new_vote.user = self.request.user
new_vote.song = song_obj
return redirect('/album/')
Song_detail.html
codes in song_detail.html
<form action="{{vote_url}}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ vote_form.as_p }}
<button class="btn btn-primary" type="submit" >Vote</button>
</form>
Error Code
This is the error when submitting the like button. Refer here for the traceback
NOT NULL constraint failed: album_vote.song_id
song and user fields are required. So you have to give song and user while creating Vote.
here is full code::
class SongVoteCreateView(View):
form_class = SongVoteForm
context = {}
def post(self,request,pk=None,song_id=None):
song_obj = Song.objects.get(pk=song_id)
vote_obj,created = Vote.objects.get_or_create(song = song_obj, user = request.user)
vote_form = SongVoteForm(request.POST, instance=vote_obj)
if vote_form.is_valid():
vote_form.save()
return redirect('/album/')
also in VoteManager, the code
return Vote(song=song,user=user)
won't create vote, instead you have to use
return Vote.objects.create(song=song,user=user)
I'm building a storage web system using django, I'm very newbie on the framework, so the problem is that, there is a business rule, which demands, two kinds of products, the inside products, and the finished ones. And the finished ones, always are composed by one or more inside products, I have the idea of using the manytomanyfields, but now, I don't really know how to extract this data , that should be a multiple choice, from the form and save in the database, does anyone has any tips or better ideas?
Models.py
class Produto(models.Model):
codigo = models.CharField(max_length=254, null=True)
produto_desc = models.CharField(max_length=200, null=False)
tipo = models.CharField(max_length=2)
qtd = models.IntegerField(null=True, default=0)
created = models.DateTimeField(default=timezone.now, editable=False)
last_updated = models.DateTimeField(default=timezone.now, editable=False)
#Relationship Fields
estrutura = models.ManyToManyField(
'storage.Produto',
related_name="produto"
)
def __str__(self):
return self.produto_desc
Views.py
def CadastroProd(request):
temp = 0
lista_produto = Produto.objects.order_by('id')[:20]
for i in lista_produto:
temp += 1
if request.method == 'POST':
form = NovoProduto(request.POST)
if form.is_valid():
obj = Produto()
obj.save(commit=False)
obj.codigo = form.cleaned_data['codigo']
obj.produto_desc = form.cleaned_data['produto_desc']
obj.tipo = form.cleaned_data['tipo']
# obj.estrutura = form.cleaned_data['estrutura']
obj.save()
return HttpResponseRedirect('/storage/produtos')
lista_produto = Produto.objects.order_by('id')[:20]
lista_pi = Produto.objects.filter(tipo='PI')
lista_pa = Produto.objects.filter(tipo='PA')
context = {'lista_produto': lista_produto,
'temp': temp,
'lista_pi': lista_pi, 'lista_pa': lista_pa,
}
return render(request, 'storage/cadproduto/cadproduto.html', context)
forms.py
class NovoProduto(forms.Form):
codigo = forms.CharField(label='codigo', max_length=254)
produto_desc = forms.CharField(label='produto_desc', max_length=100)
tipo = forms.CharField(label='tipo', max_length=2)
estrutura = forms.IntegerField()
index
<div class="row">
<div class="col-md-3 mb-3">
<label for="pi-ida">Composição de Produtos Internos</label>
<select name="estrutura" multiple id="id_estrutura" required>
{%for prod in lista_pi%}
<option value="{{prod.id}}">{{prod.produto_desc}}</option>
{% endfor %}
</select>
</div>
</div>
<hr class="mb-4">
<button class="btn btn-primary btn-lg btn-block" type="submit">Cadastrar</button>
I expected that I can get information of the product, adn of the products that compose it
You are using your own custom template so get the selected choices list using the getlist() method and use set() method to save the manytomany field like this
Also if form is valid you need to save the form
if request.method == 'POST':
form = NovoProduto(request.POST)
estrutura = request.POST.getlist('estrutura')
if form.is_valid():
obj=form.save(commit=False)
obj.codigo = form.cleaned_data['codigo']
obj.produto_desc = form.cleaned_data['produto_desc']
obj.tipo = form.cleaned_data['tipo']
# obj.estrutura = form.cleaned_data['estrutura']
obj.save()
obj.estrutura.set(estrutura)
return redirect....
In your Form subclass, use ModelMultipleChoiceField:
class NovoProduto(forms.Form):
codigo = forms.CharField(label='codigo', max_length=254)
produto_desc = forms.CharField(label='produto_desc', max_length=100)
tipo = forms.CharField(label='tipo', max_length=2)
estrutura = forms.ModelMultipleChoiceField(queryset=Produto.objects.order_by('id')[:20])
The M2M field seems to be a self reference (unless you have two Models called Produto), so you might want to exclude the current product from the list of select options.
You can modify the queryset of a ModelMultipleChoiceField in the form's constructor:
def __init__(*args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance and self.instance.id:
self.fields['estrutura'].queryset = Produto.objects.exclude(id=self.instance.id).order_by('id')[:20]
I need to create a required checkbox option if no_new_item exists. I am using the model.NullBoolean field. According to Django docs the Boolean field should render the checkbox widget but NullBoolean renders Select. The reason for the switch to NullBoolean was due to the null error when migrating. So now I am getting a drop down list with 'Yes' and 'No.'
How would I go about creating the checkbox in the Base model.Models with NullBoolean or is there a better way?
(this is an edit as I miss spoke about the Django Docs. Thanks #Alasdair)
/models.py
class StoreNightlyReport(models.Model):
store_number = models.ForeignKey('Stores', verbose_name='Store Number', max_length=20, null=True)
date = models.DateField(null=True)
#managers = models.ManyToManyField('auth.User', blank=True, null=True)
def __str__(self):
return self.store_number.store_number
class StoreNightlyReportsBase(models.Model):
store_nightly_report = models.ForeignKey(StoreNightlyReport)
no_new_item = models.NullBooleanField(verbose_name='No New Items', default=True)
customer = models.CharField(verbose_name='Customer Name', max_length=20, null=True)
class Meta:
abstract = True
/forms.py
class StoreNightlyReportsForm(ModelForm):
class Meta:
model = StoreNightlyReport
widgets = {'date': SelectDateWidget()}
exclude = ()
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(StoreNightlyReportsForm, self).__init__(*args, **kwargs)
if 'store_number' in self.fields:
if not user.is_superuser:
self.fields['store_number'].queryset = Stores.objects.filter(managers=user)
/views.py
class StoresNightlyReportsNewLoansCreate(CreateView):
template_name = 'reports/storenightlyreport_form.html'
model = StoreNightlyReport
form_class = forms.StoreNightlyReportsForm
success_url = reverse_lazy('reports:storenightlyreports')
def get_form(self, form_class=None):
form_class = self.get_form_class()
form = form_class(self.request.POST or None, user=self.request.user)
self.formsets = {}
StoreNightlyReportsNewLoanFormSet = inlineformset_factory(StoreNightlyReport,
StoreNightlyReportsNewLoan,
exclude=[],
extra=1)
self.formsets['new_loan'] = StoreNightlyReportsNewLoanFormSet(self.request.POST or None)
def get_context_data(self, **kwargs):
data = super(StoresNightlyReportsNewLoansCreate, self).get_context_data(**kwargs)
data['formset_new_loan'] = self.formsets['new_loan']
return data
def get_context_data(self, **kwargs):
data = super(StoresNightlyReportsNewLoansCreate, self).get_context_data(**kwargs)
#formset_renewal = StoreNightlyReportsRenewalFormSet()
data['formset_new_loan'] = self.formsets['new_loan']
return super(StoresNightlyReportsNewLoansCreate, self).form_invalid(form)
/template.html
{% extends "reports/base.html" %}
{% load static %}
{% block body_block %}
<div class="container-fluid">
<form class="form-inline" action="" method="post">
{% csrf_token %}
{{ form }}
<table class="table">
{{ formset_new_loan.management_form }}
<div>
<br><h4><strong>New Loans</strong></h4><br>
{% include "reports/formsets.html" with formset=formset_new_loan formset_class_name='new_loan' %}
</div>
</table>
Fixed
After some thought I just went back to the model.Base and changed it to the BooleanField type and added a default value. This cleared the null error on migration and rendered a checkbox option.
class StoreNightlyReportsBase(models.Model):
store_nightly_report = models.ForeignKey(StoreNightlyReport)
no_new_item = models.BooleanField(verbose_name="Check if No New Items", default=False)
customer = models.CharField(verbose_name='Customer Name', max_length=20, null=True)