I want to set value, but i don't know how do it.
Error:
RelatedObjectDoesNotExist at /comments/
commentsTabl has no avtor.
Request Method: GET
Request URL: http://localhost:8000/comments/
Django Version: 4.0.2
Exception Type: RelatedObjectDoesNotExist
Exception Value:
commentsTabl has no avtor.
Exception Location: D:\python39\lib\site-packages\django\db\models\fields\related_descriptors.py, line 197, in get
Python Executable: D:\python39\python.exe
Python Version: 3.9.6
Python Path:
['D:\Django\ForumXT\first',
'D:\python39\python39.zip',
'D:\python39\DLLs',
'D:\python39\lib',
'D:\python39',
'D:\python39\lib\site-packages']
Server time: Thu, 07 Apr 2022 12:20:35 +0000
models.py
class commentsTabl(models.Model):
Text = models.TextField(verbose_name='Text')
date = models.DateTimeField(default=timezone.now, verbose_name='date')
avtor = models.ForeignKey(User, verbose_name='avtor', on_delete=models.CASCADE, to_field="username")
def __str__(self):
return f'Comment {self.avtor} at {self.date}'
class Meta:
verbose_name = "Comment"
verbose_name_plural = "Comments"
views.py
def comments(request):
data = {
'com': reversed(commentsTabl.objects.all())
}
if request.method =="POST":
form = commentsTabl(request.POST)
if form.is_valid():
form.save()
else:
form = commentsTabl()
return render(request, 'home/comments.html', data, {'form':form})
In models.py
class Comment(models.Model):
Text = models.TextField(verbose_name='Text')
date = models.DateTimeField(auto_add_now=True, verbose_name='date')
avtor = models.ForeignKey(User, verbose_name='avtor', on_delete=models.CASCADE)
def __str__(self):
return 'Comment {} at {}'.format(self.avtor, self.date)
class Meta:
# Order comments in reverse order
# ordering = ["-id"]
In views.py
from .forms import CommentForm
from .models import Comments
from django.http import HttpResponseRedirect
from django.urls import reverse
def comments(request):
# Retrive all comments from database
comments = Comment.objects.all()
# Reverse ...
comments = reversed(comments)
# Form with no data (unbound form)
form = CustomerForm()
context = {"comments": comments, "form": form}
# when method is post
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
# Don't save the form to database
comment = form.save(commit=False)
# Add user to the comment
comment.avtor = request.user
# Save comment to database
comment.save()
return HttpResponseRedirect(reverse('some url name'))
# when form is invalid
else:
# Re-render the form with errors and data
context["form"] = form
return render(request, "home/comments.html", context)
# when method is not post
else:
return render(request, "home/comments.html", context)
In forms.py
from django.forms import ModelForm
from .models import Comment
# Create your forms here
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ("Text", "date",)
# or
# exclude = ("avtor",)
# fields = "__all__"
Important
python manage.py makemigrations
python manage.py migrate
In comments.html you will have access to form and comments
Related
My models.py:
from django.db import models
# Create your models here.
class modelBlog(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
body = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True,)
def __str__(self):
return ('{}.{}').format(self.id, self.title)
class comment(models.Model):
blog = models.ForeignKey(modelBlog, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
komentar = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True,)
My forms.py:
from .models import modelContact, comment
from django import forms
class CommentForm(forms.ModelForm):
class meta:
model = comment
fields = [
'name',
'komentar',
]
widgets = {
'name': forms.TextInput(attrs={'class':'form-control'}),
'komentar': forms.Textarea(attrs={'class':'form-control'}),
}
And views.py:
def detail(request, id):
blog = modelBlog.objects.get(id=id)
form = CommentForm()
if request.method == 'POST':
nama = request.POST['nama']
comment = request.POST['komentar']
new_comment = blog.comment_set.create(name=nama,komentar=comment)
new_comment.save()
messages.success(request, 'Komentar berhasil ditambahkan')
return redirect('blog:detail', id)
judul = blog.title
context = {
'title':judul,
'blog':blog,
'form':form
}
return render(request, 'blog/detail.html', context)
i got error
ValueError at /blog/1/
ModelForm has no model class specified.
Request Method: GET
Request URL: http://localhost:8000/blog/1/
Django Version: 4.0.2
Exception Type: ValueError
Exception Value:
ModelForm has no model class specified.
I think, you have written meta in smallcase, write it in Pascal case that is Meta and write all your models in PascalCase such as Comment etc.
how can I fix this issue?
the page runs perfectly. when I do post the post. it posts but when I want to type the comment and send by 'GET' I get this error. so, how can I ignore this error this my first question?
- also, I need anyone to give me the best way to make a relationship between post and comment
models.py
from django.db import models
from django.contrib.auth.models import User
class Publication(models.Model):
title = models.CharField(max_length=30)
class Meta:
ordering = ['title']
def __str__(self):
return self.title
class Article(models.Model):
publications = models.ManyToManyField(Publication)
headline = models.CharField(max_length=100)
class Meta:
ordering = ['headline']
def __str__(self):
return self.headline
class Post(models.Model):
users = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
question = models.TextField(max_length=500)
def __str__(self):
return self.title
class Comment(models.Model):
posts = models.ForeignKey(Post, on_delete=models.CASCADE)
comment = models.TextField(max_length=500)
def __str__(self):
return self.comment
views.py
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from .models import Post, Comment
from .forms import PostForm, CommentForm
def index(request):
# All questions
posts = Post.objects.all()
return render(request, 'community/index.html', {'posts': posts})
def post_view(request):
post_form = PostForm
context = {'posted': post_form}
# Create post
if request.method == 'GET':
post_form = PostForm(request.GET)
if post_form.is_valid():
user_post = post_form.save(commit=False)
user_post.title = post_form.cleaned_data['title']
user_post.question = post_form.cleaned_data['question']
post = Post.objects.create(users=User.objects.get(username=request.user), title=user_post.title, question=user_post.question)
post.save()
return redirect('community:index')
return render(request, 'community/post.html', context)
def answers(request, post_id):
# Specific post
posts = Post.objects.get(id=post_id)
# Create comment
comment_form = CommentForm
context = {'posts': posts, 'comment_form': comment_form}
if request.method == 'GET':
comment_form = CommentForm(request.GET)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
user_comment.comment = comment_form.cleaned_data['comment']
user_comment.save()
return render(request, 'community/answers.html', context)
urls.py
from django.urls import path
from . import views
app_name = 'community'
urlpatterns = [
path('', views.index, name='index'),
path('post/', views.post_view, name='post'),
path('answers/<int:post_id>', views.answers, name='answers'),
]
forms.py
from .models import Post, Comment
from django import forms
from django.contrib.auth.models import User
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = '__all__'
exclude = ['users']
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = '__all__'
exclude = ['users', 'posts']
You forgot to assign the post, or the post_id of the comment you created:
def answers(request, post_id):
# Specific post
posts = Post.objects.get(id=post_id)
# Create comment
comment_form = CommentForm
context = {'posts': posts, 'comment_form': comment_form}
if request.method == 'GET':
comment_form = CommentForm(request.GET)
if comment_form.is_valid():
comment_form.instance.post_id = post_id
user_comment = comment_form.save()
# …
That being said, the above view does not really respect the HTTP assumptions. A view that makes a GET request is not supposed to change entities, so if you want to create a comment, you need to do that through a POST request. Furthemore in order to implement the Post/Redirect/Get pattern [wiki] a successful POST request should return a redirect response.
When I try to save a post, the post is saved, but current user is not registered and the post is duplicated with a blank entry and the current user is not stored.
For adding the post I use not the admin app but a personal template and form.
See the problem:
This is my view code:
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from .forms import NewAdminPostForm
from .models import Post, Category
# Create your views here.
def home(request):
posts = Post.objects.all()
categories = Category.objects.all()
posts_last = Post.objects.order_by('-created_at')[0:3]
return render(request, 'front/blog-list.html', {'posts': posts,
'categories': categories, 'posts_last': posts_last})
#login_required
def newadminpost(request):
if request.method == 'POST':
form = NewAdminPostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
Post.objects.create(
message=form.cleaned_data.get('message'),
category_id=post.category_id,
created_by=request.user
)
#post.save()
return redirect('listadminpost')
else:
form = NewAdminPostForm()
return render(request, 'back/new-post-blog.html', {'form': form})
#login_required
def listadminpost(request):
posts = Post.objects.all()
return render(request, 'back/list-post-blog.html', {'posts': posts})
Form of my Blog:
from django import forms
from .models import Post, Category
class NewAdminPostForm(forms.ModelForm):
title = forms.CharField(label="Titre de l'article", max_length=255,)
message = forms.CharField(widget=forms.Textarea(),
max_length=4000,
help_text="Contenu de l'article")
pre_message = forms.CharField(label="Message de prévisu",
widget=forms.Textarea(),
max_length=4000,
help_text="Contenu de l'article")
class Meta:
model = Post
fields = ['title','meta_desc','message','pre_message','category']
Model of my Blog:
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=255, unique=True)
description = models.TextField(max_length=1000)
def __str__(self):
return self.name
def get_categories_count(self):
return Category.objects.filter(post__category=self).count()
class Post(models.Model):
title = models.CharField(max_length=255)
meta_desc = models.TextField(max_length=320, null=True)
pre_message = models.TextField(max_length=4000, null=True)
message = models.TextField(max_length=4000)
category = models.ForeignKey(Category, on_delete='cascade')
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE,
blank=True, null=True)
def __str__(self):
return self.title
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.create
your code:
post.save()...Post.objects.create(
from the link above:
A convenience method for creating an object and saving it all in one step. Thus:
p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
and:
p = Person(first_name="Bruce", last_name="Springsteen")
p.save(force_insert=True)
are equivalent.
So what you do in your code:
you save post object created from form
you create and save another Post instance by calling create method
choose any of them, just one, and this will avoid duplicates.
Instead of doing this:
#login_required
def newadminpost(request):
if request.method == 'POST':
form = NewAdminPostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
Post.objects.create(
message=form.cleaned_data.get('message'),
category_id=post.category_id,
created_by=request.user
)
#post.save()
return redirect('listadminpost')
else:
form = NewAdminPostForm()
return render(request, 'back/new-post-blog.html', {'form': form})
You could do this: cleaner, easier to read, more up-to-date, and easier to maintain:
class AdminCreateView(LoginRequiredMixin, generic.CreateView):
model = Request
form_class = RequestForm
def form_valid(self, form):
result = super(AdminCreateView, self).form_valid(form)
title = form.cleaned_data.get('title')
meta_desc = form.cleaned_data.get('meta_desc')
message = form.cleaned_data.get('message')
# and so on. if there's something you refuse (ex title empty) do this:
if not title:
form.add_error('title', _("Precise the title"))
return self.form_invalid(form)
Post.objects.create(message=message,
meta_desc=meta_desc,
title=title,) # and so on
return result
I will be really grateful if anyone can help to resolve the issue below.
I have the following Django project coding. The problem is: when the browser was given "/posts/remove/<post_id>/" or "/posts/edit/(<post_id>/" as the url, it will allow the second user (not owner) to perform the remove and edit jobs, respectively.
How can I allow only the owner of a new post to edit or delete the post?
account.models.py:
from django.db import models
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
def __str__(self):
return 'Profile for user {}'.format(self.user.username)
posts.models.py:
from django.db import models
from django.conf import settings
from django.utils import timezone
from django.utils.text import slugify
from django.core.urlresolvers import reverse
from taggit.managers import TaggableManager
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self).get_queryset().filter(status='published')
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='posts_created')
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique_for_date='created')
image = models.ImageField(upload_to='images/%Y/%m/%d', null=True, blank=True)
description = models.TextField(blank=True)
created = models.DateTimeField(default=timezone.now,
db_index=True)
updated = models.DateTimeField(auto_now=True)
users_like = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name='posts_voted',
blank=True)
status = models.CharField(max_length=10, default='published')
objects = models.Manager() # The default manager.
published = PublishedManager() # The Dahl-specific manager.
tags = TaggableManager()
class Meta:
ordering = ('-created',)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('posts:detail', args=[self.id, self.slug])
posts.view.py:
from django.views.decorators.http import require_POST
from django.shortcuts import render, redirect, get_object_or_404, render_to_response
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.conf import settings
from django.core.context_processors import csrf
from .forms import PostCreateForm, EmailPostForm, CommentForm, SearchForm
from .models import Post
from actions.utils import create_action
#login_required
def post_create(request):
"""
View for creating a new post.
"""
if request.method == 'POST':
# form is sent
form = PostCreateForm(data=request.POST, files=request.FILES)
if form.is_valid():
cd = form.cleaned_data
new_item = form.save(commit=False)
# assign current user to the item
new_item.user = request.user
tags = form.cleaned_data['tags']
new_item.save()
for tag in tags:
new_item.tags.add(tag)
new_item.save()
create_action(request.user, 'created a post:', new_item)
messages.success(request, 'Post added successfully')
form = PostCreateForm()
else:
messages.error(request, 'Error adding new post')
else:
# build form
form = PostCreateForm(data=request.GET)
return render(request, 'posts/post/create.html', {'section': 'posts',
'form': form})
#login_required
def post_remove(request, post_id):
Post.objects.filter(id=post_id).delete()
return redirect('posts:mypost')
#login_required
def post_edit(request, post_id):
item = Post.objects.get(pk=post_id)
if request.method == 'POST':
form = PostCreateForm(request.POST, instance=item)
if form.is_valid():
form.save()
return redirect('posts:mypost')
else:
form = PostCreateForm(instance=item)
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('posts/post/post_edit.html', args)
posts.urls.py
from django.conf.urls import url
from . import views
from .feeds import LatestPostsFeed
urlpatterns = [
url(r'^create/$', views.post_create, name='create'),
url(r'^remove/(?P<post_id>\d+)/$', views.post_remove, name='post_remove'),
url(r'^edit/(?P<post_id>\d+)/$', views.post_edit, name='post_edit'),
]
Add request.user == item.user check inside your method.
#login_required
def post_remove(request, post_id):
item = Post.objects.get(pk=post_id)
if request.user == item.user:
Post.objects.filter(id=post_id).delete()
return redirect('posts:mypost')
#login_required
def post_edit(request, post_id):
item = Post.objects.get(pk=post_id)
if request.user == item.user:
...
//write your code here
So i am testing a the inlineformset feature in Django, and so far have the following code:
Application name: Example
models.py
from django.db import models
from django.core.urlresolvers import reverse
class Recipe(models.Model):
pub_date = models.DateTimeField('Date Published', auto_now_add= True)
title = models.CharField(max_length=200)
instruction = models.TextField()
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('recipe_edit', kwargs={'pk': self.pk})
class Ingredient(models.Model):
recipe = models.ForeignKey(Recipe, related_name="ingredients")
ingredient = models.CharField(max_length=255)
def __unicode__(self):
return self.recipe_id
def get_absolute_url(self):
return reverse('ingredient_edit', kwargs={'pk': self.recipe_id})
forms.py
from django import forms
from models import Recipe, Ingredient
from django.forms.models import inlineformset_factory
MAX_INGREDIENTS = 5
IngredientFormSet = inlineformset_factory(
Recipe,
Ingredient,
can_delete=False,
extra=MAX_INGREDIENTS
)
class UserSubmittedRecipeForm(forms.ModelForm):
class Meta:
model = Recipe
exclude = ('pub_date',)
views.py
def recipe_create(request, template_name='example/recipe_form.html'):
if request.POST:
form = UserSubmittedRecipeForm(request.POST)
if form.is_valid():
recipe = form.save(commit=False)
ingredient_formset = UserSubmittedRecipeForm(request.POST, instance=recipe)
if ingredient_formset.is_valid():
recipe.save()
ingredient_formset.save()
return redirect('recipe_list')
else:
form = UserSubmittedRecipeForm()
ingredient_formset = IngredientFormSet(instance=Recipe())
return render(request, template_name, {
"form": form,
"ingredient_formset": ingredient_formset
}, context_instance=RequestContext(request))
Views version 2
This does not work either.
def recipe_create(request, template_name='example/recipe_form.html'):
if request.POST:
form = UserSubmittedRecipeForm(request.POST)
if form.is_valid():
created_recipe = form.save()
ingredient_formset = UserSubmittedRecipeForm(request.POST, instance=created_recipe)
if ingredient_formset.is_valid():
ingredient_formset.save()
return redirect('recipe_list')
else:
form = UserSubmittedRecipeForm()
recipe = Recipe()
ingredient_formset = IngredientFormSet(instance=recipe)
return render(request, template_name, {
"form": form,
"ingredient_formset": ingredient_formset
}, context_instance=RequestContext(request))
The problem that i am having is that the "ingredient" field from the Ingredient model is not saved every time the form is submitted.
There is no error displayed. The rest of the field from the Recipe model gets saved properly.
Does anyone know why is this?
Should
ingredient_formset = UserSubmittedRecipeForm(request.POST, instance=created_recipe)
be
ingredient_formset = IngredientFormSet(request.POST, instance=created_recipe)?
If that is the problem, you have made it in both views.
There was a typo in version 2 of views. Check whether this solves your problem
Views.py version 2:
def recipe_create(request, template_name='example/recipe_form.html'):
if request.POST:
form = UserSubmittedRecipeForm(request.POST)
if form.is_valid():
created_recipe = form.save()
#There was a typo here
ingredient_formset = IngredientFormSet(request.POST, instance=created_recipe)
if ingredient_formset.is_valid():
ingredient_formset.save()
return redirect('recipe_list')
else:
form = UserSubmittedRecipeForm()
recipe = Recipe()
ingredient_formset = IngredientFormSet(instance=recipe)
return render(request, template_name, {
"form": form,
"ingredient_formset": ingredient_formset
}, context_instance=RequestContext(request))