How to add comments without authentification required - python

i just done comments on my website,and i want to do non-authorized comments,and dont know how to.My models looks like this
class Comment(models.Model):
article = models.ForeignKey(Product, on_delete = models.CASCADE, verbose_name='Page', blank = True, null = True,related_name='comments' )
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete = models.CASCADE, verbose_name='Comment author', blank = True, null = True )
create_date = models.DateTimeField(auto_now=True)
text = models.TextField(verbose_name='Comment text', max_length=500)
status = models.BooleanField(verbose_name='Visible', default=False)
and views.py like this
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.article = self.get_object()
self.object.author = self.request.user
self.object.save()
return super().form_valid(form)

def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.article = self.get_object()
if self.request.user.is_authenticated:
self.object.author = self.request.user
else:
self.object.author = None
self.object.save()
return super().form_valid(form)
note: remove else block if you get an error

Related

Adding an `if` statement to send an Email when the count of Likes reaches a certain No

I am trying to add an IF statement so that when the Like Count reaches 2 an email is sent. I have written the codes but it is not working, I am trying with the below but it is not working.
My question is how to add an if statement so that when any item with likes more the 2 an email is sent a specific email.
Here is the models.py
class Post(models.Model):
title = models.CharField(max_length=100, unique=True)
likes = models.ManyToManyField(
User, related_name='liked', blank=True)
def __str__(self):
return self.title
def total_likes(self):
return self.likes.count()
Here is the views.py
class PostDetailView(DetailView):
model = Post
template_name = "post_detail.html"
def get_context_data(self, *args, **kwargs):
context = super(PostDetailView, self).get_context_data()
post = get_object_or_404(Post, slug=self.kwargs['slug'])
comments = Comment.objects.filter(
post=post, reply=None).order_by('-id')
total_likes = post.total_likes()
liked = False
if post.likes.filter(id=self.request.user.id).exists():
liked = True
if self.request.method == 'POST':
comment_form = CommentForm(self.request.POST or None)
if comment_form.is_valid():
content = self.request.POST.get('content')
reply_id = self.request.POST.get('comment_id')
comment_qs = None
if reply_id:
comment_qs = Comment.objects.get(id=reply_id)
comment = Comment.objects.create(
post=post, user=self.request.user, content=content, reply=comment_qs)
comment.save()
return HttpResponseRedirect("post_detail.html")
else:
comment_form = CommentForm()
context["total_likes"] = total_likes
context["liked"] = liked
context["comments"] = comments
context["comment_form"] = comment_form
return context
def get(self, request, *args, **kwargs):
res = super().get(request, *args, **kwargs)
self.object.incrementViewCount()
return res
def LikeView(request):
# post = get_object_or_404(Post, id=request.POST.get('post_id'))
post = get_object_or_404(Post, id=request.POST.get('id'))
liked = False
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
liked = False
else:
post.likes.add(request.user)
liked = True
context = {
'total_likes': post.total_likes,
'liked': liked,
'post': post
}
if post.likes.count() == 2:
msg = EmailMessage('Count Reached',
settings.EMAIL_HOST_USER, [request.user.email])
msg.content_subtype = "html" # Main content is now text/html
msg.fail_silently = False
msg.send()
if request.is_ajax:
html = render_to_string('like_section.html', context, request=request)
return JsonResponse({'form': html})
If you want this this happen everywhere, I would recommend adding an override to the save() method of the Post model, and send the email there when it increases to two likes. You can also use Django's send_mail function, which is a nice wrapper for sending email. Fat models, skinny views, dumb templates is a mantra for best Django practices. Maybe something like this:
from django.core.mail import send_mail
class Post(models.Model):
title = models.CharField(max_length=100, unique=True)
likes = models.ManyToManyField(
User, related_name='liked', blank=True)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if self.total_likes() == 2:
send_mail(
"my subject",
"my text message",
"myemail#myhost.com",
["myuser#theirhost.com"],
html_message="<h1>My HTML Message</h1>",
)
super().save(*args, **kwargs)
def total_likes(self):
return self.likes.count()
Good luck!

Can anyone help me to create update view in django?

views.py
class DreamHeroView(CreateView):
template_name = 'dream_hero.html'
model = Character
form_class = DreamHeroForm
def get(self, *args, **kwargs):
form = DreamHeroForm()
return render(self.request, 'dream_hero.html', {'form': form})
def post(self, *args, **kwargs):
form = DreamHeroForm(self.request.POST, self.request.FILES or None)
if form.is_valid():
title = form.cleaned_data['title']
description = form.cleaned_data['description']
strenght = form.cleaned_data['strenght']
power = form.cleaned_data['power']
weapon = form.cleaned_data['weapon']
hero_image = form.cleaned_data['hero_image']
slug = form.cleaned_data['slug']
post = Character(
title=title,
description=description,
strenght=strenght,
power=power,
weapon=weapon,
hero_image=hero_image,
slug=slug,
user=self.request.user,
)
post.save()
return redirect('character-post')
return render(self.request, 'dream_hero.html')
views.py
class StoryDetailView(FormMixin, DetailView):
model = Character
template_name = 'story.html'
context_object_name = 'comment_set'
form_class = CharCommentForm
def get_context_data(self, **kwargs):
context = super(StoryDetailView, self).get_context_data(**kwargs)
context['commenting'] = self.object.charactercomment_set.all()
context['pro_pic'] = get_object_or_404(Author, user=self.request.user)
context['charform'] = CharCommentForm()
return context
def get_success_url(self):
return reverse('story-post', kwargs={
'slug': self.object.slug
})
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.post = self.get_object()
form.save()
return super().form_valid(form)
form.py
class DreamHeroForm(forms.Form):
title = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Name of your hero'
}))
description = forms.CharField(widget=forms.Textarea(attrs={
'class': 'form-control',
'placeholder': 'Story of your Hero'
}))
slug = forms.SlugField()
hero_image = forms.ImageField()
strenght = forms.IntegerField()
power = forms.IntegerField()
weapon = forms.IntegerField()
Django has an UpdateView built in.
from django.views.generic.edit import UpdateView
class MyUpdateView(UpdateView):
model = MyModel
fields = ["field_1", "field_2"] # or use form_class = MyForm
template_name = "myapp/mymodel_update.html"
You'll need a PK in your url for the update view so it can look up the model instance correctly (you can override this by setting lookup_url_kwarg in the class IIRC)
Docs:
https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-editing/#updateview

Post comment inside Django DetailView

I need to add comments in article page. Post request receives data but not saves it.
In models.py:
class TemporaryComment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='temporary_comment')
email = models.EmailField()
message = models.TextField(max_length=1500)
timestamp = models.DateTimeField(auto_now_add=True)
is_approved = models.BooleanField(default=True)
In forms.py:
class CommentModelForm(forms.ModelForm):
class Meta:
model = TemporaryComment
fields = [
'article',
'email',
'message',
]
in views.py:
class ArticleDetailView(FormMixin, DetailView):
model = Article
template_name = 'article.html'
form_class = CommentModelForm
def get_success_url(self):
return reverse_lazy('main:article', kwargs={'pk': self.object.pk})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['last_articles'] = Article.objects.filter(is_active=True).order_by('-timestamp')[:10]
context['comments'] = self.object.temporary_comment.filter(is_approved=True)
context['form'] = self.get_form()
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.save()
return super().form_valid(form)
If i comment out article field in forms.py, i got this error:
null value in column "article_id" violates not-null
constraint. DETAIL: Failing row
contains (18, username#email.com, check message, 2019-01-20 18:35:36.615955+00, t, null).
Help will be gladly accepted. Thanks for your time.
You should comment it out, and set it in form_valid.
def form_valid(self, form):
form.instance.article = self.object
form.save()
return super().form_valid(form)

formset validation in CBV

I have an Order form where I used formsets because I want the user to dynamically add more products and their quantity.
The user enters the name of the order, and it is validated not to be empty.
How do I validate the formset itself? to check that the product/quantity is not empty
views.py
class OrderCreateView(CreateView):
model = Order
template_name = "orderform.html"
fields = ['name', ]
def get_context_data(self, **kwargs):
data = super(OrderCreateView, self).get_context_data(**kwargs)
if self.request.POST:
data['productmetas'] = InlineOrderFormSet(self.request.POST)
return data
def form_valid(self, form):
context = self.get_context_data()
productmetas = context['productmetas']
self.object = form.save(commit=False)
self.object.save()
if productmetas.is_valid():
productmetas.instance = self.object
productmetas.save()
return super(OrderCreateView, self).form_valid(form)
models.py
class ProductMeta(models.Model):
order = models.ForeignKey(Order)
product = models.ForeignKey(Product)
quantity = models.FloatField()
forms.py
InlineOrderFormSet = inlineformset_factory(Order, ProductMeta,
form=OrderAutoCompleteForm,
extra=1)
For anyone interested in the working solution for the question above
adapted from the answer by #neverwalkaloner
def form_valid(self, form):
context = self.get_context_data()
productmetas = context['productmetas']
with transaction.atomic():
self.object = form.save()
if form.is_valid():
if productmetas.is_valid():
productmetas.instance = self.object
productmetas.save()
else:
return super(OrderCreateView, self).form_invalid(form)
return super(OrderCreateView, self).form_valid(form)

Django's CreateView is not saving an object

I'm practicing Django's generic views, particularly ModelForms
These are my views and models
models.py
class Post(models.Model):
user = models.ForeignKey(User)
post_title = models.CharField(max_length=200)
post_content = models.CharField(max_length=500)
post_date = models.DateTimeField('date posted')
def get_absolute_url(self):
return reverse('user-detail', kwargs={'pk': self.pk})
def __unicode__(self):
return self.post_title
forms.py
class PostForm(forms.ModelForm):
post_title = forms.CharField(
label=u'Title',
widget=forms.TextInput(attrs={'size':64})
)
post_content = forms.CharField(
label=u'Content',
widget=forms.TextInput(attrs={'size':128})
)
class Meta:
model = Post
views.py
class PostCreate(CreateView):
fields = ['post_title', 'post_content']
template_name = 'app_blog/post_save_form.html'
model = Post
form_class = PostForm
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(PostCreate, self).dispatch(*args, **kwargs)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.post_date = datetime.now()
return super(PostCreate, self).form_valid(form)
The view seems to work fine, not displaying any errors. However, when I check the Django admin page after submitting a form and saving a post, the post is not saved into the database for some reason.
Any idea why this is happening?
As I can see from your code you use
self.object = form.save(commit=False)
which mean that object will not be saved to database, but you can use it for futher processing. So you should use something like this:
self.object = form.save(commit=False) # Not hit database
self.object.user = self.request.user # Update user
self.object.post_date = datetime.now() # Update post_date
self.object.save() # And finally save your object to database.
Try this.
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.post_date = datetime.now()
return super(PostCreate, self).form_valid(form)

Categories