I'm Trying to add comments to Facts(posts). When I try to submit a comment I get the following error? I'm using Postgres FYI
IntegrityError at /fc/2/comment/
null value in column "comment_id" violates not-null constraint
DETAIL: Failing row contains (8, It has plugins too, 2018-10-03 07:41:25.249524+00, 1, null).
Exception Value:
null value in column "comment_id" violates not-null constraint
DETAIL: Failing row contains (8, It has plugins too, 2018-10-03 07:41:25.249524+00, 1, null).
Model:
class Fact(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(
default=timezone.now)
published_date = models.DateTimeField(
blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
class Comment(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
comment = models.ForeignKey('fc.Fact', on_delete=models.CASCADE, related_name='comments')
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
View:
def add_comment_to_post(request,pk):
fc = get_object_or_404(Fact, pk=pk)
if request.method =="POST":
form =CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.fc = fc
comment.save()
return redirect('fc_detail',pk=fc.pk)
else:
form =CommentForm()
return render(request,'add_comment_to_post.html',{'form':form})
Form view:
{% extends 'base.html' %}
{% block content %}
<h1>Check this fact</h1>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
{% endblock %}
Form:
class FcForm(forms.ModelForm):
class Meta:
model = Fact
fields = ('title', 'text',)
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text',)
Why is the comment_id null, I would have thought Django auto-populates this as it did with my Fact model.
Appreciate help on this.
Thank you.
It should be
comment.comment = fc
instead of
comment.fc = fc
hence your view will be
def add_comment_to_post(request, pk):
fc = get_object_or_404(Fact, pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.comment = fc # change is here <<<
comment.save()
return redirect('fc_detail', pk=fc.pk)
else:
form = CommentForm()
return render(request, 'add_comment_to_post.html', {'form': form})
Related
thanks for your time:
i've been having a problem on my POST request its getting me de code 302.0
it should create a object that is related to the user that did the request:
views.py:
#login_required
#transaction.atomic
def parceiros_create(request):
if request.method == 'POST':
form = ParceirosForm(request.POST, instance=request.user.parceiros)
if form.is_valid():
form.save()
messages.success(request, ('Parceiro criado'))
return redirect('home2')
else:
messages.error(request, ('Please correct the error below.'))
else:
form = ParceirosForm(instance=request.user)
context = {
'form': form,
}
return render (request, 'parceiroform.html', context)
forms.py:
class ParceirosForm(forms.ModelForm):
nome = forms.CharField(max_length=200)
endereco = forms.TextInput()
responsavel = forms.CharField(max_length=100)
tel = PhoneField(max_length=12)
class Meta:
prefix = 'parceiro'
model = Parceiros
fields = ['nome', 'endereco', 'responsavel', 'tel']
models.py:
get_user_model = User
class Parceiros (models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
nome = models.CharField(max_length=200)
endereco = models.TextField(max_length=400, blank=True)
responsavel = models.CharField(max_length=100)
tel = PhoneField(max_length=12)
created_at = models.DateTimeField(auto_now=True)
updated_at = models.DateTimeField(auto_now_add=True, blank=True)
ativo = models.BooleanField(default=False)
def __str__(self):
return '%s %s' % (self.user, self.nome)
parceiroform.html:
{% extends 'base.html' %}
{% block content %}
<h1>ok</h1>
<h1>OK</h1>
<h1>ok</h1>
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button type="submit">Save</button>
</form>
{% endblock %}
i'm getting the message (parceiro criado) on my admin although ain't creating any object(Parceiros).
You are not handling the user so change it like this
if form.is_valid():
obj = form.save(commit=False)
obj.user = request.user
obj.save()
....
I have to insert the post through a form but when i submit i got this error FOREIGN KEY constraint failed, the problem is with the author field
models.py
class Post(models.Model):
STATUS_CHOICES = (
('draft','Draft'),
('published','Published'),
)
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=120)
author = models.ForeignKey('auth.User',related_name='blog_posts',on_delete=models.CASCADE,blank=True, null=True)
body = RichTextField()
created = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,choices=STATUS_CHOICES,default='draft')
tag = models.OneToOneField(Tag,related_name="blog_tag",on_delete=models.CASCADE,default=0)
def __str__(self):
return self.title
views.py
def tagView(request,name):
tag = Tag.objects.get(name=name)
post_form = PostForm(request.POST or None)
if request.method == 'POST':
post_form = PostForm(request.POST)
if post_form.is_valid():
item = post_form.save(commit=False)
item.author = request.user
item.save()
return HttpResponseRedirect(request.path_info)
context = {
'post_form' : post_form,
'tag' : tag,
}
return render(request,'blog/tagPage.html',context)
forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title','body']
template
<form class="post-form" method="POST" enctype="multipart/form-data" action="">
{% csrf_token %}
{{ post_form }}
<input class="post-form-submit submit" type="submit" value="Save">
</form>
If the author field is the problem, be sure to import auth.User
My guess is that you are trying to add the post as anonymous but anonymous user is not null (id is though). Also don't use 'auth.User' and follow the instructions from the documentation.
My problem is that I can not save the form. I think the problem lies in the event field in the Register model.
I do not want the user to choose an Event from the list, I want it to happen automatically, hence the code: form.cleaned_data['event'] = kwargs['pk']
This part of code kwargs['pk'] is from url.
Please any hint if this is good approch to dealing with forms and hint to solve my problem. Below is my code.
Thanks :)
Models:
class Event(models.Model):
title = models.CharField(max_length=500)
date = models.DateField()
text = models.TextField()
image = FilerImageField(null=True, blank=True)
flag = models.ForeignKey(Flag)
free_places = models.IntegerField()
class Meta:
ordering = ['-date']
def __str__(self):
return self.title
#property
def slug(self):
return slugify(self.title)
def get_absolute_url(self):
return reverse('events:detail', args=[self.slug, self.id])
class Register(models.Model):
event = models.ForeignKey(Event)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
company = models.CharField(max_length=30, blank=True)
street = models.CharField(max_length=50, blank=True)
post_code = models.CharField(max_length=30, blank=True)
city = models.CharField(max_length=30, blank=True)
email = models.EmailField()
phone_number = models.IntegerField()
def __str__(self):
return self.first_name
def get_event_name(self):
return self.event
View:
class EventDetailView(DetailView, ModelFormMixin):
model = models.Event
form_class = forms.RegisterForm
def get_success_url(self):
return reverse('events:list')
def post(self, request, *args, **kwargs):
form = self.get_form()
print(kwargs['pk'])
print(self.form_class)
if form.is_valid():
print(form.cleaned_data['event'])
form.cleaned_data['event'] = kwargs['pk']
form.save()
return self.form_valid(form)
else:
return self.form_invalid(form)
My form:
class RegisterForm(ModelForm):
class Meta:
model = models.Register
fields = ('event', 'first_name', 'last_name', 'company', 'street', 'post_code', 'city', 'email', 'phone_number',)
My template:
{% extends 'base.html' %}
{% block content %}
<ul>
<h1>Detail page:</h1>
<li>{{ object.title }}</li>
<li>{{ object.text }}</li>
<li>{{ object.date }}</li>
</ul>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
{% endblock content %}
What you are doing here is to insert into a validated data. Instead of that,
Initialize the form with request POST data which should include "event" key and its value you got from kwargs['pk']. Then validate it and save. You will not get validation errors, as well as the value will be saved.
Basically, even the event id you get from the url that has to be validated. Django does with db level check against the pk value you passed when you call is_valid.
I'm making a comment system for my django app and i've been told it's best to make a seperate model for comment-voting. So i've done that and here's my models.py:
class Comment(models.Model):
user = models.ForeignKey(User, default=1)
destination = models.CharField(default='1', max_length=12, blank=True)
author = models.CharField(max_length=120, blank=True)
comment_id = models.IntegerField(default=1)
parent_id = models.IntegerField(default=0)
comment_text = models.TextField(max_length=350, blank=True)
timestamp = models.DateTimeField(default=timezone.now, blank=True)
def __str__(self):
return self.comment_text
class CommentScore(models.Model):
user = models.ForeignKey(User, default=1)
comment = models.ForeignKey(Comment, related_name='score')
upvotes = models.IntegerField(default=0)
downvotes = models.IntegerField(default=0)
def __str__(self):
return str(self.comment)
Here's my views.py where the comments are created:
def article(request, category, id):
name = resolve(request.path).kwargs['category']
for a, b in CATEGORY_CHOICES:
if b == name:
name = a
instance = get_object_or_404(Post, id=id, category=name)
allauth_login = LoginForm(request.POST or None)
allauth_signup = SignupForm(request.POST or None)
#comments
comment = CommentForm(request.POST or None)
ajax_comment = request.POST.get('text')
comment_length = len(str(ajax_comment))
#database_comment = get_object_or_404(Comments, comment_id=1)
comment_list = Comment.objects.filter(destination=id)
score = CommentScore.objects.filter(comment=comment_list)
if request.is_ajax():
if comment.is_valid():
comment = Comment.objects.create(comment_text=ajax_comment, author=str(request.user), destination=id)
print(comment)
comment.save()
score = CommentScore.objects.create(comment=comment)
score.save()
username = str(request.user)
return JsonResponse({'text': ajax_comment, 'text_length': comment_length, 'username': username})
else:
print(comment.errors)
context = {
'score': score,
'comment_list': comment_list,
'comment': comment,
'instance': instance,
'allauth_login': allauth_login,
'allauth_signup': allauth_signup
}
return render(request, 'article.html', context)
So the comment works fine, but as you can see a couple lines later i'm trying to then create a CommentScore instance to match with the comment. In my template, I've rendered each comment and it's fields (comment_text, author etc), but I want to render the upvotes field associated with that comment. How would I do this?
template
{% for i in comment_list %}
<div class='comment_div'>
<h3>{{ i.author }}</h3>
<p>{{ i.comment_text }}</p><br>
</div>
{% endfor %}
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = [
'comment_text',
'id',
'author',
'destination',
]
In your view you have this line:
comment_list = Comment.objects.filter(destination=id)
so if you want to get to CommentScore that associated with Comment, you have to write like this on your view:
score = CommentScore.objects.filter(comment=comment_list)
filter expects multiple variable so you can access to upvotes in your template, like this:
{% for i in score %}
{{i.upvotes}}
{% endfor %}
if you have single score instance, you have to use get parameter:
score = CommentScore.objects.get(comment=comment_list)
then you can you just
{{score.upvotes}}
on your template
When I create or edit model CV, I need to input some data in birth_date field. It's working, but I want to add some additional text to define some date format like (yyyy-mm-dd). I'm using cripsy forms for better look of forms. How can I add this help text ?
my code:
template.html
{% block profile %}
<div class="jumbotron">
<h2>Edit your basic informations</h2>
<hr>
<form method="POST" class="post-form" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</div>
{% endblock %}
models.py
class Cv(models.Model):
author = models.ForeignKey('auth.User')
name = models.CharField(max_length=25, null = True)
surname = models.CharField(max_length=25, null = True)
city = models.CharField(max_length=100, blank=True)
birth_date = models.DateField(blank=True, null=True)
email = models.EmailField(max_length=50, null=True)
main_programming_language = models.CharField(max_length=15, null = True)
specialization = models.CharField(max_length=30, blank=True, null=True)
interests = models.TextField(blank=True, null=True)
summary = models.TextField(blank=True, null=True)
#thumbnail = models.FileField(upload_to=get_upload_file_name, blank=True)
#property
def age(self):
return int((datetime.datetime.now().date() - self.birth_date).days / 365.25 )
def zapisz(self):
self.save()
def __str__(self):
return self.surname.encode('utf-8')
forms.py
class CvForm(forms.ModelForm):
class Meta:
model = Cv
fields = ('name', 'surname', 'city', 'birth_date', 'email', 'main_programming_language', 'specialization', 'interests', 'summary',)
views.py
#login_required
def new_cv(request):
if request.method == "POST":
form = CvForm(request.POST, request.FILES)
if form.is_valid():
cv = form.save(commit=False)
cv.author = request.user
cv.save()
return redirect('proj.views.cv_detail', pk=cv.pk)
else:
form = CvForm()
return render(request, 'new_cv.html', {'form': form})
Can add help_text to your model fields:
birth_date = models.DateField(blank=True, null=True, help_text="format (yyyy-mm-dd)")
see more Django Model and Form docs.
You can also use external library JQuery Tooltip too.