comment is not saved in view.py - django

The codes (below) must enable a user to comment on a post/page. Thus, the comment is linked to that page. But after the submit event, the comment is not saved, hence nothing is displayed except the comments from the Admin page.
Function that display the page and the comment in view.py
def list_page(request, list_id):
if request.user.is_authenticated:
list_auction = Auction_listings.objects.get(id=list_id)
categories = Category.objects.get(id = list_id)
return render(request, "auctions/auc_details.html", {
"detail": list_auction,
"cats":categories,
"user": request.user,
"comments": list_auction.comment.all(),
})
else:
list_auction = Auction_listings.objects.get(id =list_id)
return render(request, "auctions/auc_details.html", {
"detail":list_auction
})
comment function in view.py
def comment(request, list_id):
if request.user.is_authenticated:
list_auction = get_object_or_404(Auction_listings, pk=list_id)
if request.method == "POST":
comment_form = forms.Create_comment(request.POST)
if comment_form.is_valid():
com_t = comment_form.save(commit=False)
com_t.comment = list_auction
com_t.comment_by = request.user
com_t.save()
print(com_t)
return HttpResponseRedirect(reverse("list_page", args=(list_auction.id,)))
return render (request,"auctions/auc_details.html", {
"detail": list_auction,
"user": request.user,
"comments": list_auction.comment.all(),
})
Route in urls.py
path("<int:list_id>/comment", views.comment, name="comment"),
Form class in form.py
class Create_comment(forms.ModelForm):
class Meta:
model = models.Comment
fields = ['comment']
Model class in models.py
Comment model
class Comment(models.Model):
comment_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="commentor", blank=False)
comment_on = models.ForeignKey( Auction_listings, related_name="comment", on_delete=models.CASCADE)
comment = models.CharField(max_length=600)
comment_date_published = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.comment}"
Page model (auction_listings
class Auction_listings(models.Model):
auc_title = models.CharField(max_length=50)
auc_details = models.CharField(max_length=250)
auc_price = models.IntegerField()
auc_date_published = models.DateTimeField(auto_now_add=True)
auc_created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="creator", blank=True)
auc_image = models.ImageField(default='rose.jpg', blank=True)
auctions = models.ManyToManyField(Category, blank= True, related_name="category")
def __str__(self):
return f"{self.auc_title}"
html page
<form action="{% url 'comment' detail.id %}" method="POST">
{% csrf_token %}
<input type="text" name="text">
<input type="hidden" name="auction_id" value="{{detail.id}}">
<button type=" submit ">Create</button>
</form>
I tried to change the route to look like:
path("/comment/<int:list_id>", views.comment, name="comment"),
Tried
But that didn't change anything.

If you expect the comment to attach to list_auction there should be a connection between them
com_t.comment_on = list_auction
OR
com_t.comment_on_id = list_auction.id
in your case:
if comment_form.is_valid():
com_t = comment_form.save(commit=False)
com_t.comment = 'the text of comment'
com_t.comment_on = list_auction
com_t.comment_by = request.user
com_t.save()
print(com_t)
return HttpResponseRedirect(reverse("list_page", args=(list_auction.id,)))
NOTE: For better debugging, check your database to see how the data is stored

1. Call the Create_comment from form.py
def list_page(request, list_id):
if request.user.is_authenticated:
list_auction = Auction_listings.objects.get(id=list_id)
categories = Category.objects.get(id = list_id)
comment_form = forms.Create_comment()
return render(request, "auctions/auc_details.html", {
"detail": list_auction,
"cats":categories,
"user": request.user,
"comments": list_auction.comment.all(),
"com_form":comment_form,
})
else:
list_auction = Auction_listings.objects.get(id =list_id)
return render(request, "auctions/auc_details.html", {
"detail":list_auction
})
2 Call the ""com_form"" on the template.
<form action="{% url 'comment' detail.id %}" method="POST">
{% csrf_token %}
{{com_form}}
<button type=" submit ">Create</button>
</form>

Related

how to delete previous uploaded file when a new one gets uploaded using id

I have simple cv upload class for users to upload their resume. it works just fine but when they upload a newer one, the previous wont get deleted.
this is my code:
class ResumeDocument(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
cvfile = models.FileField(upload_to="documents", null=True, validators= [validate_file_extension])
#property
def filename(self):
return os.path.basename(self.cvfile.name)
how can I reach the previous id? id = self.id - 1. something like that.
this is my views:
#login_required
def pdf_resume(request):
if request.method == 'POST':
form = DocumentForm(request.POST,request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('pdf_resume')
if 'delete' in request.GET:
return delete_item(ResumeDocument, request.GET['id'])
else:
form = DocumentForm()
documents = ResumeDocument.objects.filter(user=request.user)
if documents:
form = DocumentForm(instance=documents[0])
context = {
'form':form,
'documents':documents,
}
return render(request, 'reg/pdf_resume.html', context)
and this is also my HTML code:
<form id="document-form" method="POST" enctype="multipart/form-data" action="{% url 'pdf_resume' %}" autocomplete="off" class="ant-form ant-form-horizontal">
{% csrf_token %}
<p>{{ form }}</p>
<div class="ant-row-flex" style="margin-left: -10px; margin-right: -10px;"></div>
<button id="btn_submit" type="submit"
class="ant-btn ant-btn-primary"
ant-click-animating-without-extra-node="false" style="float: left;"><span>upload</span></button>
</form>
One possible solution is to save all uploaded CVs for each user and track the last uploaded CV with field uploaded_on. You may refer to the below high-level example:
class CVFile(models.Model):
file_name = models.CharField(max_length=200)
cv_file = models.FileField(upload_to="documents", null=True, validators=[validate_file_extension])
uploaded_on = models.DateTimeField(default=timezone.now, blank=True)
class ResumeDocument(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
cv_file = models.ForeignKey(CVFile, on_delete=models.CASCADE)
You will need to amend your HMTL and views.py accordingly.
models.py
class ResumeDocument(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
cvfile = models.FileField(upload_to="documents", null=True, validators=
[validate_file_extension])
views.py(i just look is there any resumedocuments for that user if yes so i give him
the form just if he was editing the existing file)
#login_required
def pdf_resume(request):
if request.method == 'POST':
form = DocumentForm(request.POST,request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('pdf_resume')
if 'delete' in request.GET:
return delete_item(ResumeDocument, request.GET['id'])
else:
form = DocumentForm()
documents = ResumeDocument.objects.filter(user=request.user)
if documents:#new
form = DocumentForm(instance=documents[0])
context = {
'form':form,
'documents':documents,
}
return render(request, 'reg/pdf_resume.html', context)
now inside your pdf_resume.html your can just pass the 'form' because you already check if that user has a document or not.

Django formsets do not save images

I have an addpage form where users have to add their card for boots model. Below i will show to you my code.
SO! The problem is my images are not saving at my media directory at all. And so one of the
consequences Card.model doesn't take this images, but rest of the form fields working perfictly. Sorry for my bad english and asking for support!!
Models.py
class Card(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name='Категория')
brand = models.ForeignKey(Brand, on_delete=models.PROTECT, verbose_name='Бренд')
boots_model = models.CharField(max_length=100, db_index=True, verbose_name='Модель бутс')
description = models.TextField(verbose_name='Описание')
slug = AutoSlugField('URL', max_length=70, db_index=True, unique_with=('created', 'boots_model', 'size', 'color', 'price'), populate_from=instance_boots_model, slugify=slugify_value)
price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='Цена')
# image = models.ImageField(upload_to="photos/%Y/%m/%d/", blank=True, verbose_name='Загрузите фотографии')
created = models.DateTimeField(auto_now_add=True, db_index=True)
updated = models.DateTimeField(auto_now=True)
size = models.DecimalField(max_digits=4, decimal_places=1, verbose_name='Размер')
NEW = 'new'
USED = 'old'
STATEMENT_CHOICES = [
(NEW, 'Новые'),
(USED, 'Б/У')
]
statement = models.CharField(max_length=3, choices=STATEMENT_CHOICES, default=USED, verbose_name='Состояние')
color = models.CharField(max_length=100, db_index=True, verbose_name='цвет')
class Meta:
ordering = ('-created',)
verbose_name = 'Объявление'
verbose_name_plural = 'Объявления'
def __str__(self):
return self.boots_model
def save(self, *args, **kwargs):
self.slug = uuslug(self.slug, instance=self)
super(Card, self).save(*args, **kwargs)
def get_absolute_url(self):
category = self.category
brand = self.brand
return reverse('card', args=[str(category.slug), str(brand.slug), str(self.slug)])
class ImagePhoto(models.Model):
directory = models.ForeignKey(Card, on_delete=models.CASCADE)
image = models.ImageField(upload_to=upload_custom_directory, blank=True, verbose_name='Фотографии')
def __str__(self):
return str(self.image)
class Meta:
verbose_name = 'Фотографии'
verbose_name_plural = 'Фотографии'
forms.py
class AddCardForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['category'].empty_label = "Категория не выбрана"
self.fields['brand'].empty_label = "Бренд не выбран"
# self.fields['boots_model'].help_text = "Старайтесь вводить полное название обуви"
class Meta:
model = Card
fields = ['category', 'brand', 'boots_model', 'description', 'price', 'size', 'statement', 'color']
help_texts = {
'boots_model': 'Название на английском языке с цифрами\nНапример: PREDATOR 18.3 FG',
}
widgets = {
'description': forms.Textarea(attrs={'cols': 30, 'rows': 5, 'placeholder': 'Введите что-нибудь'}),
}
def clean_boots_model(self):
cyrillic_letters = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
boots_model = self.cleaned_data['boots_model']
for c in boots_model:
if c in cyrillic_letters:
raise ValidationError('Допускается название только на английском языке и цифры')
return boots_model
class AddimgForm(forms.ModelForm):
class Meta:
model = ImagePhoto
fields = ['image']
widgets = {
'image': forms.ClearableFileInput(attrs={'multiple': True}),
}
and finally views.py
def add_page(request):
MyFormSet = inlineformset_factory(Card, ImagePhoto, fields=('image',), extra=0)
if request.method == 'POST':
form = AddCardForm(request.POST)
formset = MyFormSet(request.POST, request.FILES,)
if form.is_valid() and formset.is_valid():
c = form.save(commit=False)
c.save()
for f in formset:
pic = ImagePhoto(directory=c, image=f.cleaned_data('image'))
pic.save()
return redirect('home')
else:
form = AddCardForm()
formset = MyFormSet(queryset=ImagePhoto.objects.none())
return render(request, 'mysite/addpage.html', {'formset': formset, 'form': form, 'title': 'Добавить объявление'})
also addcard.html
<form action="{% url 'addpage' %}" method="post" enctype="multipart/form-data" class="addpage-form">
{% csrf_token %}
<h1>Разместить объявление</h1>
{% for p in form %}
{% if p.help_text %}<p class="help-text">{{ p.help_text|linebreaksbr }}{% endif %}
<p><label class="form-label" for="{{ form.id_for_label }}">{{ p.label }}: </label>{{ p }}</p>
{% endfor %}
{{ formset.management_form }}
<input type="file" name = "files" multiple />{% for f in formset %}
<div class="form-error">{{ f.errors }}</div>
{% endfor %}
<div class="addpage-button-submit">
<button type="submit">Добавить объявление</button>
</div>
</form>

Add multiple hidden fields in Django Form

I'm using Django. I need a form that shows the 3 fields of a class that I have created, the idea is that every time you want to add a new day and time to start and end, show a new new section, so that each teacher can be found in more of a day and time of beginning and end (the three fields go together)
I still do not logo to make it work, if someone has any idea they would be grateful.
Models.py
class Profesor(Person):
legajo = models.IntegerField(blank=True, null=True)
type = models.CharField(max_length=30)
matter = models.CharField(max_length=100, blank=True, null=True)
calendar = models.ForeignKey('calendar', on_delete=models.DO_NOTHING)
user = models.CharField(max_length=20, blank=True, null=True)
class calendar(models.Model):
day = models.DateTimeField(default=date.today().isoweekday())
hs_init = models.DateTimeField(default=datetime.now().hour)
hs_end = models.DateTimeField(default=datetime.now().hour)
Forms.py
class addProfesorForm(ModelForm):
calendar = forms.ModelChoiceField(queryset=calendar.objects.all(), widget=forms.HiddenInput())
class Meta:
model = Profesor
TYPES = (
('Motiv', 'Motiv'),
('Academic', 'Académic'),
('Otro', 'Otro')
)
help_texts = {
'matter': 'message'
}
fields = ['id', 'type', 'matter']
widgets = {
'type': Select2Widget(choices=typeS)
}
class calendarForm(ModelForm):
class Meta:
model = calendar
fields = ['day','hs_init','hs_end']
Views.py
def agregarTutor(request):
if request.method == 'POST':
form = addProfesorForm(request.POST['calendar'])
calendar=calendar.objects.all()[0]
if form.is_valid():
id = form.cleaned_data['id']
try:
person_Sysatem = SysatemPerson.objects.get(pk=id)
alumn_Sysatem = SysatemAlumn.objects.get(pk=id)
except SysatemPerson.DoesNotExist:
return render(request, 'menu/new-Profesor.html',
{'new_manual': True, 'not_found': True, 'nbar': 'profesors', 'id': id})
new_Profesor = Profesor(
nombre=person_Sysatem.nombre.rstrip(),
id=person_Sysatem.numerodocu,
legajo=alumn_Sysatem.legajo,
telefono=person_Sysatem.telefono.rstrip(),
mail=person_Sysatem.mail.rstrip(),
type=form.cleaned_data['type'],
calendar=form.cleaned_data['calendar'],
matter=form.cleaned_data['matter'],
user=id,
)
Profesor.save(new_Profesor)
contrasena = 'id'+str(id)[0:5]
user = User.objects.create_user(id, person_Sysatem.mail.rstrip(), contrasena)
user.first_name = person_Sysatem.nombre.rstrip()
user.save()
form = addProfesorForm(initial={'calendar':calendar})
return render(request, 'menu/new-Profesor.html', {'form': form, 'Profesor': new_Profesor, 'success': True, 'nbar': 'profesors'})
else:
return render(request, 'menu/new-Profesor.html', {'form': form, 'error_form': True, 'nbar': 'profesors'})
else:
form = addProfesorForm()
return render(request, 'menu/new-Profesor.html', {'form': form, 'nbar': 'profesors'})
Template.html
<h2>new Profesor</h2>
<div class="row">
<div class="col">
<form method="post">{% csrf_token %}
{% include 'common/form_template.html' with form=form %}
<button type="submit" style="margin-top: 10px; float: right;" class="btn btn-primary">Add</button>
</form>
</div>
</div>

Edit UserProfile information in Django

Problem description: UserProfile form doesn't save any data.
I am creating a new User and automatically create a UserProfile object for him (so I'm extending UserProfile), so I can go to admin page and fill all the fields . But when I'm trying to do it from client side, my form just doesn't catch the data.
Also the strangest moment is that I can change username and email using UserChangeForm, so I'm trying to do the same for UserProfileObject.
models.py:
class UserProfile(models.Model):
user = models.OneToOneField(User)
image = models.ImageField(upload_to='profile_image', blank=True)
title = models.CharField(max_length=100, default = '')
first_name = models.CharField(max_length=200, default = '')
last_name = models.CharField(max_length=200, default = '')
subject = models.ManyToManyField('Subject', related_name='tutor_type', default = '', help_text="Select a subject")
AREA_STATUS = (
('Jerusalem', 'Jerusalem'),
('Tel Aviv', 'Tel Aviv'),
('Haifa', 'Haifa'),
('Eilat', 'Eilat')
)
area = models.CharField(max_length=200, choices=AREA_STATUS, blank=True, default='', help_text='Tutor area')
# Foreign Key used because tutor can only have one area, but area can have multiple tutors
# Author as a string rather than object because it hasn't been declared yet in file.
description = models.TextField(max_length=4000, help_text="Enter a brief description about yourself")
charge = models.IntegerField(default = '0')
# ManyToManyField used because Subject can contain many tutors. Tutors can cover many subjects.
# Subject declared as an object because it has already been defined.
LANGUAGE_CHOICES = (
('English','English'),
('Hebrew','Hebrew'),
('Russian','Russian'),
('French','French'),
('Arabic','Arabic'),
)
language = models.CharField('Language', choices = LANGUAGE_CHOICES, max_length=50, null=True)
def __str__(self):
return self.user.username
def display_subject(self):
"""
Creates a string for the subject. This is required to display subject in Admin.
"""
return ', '.join([ subject.name for subject in self.subject.all()[:3] ])
display_subject.short_description = 'Subject'
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender = User)
forms.py::
class EditProfileForm(UserChangeForm):
class Meta:
model = User
fields = (
'username',
'email',
'password'
)
class EditExtendedProfileForm(UserChangeForm):
class Meta:
model = UserProfile
fields = '__all__'
exclude = ('user',)
views.py:
def edit_profile(request):
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect(reverse('accounts:view_profile'))
else:
form = EditProfileForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/edit_profile.html', args)
def edit_extended_profile(request):
if request.method == "POST":
form = EditExtendedProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect(reverse('accounts:view_profile'))
else:
return redirect(reverse('accounts:edit_extended_profile'))
else:
form = EditExtendedProfileForm(instance = request.user)
args = {'form':form}
return render(request, 'accounts/edit_extended_profile.html', args)
edit_extended_profile.html:
{% extends "base.html" %}
{% block head %}
<title>Profile</title>
{% endblock %}
{% block body %}
<div class = "container">
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button type = "submit" class = "btn btn-success">Submit</button>
</form>
</div>
{% endblock %}
and it is the same template as for edit_profile view.
No traceback, no errors. Any help will be appreciated. Thanks in advance.

How to create and process a form with multiple same fields?

I'm really stuck with this. To show my problem I created a new Django project and started from scratch, focusing only on one single form.
What I'm trying to do is to create a form with several fields of the same name. I tried using modelformset_factory to achieve this but it looks to me like it's not what I really need.
Below is my code (also on dpaste) which currently works fine with one single field called name. How can I create and process a form which would have several name fields? Could somebody point me in the right direction?
# models.py
class Category(models.Model):
name = models.CharField(max_length=30, unique=True)
user = models.ForeignKey(User, blank=True, null=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
# forms.py
class CategoryForm(ModelForm):
class Meta:
model = Category
fields = ('name',)
# views.py
def home(request):
if request.method == 'POST':
catform = CategoryForm(request.POST)
catformInstance = catform.save(commit = False)
catformInstance.save()
return HttpResponseRedirect('')
else:
catform = CategoryForm()
context = {'catform': catform}
return render_to_response('home.html', context, context_instance=RequestContext(request))
# home.html template
<h3>Insert new Category</h3>
<form action="/" method="post" id="ingr-cat-form">{% csrf_token %}
{{ catform.as_p }}
<input type="submit" name="ingrCatForm" value="Save" />
</form>
UPDATE: to clarify, I want to allow user to insert several categories within one form. I think I'm getting close, here is my new version of views.py but it still stores just one category (the last one in the list):
def home(request):
if request.method == 'POST':
catform = CategoryForm(request.POST)
names = request.POST.getlist('name')
catformInstance = catform.save(commit = False)
for name in names:
catformInstance.name = name
catformInstance.save()
return HttpResponseRedirect('')
else:
catform = CategoryForm()
context = {'catform': catform}
return render_to_response('home.html', context, context_instance=RequestContext(request))
You cannot have fields with the same name (on the same Model). If you only need to change the html label in the html form, use
class Category(models.Model):
name = models.CharField(max_length=30, unique=True)
name2 = models.CharField(max_length=30, unique=True, verbose_name="name")
user = models.ForeignKey(User, blank=True, null=True)
or
class CategoryForm(ModelForm):
def __init__(self , *args, **kwargs):
super(CategoryForm, self).__init__(*args, **kwargs)
self.fields['name2'].label = "name"
Here is a working solution. Thanks to #YardenST for pointing me in the right direction. I managed to solve my initial problem by following this tutorial.
# models.py
class Category(models.Model):
name = models.CharField(max_length=30, unique=True)
user = models.ForeignKey(User, blank=True, null=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
# forms.py
class CategoryForm(ModelForm):
class Meta:
model = Category
fields = ('name',)
# views.py
def home(request):
if request.method == 'POST':
catforms = [CategoryForm(request.POST, prefix=str(x), instance=Category()) for x in range(0,3)]
if all([cf.is_valid() for cf in catforms]):
for cf in catforms:
catformInstance = cf.save(commit = False)
catformInstance.save()
return HttpResponseRedirect('')
else:
catform = [CategoryForm(prefix=str(x), instance=Category()) for x in range(0,3)]
context = {'catform': catform}
return render_to_response('home.html', context, context_instance=RequestContext(request))
# home.html template
<h3>Insert new Category</h3>
<form action="/" method="post" id="ingr-cat-form">{% csrf_token %}
{% for catform_instance in catform %} {{ catform_instance.as_p }} {% endfor %}
<input type="submit" name="ingrCatForm" value="Save" />
</form>