Limit dropdown results in generic UpdateView - django

Working on my first Django project! I have an UpdateView and I want to limit the dropdown results of program_code so it only shows items that the user owns. I think I have to pass kwargs to the view to limit the queryset but not sure where to begin or how to go about doing that. Any advice would be greatly appreciated.
View:
class ContactsUpdateView(LoginRequiredMixin, UserPassesTestMixin, SuccessMessageMixin, UpdateView):
model = Contact
fields = ['first_name1', 'last_name1','address1','address2','city','province','postal_code','country','active_status','program_code']
template_name = 'contacts/contacts_form.html'
success_message = "Contact was updated successfully"
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
contact = self.get_object()
if self.request.user == contact.author:
return True
return False
model:
class Contact(models.Model):
first_name1 = models.CharField(max_length=100, verbose_name='First Name', null=True)
last_name1 = models.CharField(max_length=100, verbose_name='Last Name', null=True)
address1 = models.CharField(max_length=100, verbose_name='Address 1', null=True)
address2 = models.CharField(max_length=100, verbose_name='Address 2', null=True, blank=True)
city = models.CharField(max_length=100, verbose_name='City', null=True)
province = models.CharField(max_length=2, choices=PROVINCE_CHOICES, default='Ontario', verbose_name='Province')
postal_code = models.CharField(max_length=7, verbose_name='Postal Code', null=True)
country = models.CharField(max_length=100, verbose_name='Country', null=True, default='Canada')
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
active_status = models.BooleanField(default=True)
program_code = models.ForeignKey(Program, on_delete=models.CASCADE)
def __str__(self):
return self.first_name1 + ' ' + self.last_name1
def get_absolute_url(self):
return reverse('contacts-home')
template form:
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-2 mt-2">Update Contact</legend>
<p>Created by: {{ object.author }}, Last Updated: {{ object.date_posted }}</p>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-info" type="submit">Update</button>
<div class="mt-4"><a class="btn btn-outline-danger btn-sm" href="{% url 'contacts-delete' object.id %}" role="button">Delete Contact</a></div>
</div>
</form>

You can try like this:
# form
class ContactForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None) # This will be sent from View
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['program_code'].queryset = Program.objects.filter(owner=user)
class Meta:
model = Contact
fields = ['first_name1', 'last_name1','address1','address2','city','province','postal_code','country','active_status','program_code']
#view
class ContactsUpdateView(LoginRequiredMixin, UserPassesTestMixin, SuccessMessageMixin, UpdateView):
model = Contact
from_class = ContactForm
template_name = 'contacts/contacts_form.html'
success_message = "Contact was updated successfully"
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def get_form_kwargs(self):
# Sending user information to Form
kwargs = super(ContactsUpdateView, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
Here in the View, we are overriding the get_form_kwargs method to pass current user information to the Form. And inside the form, we are overriding the __init__ method to catch the user data sent from View, and use it to override default queryset value of the field program_code.

Related

Django not receiving any request in backend after submit the form

Hi Everyone I am trying to submit the form in Django. but I am not getting any response in Backend. when I clicked on submit. the form is not getting submitted.
The code
Models
class JobListing(models.Model):
position = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, blank=True)
company_name = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
about_company = models.TextField(blank=True)
description = models.TextField()
city = models.CharField(max_length=250)
job_location = models.CharField(max_length=250)
KeySkill = models.TextField()
eligiblity = models.TextField(blank=True)
resposibility = models.TextField(blank=True)
min_experience = models.FloatField()
max_experience = models.FloatField()
last_date_to_apply = models.DateField(default=timezone.now)
min_salary = models.PositiveIntegerField()
max_salary = models.PositiveIntegerField()
shift_time = models.CharField(max_length=15, choices=shiftDetail)
posted = models.DateField(default=timezone.now)
number_of_position_opening = models.PositiveIntegerField(default=1)
job_post_status = models.IntegerField(default=1, choices=job_post_status)
def save(self, *arg, **kwargs):
if not self.slug:
self.slug = slugify(self.position)
super(JobListing, self).save(*arg, **kwargs)
def __str__(self):
return str(self.position) + " -- " + str(self.company_name)
Form.py
class JobList(forms.ModelForm, forms.Form):
job_location = forms.ModelChoiceField(queryset=CountryAndState.objects.filter(country__isnull=False).distinct())
Key_Skill = forms.ModelMultipleChoiceField(
queryset=skill.objects.all().values_list('name', flat=True).distinct().order_by('name'),
widget=forms.SelectMultiple, required=False, blank=True)
class Meta:
model = JobListing
fields = ['position', 'number_of_position_opening', 'company_name', 'about_company', 'description',
'eligiblity', 'resposibility', 'city',
'job_location', 'KeySkill', 'Key_Skill', 'min_experience', 'max_experience', 'min_salary',
'max_salary', 'shift_time', 'last_date_to_apply']
exclude = ['slug', 'posted']
widgets = {
'KeySkill': forms.TextInput(attrs={'type':'text'}),
'about_company': forms.Textarea(attrs={'rows': 100, 'cols': 15}),
'last_date_to_apply': forms.DateInput(attrs={'type':'date'})
}
def __init__(self, user, *args, **kwargs):
super(JobList, self).__init__(*args, **kwargs)
for field in self.fields.keys():
widget = self.fields[field].widget
if 'cols' in widget.attrs and 'rows' in widget.attrs:
widget.attrs.update({'class': 'form-control pl-15 bg-transparent summernote'})
else:
widget.attrs.update({'class': 'form-control pl-15 bg-transparent'})
widget.attrs['placeholder'] = self.fields[field].label
self.fields[field].required = False
self.fields['company_name'].queryset = User.objects.filter(created_by=user, user_type=4)
View.py
class JobCreateView(LoginRequiredMixin, TemplateView):
template_name = 'Job/Recruiter/PostNewJob.html'
template_name2 = 'Job/RecruiterAgency/PostNewJob.html'
redirect_field_name = 'redirect_to'
def get(self, request, *args, **kwargs):
joblist = JobList(request.user.id)
if request.user.user_type == 2:
return render(request, self.template_name, {"form": joblist})
elif request.user.user_type == 3:
return render(request, self.template_name2, {"form": joblist})
def post(self, request):
job_detail = JobList(request.user.id, request.POST)
field = job_detail.fields.pop('Key_Skill')
if job_detail.is_valid():
job_detail.save()
return redirect('/job/manage_job')
job_detail.fields['Key_Skill'] = field
if request.user.user_type == 2:
return render(request, self.template_name, {"form": job_detail})
elif request.user.user_type == 3:
return render(request, self.template_name2, {"form": job_detail})
template.html
{%extends 'index.html'%}
<body class="hold-transition light-skin sidebar-mini theme-primary">
{%block body%}
<div class="content-wrapper">
<h1>Create New Job</h1>
<div class="">
<form action="" enctype="multipart/form-data" method="post" id="form">
{%csrf_token%}
<div>
{{form.as_p}}
{{form.errors}}
</div>
<button type="submit" class="btn btn-dark" value="Submit" form="form"> Submit </button>
</form>
</div>
I have tried both Submit method with Input tags as well as Button. I tried debugging the code but am not receiving any requests in the backend. submit button is acting like it is disable
You added action as blank in form tag
<form action="" enctype="multipart/form-data" method="post" id="form">
add appropriate url name in form tag
<form action="{% url 'post_url_name' %}" enctype="multipart/form-data" method="post" id="form">

How can I make my comments form work in django?

I'm trying to call my comment form from the blog page, but it just keeps refreshing the particular blog page. Here's my code;
models.py
class BlogPost(models.Model):
# id = models.IntegerField()
user = models.ForeignKey(User, default=1, null=True, on_delete=models.SET_NULL)
image = models.ImageField(upload_to='image/', blank=True, null=True)
title = models.CharField(max_length=120)
slug = models.SlugField(unique=True)
content = models.TextField(null=True, blank=True)
publish_date = models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True)
timestamp = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
objects = BlogPostManager()
class Meta:
ordering = ['-publish_date', '-updated', '-timestamp']
def __str__(self):
return self.title
def get_absolute_url(self):
return f"/blog/{self.slug}"
def get_edit_url(self):
return f"{self.get_absolute_url()}/edit"
def get_delete_url(self):
return f"{self.get_absolute_url()}/delete"
class Comment(models.Model):
comment_cont = models.TextField(max_length=200, verbose_name='Comment content')
user_name = models.ForeignKey(User, default=1, null=True, on_delete=models.SET_NULL)
comment_post = models.ForeignKey(BlogPost, on_delete=models.CASCADE, related_name='comments')
comment_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.comment_cont
def get_absolute_url(self):
return f"{BlogPost.get_absolute_url()}"
def get_add_url(self):
return f"{self.get_absolute_url()}/addc"
views.py
def add_comment_to_post(request, slug):
post = get_object_or_404(BlogPost, slug=slug)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('blog_post_detail_view', slug=post.slug)
else:
form = CommentForm()
template_name = 'formc.html'
context = {"title": f"New comment on {post.title}", "form": form}
return render(request, template_name, context)
urls.py
path('<str:slug>/addc', add_comment_to_post),
formc.html
<form method='POST' action='.' enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Comment</button>
</form>
button in home.html
<a class="btn btn-primary" href="{{ comments.get_add_url }}">Add Comment...</a>
I know the href for the button isn't right, but I can't figure out how to make it call the comment form. Please, I need help. Thanks.
I figured out what the href could be. I kinda feel like I was purposefully left to figure this one out on my own lol.
Please let me know if there's a better way I could do this. Thanks!!
home.html
<a class="btn btn-primary" href="/{{blog_post.slug}}/addc/">Add Comment...</a>

Django Formset issue - POST doesn't seems to work

I'm trying to use django formset for the first time in order to combine both forms on the same page.
My form is well displayed but I don't overvome to save data in my database. When I click on submit button, nothing happens.
This is my model.py file :
class Publication(models.Model):
title = models.CharField(max_length=512, verbose_name=_('title'), null=False)
category = models.ForeignKey(Category, verbose_name=_('category'), null=False)
creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('creation date'), null=False)
modification_date = models.DateTimeField(auto_now=True, verbose_name=_('modification date'), null=False)
class Meta:
verbose_name = _('publication')
verbose_name_plural = _('publication')
def __str__(self):
return f"{self.title}"
class Document(models.Model):
FORMAT_CHOICES = (
('pdf', 'pdf'),
('epub', 'epub'),
)
format = models.CharField(max_length=10, verbose_name=_('format'), choices=FORMAT_CHOICES, null=False)
title = models.CharField(max_length=512, verbose_name=_('title'), null=False)
publication = models.ForeignKey(Publication, verbose_name=_('publication'), null=False)
upload = models.FileField(upload_to='media/', default="")
creation_date = models.DateTimeField(auto_now_add=True, verbose_name=_('creation date'), null=False)
modification_date = models.DateTimeField(auto_now=True, verbose_name=_('modification date'), null=False)
class Meta:
verbose_name = _('document')
verbose_name_plural = _('document')
def __str__(self):
return f"{self.age_id} : {self.title}"
My form file is very simple too with defined Formset :
class PublicationForm(forms.ModelForm):
class Meta:
model = Publication
fields = ('title', 'category')
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = ['publication', 'format', 'title', 'upload']
DocumentFormSet = inlineformset_factory(Publication, Document, form=DocumentForm, extra=1)
My view is a bit more complicated :
class PublicationCreateUpdateView(AgePermissionRequiredMixin, UpdateView):
""" Display a form to create or update a publication
Only for age admin.
**Context**
``subtitle``
Title of the page
**Template:**
:template:`app/category_form.html`
"""
model = Publication
form_class = PublicationForm
success_url = reverse_lazy('app:app-publication-list')
template_name = 'app/publication_form.html'
permission_required = 'publication.change_webapplication'
def get_object(self, queryset=None):
try:
return super(PublicationCreateUpdateView, self).get_object(queryset)
except AttributeError:
return None
def get_title(self):
if self.object:
return _('Edit publication: ') + str(self.object)
return _('Add new publication')
def get_context_data(self, **kwargs):
context = super(PublicationCreateUpdateView, self).get_context_data(**kwargs)
if self.request.POST :
context['documents'] = DocumentFormSet(self.request.POST)
else :
context['documents'] = DocumentFormSet()
context.update({
'subtitle': self.get_title(),
})
return context
def form_valid(self, form):
context=self.get_context_data()
documents = context['documents']
with transaction.atomic():
self.object = form.save()
if documents.is_valid():
documents.instance = self.object
documents.save()
return super(DocumentCreateUpdateView, self).form_valid(form)
And finally my template looks like this :
{% extends "publication/base_backend.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block main %}
<form method="post" novalidate>
{% csrf_token %}
{% crispy form %}
{{ documents.management_form }}
{{ documents.non_form_errors }}
{% crispy documents %}
<br>
<input type="submit" class="btn btn-default" value="{% trans 'Save' %}" />
{% trans 'Cancel' %}
</form>
{% endblock main %}
I don't understand where I could make a mistake, furthermore I'm pretty new with Django Class Based View.

Django] Saving multiple images by formset doesn't work

I'm trying to save multiple Images and his parent's data together on the same template.
I have one parent's model(to save normal data) and child's model(to save images). In this case, saving parent's data is working very well. but images are not work.
There isn't any error message.
//model
class QuotationPanchok(models.Model):
whose = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=50, help_text='', default='')
many = models.IntegerField(default='1', help_text='')
design = models.CharField(max_length=3, choices=(('yes', 'yes'), ('no', 'no'),))
sian = models.CharField(max_length=3, choices=(('yes','yes'), ('no', 'no'),))
havefile = models.CharField(max_length=3, choices=(('yes','yes'), ('no', 'no'),))
deadline = models.DateField(blank=True)
addressto = models.CharField(max_length=50, default='', help_text='')
fulltext = models.TextField(max_length=150, blank=True)
status = models.CharField(max_length=7, choices=(('not','not'), ('finish', 'finish'),), default='not')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class ImagesForQuotation(models.Model):
whose = models.ForeignKey(QuotationPanchok, on_delete=models.CASCADE)
image = models.ImageField(upload_to='images/', blank=True, null=True)
def __str__(self):
return self.whose.title + " Image"
// views
def quotation_create(request):
ImageFormset = modelformset_factory(ImagesForQuotation, fields=('image',), extra=4)
if request.method == 'POST':
form = QuotationCreateForm(request.POST)
formset = ImageFormset(request.POST or None, request.FILES or None)
if form.is_valid() and formset.is_valid():
post = form.save(commit=False)
post.whose = request.user
post.save()
for f in formset:
try:
photo = ImagesForQuotation(whose=post, image=f.cleaned_date['image'])
photo.save()
except Exception as e:
break
return redirect('index')
else:
form = QuotationCreateForm()
formset = ImageFormset(queryset=ImagesForQuotation.objects.none())
context = {
'form': form,
'formset': formset,
}
return render(request, 'quotationapp/quotation_create.html', context)
//forms
class QuotationCreateForm(forms.ModelForm):
class Meta:
model = QuotationPanchok
fields = (
'title',
'many',
'design',
'sian',
'havefile',
'deadline',
'addressto',
'fulltext',
)
def __init__(self, *args, **kwargs):
super(QuotationCreateForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control'
//template(quotation_create.html)
{% block content %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
{{ formset.as_table }}
<input type="submit" class="btn btn-primary" value="">
</form>
{% endblock %}
How can I solve this problem?
Thank you..

django form how to render the fields

I'm trying to render a form but the fields are not displayed in the HTML.
views.py
#url(r'^boxes/(?P<pk>[0-9A-Za-z-]+)/$', views.show_form, name='box'),
def show_form(request, pk):
box = Box.objects.get(pk=pk)
form = SuggestionForm()
context = {
'box':box,
'form':form
}
return render(request, 'boxes/detail.html', context)
forms.py
class SuggestionForm(ModelForm):
class Meta:
model = Suggestion
fields = ['comment']
detail.html
<h3>{{box.title}}</h3>
<form action="." method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-info" value="Add suggies" />
</form>
My models.py
#python_2_unicode_compatible
class Suggestion(models.Model):
"""
For adding comments (or suggestions)
"""
def __str__(self):
return self.comment[0:10]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
comment = models.CharField("",max_length=250, blank=True, null=True)
box = models.ForeignKey(Participant, on_delete=models.CASCADE)
created_at = models.DateField(auto_now_add=True)
updated_at = models.DateField(auto_now=True)
The result HTML.. There is no fields in this form. I want to use a function based view.