Comment thread in Django - python

I am building up a simple Django app with blogs and comments on blogs. While developing the comment thread, I am getting the error "no such table: blog_commentsonpost" when I try to enter a comment. Can someone help me to solve the issue.
models.py
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
title = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
def publish(self):
self.published_date = timezone.now()
self.save()
def get_type(self):
return "post"
def get_absolute_url(self):
return reverse("post_detail", kwargs={'pk': self.pk})
def __str__(self):
return self.title
class CommentsOnPost(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='comment')
post = models.ForeignKey('blog.Post', on_delete=models.CASCADE, related_name='comments')
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
text = models.CharField(max_length=1000)
#classmethod
def create(cls, author, text, post):
postcomment = cls(author=author,
post_id=post,
text=text, created_date=timezone.now,
published_date=timezone.now)
return postcomment
views.py
class PostDetailView(DetailView):
model = Post
redirect_field_name = 'post_detail'
def post(self, request, *args, **kwargs):
author = request.user
text = request.POST['postcomment']
post = request.POST['post']
postcomment = CommentsOnPost()
postcomment.text = text
postcomment.author = author
postcomment.save()
return HttpResponseRedirect('/blog/post/{}'.format(post))
html
<form method="POST" class="post-form" >{% csrf_token %}
<div class="form-group">
<label for="postcomment">Comments:</label>
<textarea class="form-control" name="postcomment" rows="5"></textarea>
</div>
<input type="hidden" name="post" value="{{ post.id }}">
<div>
<input type="submit" class="btn btn-primary" style="color:blue;" value="Comment"/>

Did you run python manage.py makemigrations and python manage.py migrate?
If it is a new app, did you add it to the settings.py?

Related

Can't render out user specific content

I am trying to render out model objects that are unique to a user. All methods I've found haven't worked and I've been trying to figure this out for a while now. What is supposed to happen is that you can see the jobs you've posted in the manage-jobs.html template. Also I've removed all of my failed attempts to render out user specific content, it's not that I haven't tried to do this by myself. Thanks.
models.py
class Job(models.Model):
company = models.CharField(max_length=40, null=True, verbose_name="Company/Employer")
description = models.TextField(null=True)
role = models.CharField(max_length=25)
area_of_filming = models.CharField(max_length=50, verbose_name="Area Of Filming", default="")
contact_email = models.EmailField(verbose_name='Contact Email', max_length=60, default='')
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(Account, default='', null=True, on_delete=models.CASCADE)
def __str__(self):
return self.company
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
name = models.CharField(max_length=45, unique=False)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_employee = models.BooleanField(default=True, verbose_name='Are you using FilmLink as an employee?')
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'is_employee']
objects = MyAccountManager()
class Meta:
permissions = [
("post_jobs", "Can post jobs"),
]
def __str__(self):
return self.name
def has_perm(self, perm, obj=None):
return True
def has_perms(self, perm):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.is_admin
views.py
#login_required(login_url='login')
def manage_jobs(request):
if request.user.is_employee:
return redirect('home')
else:
form = JobForm(request.POST)
if form.is_valid():
form.save()
context = {"form":form}
return render(request, 'employer/manage-jobs.html', context)
manage-jobs.html
<button id="myBtn">Post A Job</button>
<div id="main"></div>
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">&times</span>
<form action="" method="POST">
{% csrf_token %}
<div id="company-container">
<p>Employer Name</p>
<p id="employer">{{form.company}}</p>
</div>
<div id="role-container">
<p>Role (e.g. Actor, Director)</p>
<p id="role">{{form.role}}</p>
</div>
<div class="area-of-filming-container">
<p>Area Of Production/Filming</p>
<p id="area-of-filming">{{form.area_of_filming}}</p>
</div>
<div id="contact-email-container">
<p>Contact Email</p>
<p id="contact-email">{{form.contact_email}}</p>
</div>
<div id="description-container">
<p>Description Of Job</p>
<p id="description">{{form.description}}</p>
</div>
<button type="submit" id="post-job">Publish Job</button>
</form>
</div>
</div>
You said that this should render out "jobs". This is only going to render out one job but I am going to assume you intend to solve that after you can actually see content on your screen.
I think the problem is to do with your frontend form.
Note that on your views.py function manage_jobs, that if the user is not an employee you create a form by POST, but the frontend is not connecting to that request.POST.
I am not sure how your urls.py file looks, but you want to link to that views.py call from your form.
In your <form action="{% url 'manage_jobs' %}" method="POST">
This may not be your solution, but I would check out this anyway.
Hope you can figure it out!

How to save foreign key data using forms.py?

urls.py
...
path('restaurant/menu/', r_view.Menu, name='menu'),
...
menu.html
<form method="POST" id="menuForm" autocomplete="off" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-inline">
<div class="form-group mb-4">
{{ form.item|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.itemImage|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.price|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.category|as_crispy_field }}
</div>
</div>
<button type="submit" class="col-md-12 myBtn">Submit</button>
</form>
views.py
def Menu(request, restaurantID):
restaurant = get_object_or_404(Restaurant_Account, restaurantID=restaurantID)
form = MenuForm()
if request.method == 'POST':
form = MenuForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.restaurant = restaurant
instance.save()
messages.success(request, "Saved successfully!")
return redirect('r_index')
context = {'form':form}
return render(request, 'restaurant/menu.html', context)
forms.py
class MenuForm(forms.ModelForm):
restaurantID = Restaurant_Account.objects.filter(restaurantID='restaurantID')
item = forms.CharField(required=True)
itemImage = forms.ImageField(required=False, label='Item image')
price = forms.DecimalField(required=True)
category = forms.ChoiceField(choices=CATEGORY)
class Meta:
model = Menu
fields = ('item', 'itemImage', 'price', 'category')
models.py
class Restaurant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_restaurant = models.BooleanField(default=True)
restaurantID = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
isActive = models.BooleanField(default=True)
image = models.ImageField(upload_to='images/', blank=True)
website = models.URLField(blank=True, unique=False)
country = models.CharField(max_length=50)
def __str__(self):
return self.user.username
class Menu(models.Model):
menuID = models.AutoField(primary_key=True)
restaurantID = models.ForeignKey(Restaurant_Account, on_delete=models.CASCADE, default=None)
item = models.CharField(max_length=100)
itemImage = models.ImageField(upload_to='images/', blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
category = models.CharField(
max_length=20,
choices=[('', 'Choose category'),('Appetizer', 'Appetizer'),('Entree', 'Entree'),('Drink', 'Drink'),('Dessert', 'Dessert'), ('Side', 'Side')])
def __str__(self):
return self.item
I'm new to Django.
I made a form for saving menu data. If the user fills the form and click the submit button every data should be saved in the Menu table. I have no idea how to save restaurantID, which is a foreign key that refers to the Restaurant table, automatically. (By automatically I mean without the user entering input) Can somebody help me with this?
You haven't need to do all these things, if you have made restaurantID a foreign key while defining the model that is Menu, django itself handles it.
Below code might work for you:
forms.py
class MenuForm(forms.ModelForm):
item = forms.CharField(required=True)
itemImage = forms.ImageField(required=False, label='Item image')
price = forms.DecimalField(required=True)
category = forms.ChoiceField(choices=CATEGORY)
class Meta:
model = Menu
fields = ('item', 'itemImage', 'price', 'category')
views.py
def menu(request):
if request.method == 'POST':
form = MenuForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request, "Saved successfully!")
return redirect('r_index')
else:
form=MenuForm()
return render(request, 'restaurant/menu.html', {'form':form})
optional: You also don't need to write this line menuID = models.AutoField(primary_key=True) in Menu model, as django makes id column by default for AutoField.
Update:
Make your models.py in this way:
MY_CHOICES=[
('', 'Choose category'),
('Appetizer', 'Appetizer'),
('Entree', 'Entree'),
('Drink', 'Drink'),
('Dessert', 'Dessert'),
('Side', 'Side')
]
class Restaurant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_restaurant = models.BooleanField(default=True)
name = models.CharField(max_length=200)
isActive = models.BooleanField(default=True)
image = models.ImageField(upload_to='images/', blank=True)
website = models.URLField(blank=True, unique=False)
country = models.CharField(max_length=50)
def __str__(self):
return self.user.username
class Menu(models.Model):
restaurant= models.ForeignKey(Restaurant, on_delete=models.CASCADE, default=None)
item = models.CharField(max_length=100)
itemImage = models.ImageField(upload_to='images/', blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
category = models.CharField(
max_length=20,
choices=MY_CHOICES)
def __str__(self):
return self.item
Remove your AutoField, django by default make id which is primary key.
Don't forget to run makemigrations and migrate, after doing this, if it still gives error, so comment your all models and then run.

How to send an error to user that already add book to favorite

I'm trying to make a user stop adding a book into favorite when they already added and show the message into template.
Here's my class django python:
class User(models.Model):
fname = models.CharField(max_length=255)
lname = models.CharField(max_length=255)
email = models.EmailField()
password = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = UserManager()
class Book(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
uploaded_by = models.ForeignKey(User,
related_name="book_uploaded", on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = BookManager()
class Like(models.Model):
u_like = models.ForeignKey(
User, related_name="user_like", on_delete=models.CASCADE)
b_like = models.ForeignKey(
Book, related_name="book_like", on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
And here's my views.py:
def book_info(request, id):
user_who_like = Book.objects.get(id=id).book_like.all()
context = {
'book': Book.objects.get(id=id),
'user': User.objects.get(id=request.session["user_id"]),
'user_who_like': Book.objects.get(id=id).book_like.all(),
'user_uploaded': Book.objects.first().uploaded_by,
}
return render(request, 'book_info.html', context)
def like(request, id):
book = Book.objects.get(id=id)
user = User.objects.get(id=request.session["user_id"])
like = Like.objects.create(u_like=user, b_like=book)
return redirect(f"/books/{book.id}")
Appreciate all your help! Thank you
You can try this:
def like(request, id):
book = Book.objects.get(id=id)
user = User.objects.get(id=request.session["user_id"])
like = Like.objects.get_or_create(u_like=user, b_like=book)
if not like[1]:
message = "Already added to favourite"
return redirect(f"/books/{book.id}")
Here, what get_or_create does is it creates an object if the object is not already present and it returns a tuple, the object itself and a boolean value. If the object is newly created then it will return True otherwise False. You can then send this message on you template in a conventional way.
this is my def:
def like(request, id):
book = Book.objects.get(id=id)
user = User.objects.get(id=request.session["user_id"])
like = Like.objects.get_or_create(u_like=user, b_like=book)
if not like[1]:
messages.error(request,"Already added to favorite",extra_tags="like_error")
return redirect("/books/")
context = {
'like1': like[1],
}
return redirect(f"/books/{book.id}")
and here's my template:
<form action="/books/{{book.id}}/like/" method="post" class="like">
{% csrf_token %}
<button type="submit" class="btn far fa-thumbs-up"></button>
{% if messages %}
<ul class="messages">
{% for message in messages %}
{% if "like_error" in message.tags %}
<li class="text-danger">{{ message }}</li>
{%endif%}
{% endfor %}
</ul>
{%endif%}
</form>

Reading and saving data to a Django model

I am trying to understand how to save data into my Django models. I have a form that display Questions and choices from my models. I want the user to answer the question and to be saved in the Answer model. Here are my models
class Question(models.Model):
question_text = models.CharField(max_length=200)
caption = models.CharField(max_length=200, default="this is a caption")
choices = models.ManyToManyField(Choice)
vis_image = models.ImageField(default= "this is an image", null=False, blank=False, upload_to="static/study/img")
def __str__(self):
return self.question_text
class Condition(models.Model):
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class Participant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
condition = models.ForeignKey(Condition, on_delete=models.CASCADE)
score = models.IntegerField(default=0)
def __str__(self):
return self.user.username
class Answer(models.Model):
participant = models.ForeignKey(Participant, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
answer = models.CharField(max_length=200, null=True)
completion_time = models.FloatField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.answer
views.py
#login_required
def LPSC_VIEW1(request):
participant=Participant.objects.get(user=request.user)
#GET the first question based on the participant condition
if participant.condition.name == 'LPN':
First_question= Question.objects.get(id=1)
all_choices = First_question.choices.all()
context = {'First_question': First_question, 'all_choices': all_choices}
return render(request, 'study/FirstQN.html', context)
else:
First_question= Question.objects.get(id=11)
all_choices = First_question.choices.all()
context = {'First_question': First_question, 'all_choices': all_choices}
return render(request, 'study/FirstQSC.html', context)
FirstQN.html
<form method="POST">
{% csrf_token %}
<label>
{{First_question}}
</label>
<img src="{{ First_question.vis_image.url }}" style= "height: 600px; width: 960px">
{% for i in all_choices %}
<input type="radio" id="choice" name="choice" value="{{ choice.id }}">
<label for="choice">{{ i.choice_text }}</label>
{% endfor %}
<input type="button" value="Submit" class="btn btn-primary" onclick="window.location.href = server_url +'/study/LPSC_VIEW2'">
</form>
my question is can I use the same view to read data from the database and save data submitted from the user on the same view? or do I have to create a new view but then wouldn't that result in redundancy? I have read about saving data from forms but couldn't understand how to apply it on my case where the form itself is fetched from the database. At the moment the code above all works fine.
You can reuse the view, and is a standard way of doing it using function-based views. Just check the request.method as follows:
#login_required
def LPSC_VIEW1(request):
...
if request.method == 'POST':
# do your code for saving the answers here
... the rest of your code

Additional help text to form in Django

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.

Categories