Django editing user's posts - django

I am working in a blog application using django. A user can add posts and edit their own posts. However, I am having trouble with retrieving user's posts. Here is a similar question, but it does not work with my application: Django edit form based on add form? Any help is truly appreciate
Here is my code:
#login_required
def edit(request, id):
if id:
post = get_object_or_404(BlogPost, id=id)
if post.author != request.user:
return render(request, "403.html")
else:
post = BlogPost(author=request.user)
if request.method == "POST":
form = AddPost(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.save()
messages.add_message(request, messages.SUCCESS,
'You have succesfully updated your post')
return redirect('homepage')
else:
form = AddPost(instance=post)
return render(request, 'blog/update.html', {'form': form})
Here is my model:
class BlogPost(models.Model):
title = models.CharField(
max_length=100, null=False, blank=False, unique=True)
content = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
date_updated = models.DateTimeField(auto_now=True)
author = models.CharField(max_length=50).......

Your author field is a CharField. I'm not sure what you're putting into that field, or how you're setting it, but it will never equal request.user, because that is an instance of your User model.
Normally the author field would be a ForeignKey to User, so that the comparison would be true for those posts authored by the current user. If you are putting the username into the author field, you could compare with that: if post.author != request.user.username - but I would really not recommend doing that, as you are breaking normalization for no good reason.
(Also note my other comment: your first else clause looks like it should be one indent to the left: ie under if id, not if post.author....)

Related

Create a 'post' object and initialize a m2m attribute with post id and author id

I am trying to accomplish the following in Django:
An app that allows users to create image posts. They can view any post that is in the system and add those posts to their bookmarks. When a user creates a post, the post is automatically added to their bookmarks.
Model
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
post_image = models.ImageField(max_length=255, upload_to='images/content/', blank=False, null=False)
author = models.ForeignKey(User, on_delete=models.PROTECT, related_name='authors')
tags = TaggableManager(through=UUIDTaggedItem, help_text=_('Maximum of 5 tags allowed'))
created = models.DateTimeField(auto_now_add=True)
bookmarks = models.ManyToManyField(User, related_name='bookmarked', blank=True)
bookmark_count = models.IntegerField(default=0)
def get_create_date(self):
return self.created.strftime("%B %Y")
ordering = ['-created']
View
#login_required
def post_add_view(request, *args, **kwargs):
context = {}
user = request.user
if request.method == 'POST':
form = PostAddForm(request.POST, request.FILES)
if form.is_valid():
new_post = form.save(commit=False)
new_post.author = user
new_post.save()
form.save_m2m()
context['form'] = form
messages.add_message(request, messages.SUCCESS, 'Image uploaded successfuly!')
return redirect('library:posts')
context['form'] = form
return render(request, 'library/post_add.html', context)
else:
form = PostAddForm()
context['form'] = form
return render(request, 'library/post_add.html', context)
When a user creates a new post, that post will be associated with an additional attribute in the Post object called 'bookmarks'. The 'bookmarks' attribute has a many-to-many relationship with author and post.
I can easily create the post object, associate it with the author and save it to the db. That part is working fine. The part that I am struggling with is how to handle the 'bookmarks' field. The author id is easy, since I already have that from the session with user = request.user.
Somehow I need to obtain the newly created post id so that I can attach it to the 'bookmarks' field. This where I am stuck. I am new to Django and coding in general.
I have seen some possible ways to handle this, but I am not sure if they are correct or advisable.
Django Signals
I saw a few posts online about using signals.
Django Transactions
This SO post discusses using transactions
Do I need to use one of the above methods or is there another way of accomplishing what I want? Thanks!
If I understand you correctly, all you need to do is add the user to the bookmarks field of the new_post. However, I think the new_post needs an id for this to be possible, although someone may correct me on that. By which I mean, the user needs to be added to the bookmarks after new_post has been saved (that's when new_post is assigned an id).
So something like:
....
if form.is_valid():
new_post = form.save(commit=False)
new_post.author = user
new_post.save()
new_post.bookmarks.add(user)
form.save_m2m()
...

How do I resolve IntegrityError: NOT NULL constraint failed?

I try to let user add comments to blog post am making...
When I run makemigrations and migrate, everything seemed fine . The form displayed well but shows the following error when I fill the form and click on the submit button.
Django.db.utils.IntegrityError: NOT NULL constraint failed: blog_comment.author_id
Am new to Django and following a tutorial. The tutorial doesn't have users except the super user. I learnt about users and so I let user register to use the blog. The tutorial provided a name field in the form so commenter can enter their name. Here, I want to use the current user for this field(see my models.py below to see how I have done this).
Any help to solve this will be appreciated.
models.py
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)
comment = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
class Meta:
ordering = ('created',)
def __str__(self):
return f'Comment by {self.author} on {self.post}'
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('comment',)
views.py
login_required
def post_detail(request, post, pk):
post = get_object_or_404(Post, id=pk, slug=post, status='published')
comments = post.comments.filter(active=True)
new_comment = None
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.save()
else:
comment_form = CommentForm()
return render(request,
'post_detail.html',
{'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form})
PS: I have seen similar questions like this and deleted my migrations file and re-ran migrations but it didn't still work.
In the if comment.is_valid(): block,
Before;
new_comment.save()
Add,
new_comment.author = request.user

Pure Django Form Tying User To Submitted Form And View

I am unsure how to tie a logged in user to a submitted form using regular Django forms. I see alot of examples using ModelForms but none (that I can tell) without using the ModelForms. In my forms.py im having a hard time figuring out how to add the author field. I cannot just add author = forms.ForeignKey or something like that. Then somehow in my view i need to call the author field to be saved into the database (my below example is my best guess and probably not right with the "tenant_form.author = request.user").
I have a model that looks like this and has a user Foreignkey setup:
class AppyModel(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
date_time_form_filled = models.DateTimeField(auto_now_add=True)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
I have a forms.py:
class TenantForm(forms.Form):
first_name = forms.CharField(required=False, label='First Name')
last_name = forms.CharField(required=False, label='Last Name')
I have a views.py
#login_required
def tenant_create_form_view(request):
tenant_form = TenantForm()
if request.method == 'POST':
tenant_form.author = request.user
tenant_form = TenantForm(request.POST)
if tenant_form.is_valid():
print(tenant_form.cleaned_data)
AppyModel.objects.create(**tenant_form.cleaned_data)
else:
print(tenant_form.errors)
context = {
'form': tenant_form
}
return render(request, 'fill_appy.html', context)
You should add author when the form is valid,
tenant_form = TenantForm()
if request.method == 'POST':
tenant_form = TenantForm(request.POST)
if tenant_form.is_valid():
obj = tenant_form.save(commit=False)
obj.author = request.user #add author here
obj.save()
# .. rest of code

Show modelform with the data the user filled in

Im trying to make a simple voting app.
The user should be presented with a blank form at first, but when the user has filled in the form, the user should be presented with the same form, but with the data they filled in.
How can I present the data they put in, on the same form?
My model:
class Vote(models.Model):
user = models.ForeignKey(User)
vote_1 = models.ForeignKey(Song, null=True, blank=True, related_name="voted_1")
vote_2 = models.ForeignKey(Song, null=True, blank=True, related_name="voted_2")
vote_3 = models.ForeignKey(Song, null=True, blank=True, related_name="voted_3")
creation_date = models.DateTimeField(auto_now_add=True)
edited = models.DateTimeField(auto_now=True)
My view:
def show_voteform(request):
if request.method == 'POST':
form = VoteForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, "Vote saved", extra_tags='alert-success')
#Return the user to same page
return HttpResponseRedirect('/vote/')
else:
form = VoteForm(initial={'user':request.user, 'vote_1':???, 'vote_2':???, 'vote_3':???,})
return render(request, 'vote/form.html', {
'form': form,
})
Is this something I could provide in initial, or do I have to do this another way?
Edit:
Changed it to this:
else:
try:
vote = Vote.objects.filter(user=request.user).latest('creation_date')
form = VoteForm(instance=vote)
except Vote.DoesNotExist:
form = VoteForm(initial={'user':request.user})
If your VoteForm is a ModelForm, then you can show the form with data from a model instance filled in using:
# get the most recent Vote by this user
vote = Vote.objects.filter(user=request.user).latest('creation_date')
# fill in the form with data from the instance
form = VoteForm(instance=vote)

django - help on a view to create an article

I'm going through a django tutorial to create a wiki and I'm a little stumped on what's happening in the view below. Specifically, this part:
if form.is_valid():
article = form.save(commit=False)
article.author = request.user
article.save()
msg = "Article saved successfully"
messages.success(request, msg, fail_silently=True)
return redirect(article)
Here are my questions:
what is being instantiating when you write article = form.save(commit=False) and what does the argument, (commit=False) mean?
Where does request.user come from and what does it do?
I could also use an explanation for article.save()
where does messages.success come from?
Sorry for all the questions, but the tutorial is a little sparse on details :(.
Here's the model:
class Article(models.Model):
"""Represents a wiki article"""
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=50, unique=True)
text = models.TextField(help_text="Formatted using ReST")
author = models.ForeignKey(User)
is_published = models.BooleanField(default=False, verbose_name="Publish?")
created_on = models.DateTimeField(auto_now_add=True)
objects = models.Manager()
published = PublishedArticlesManager()
def __unicode__(self):
return self.title
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Article, self).save(*args, **kwargs)
#models.permalink
def get_absolute_url(self):
return ('wiki_article_detail', (), { 'slug': self.slug })
Here's the full view:
#login_required
def add_article(request):
form = ArticleForm(request.POST or None)
if form.is_valid():
article = form.save(commit=False)
article.author = request.user
article.save()
msg = "Article saved successfully"
messages.success(request, msg, fail_silently=True)
return redirect(article)
return render_to_response('wiki/article_form.html',
{ 'form': form },
context_instance=RequestContext(request))
what is being instantiating when you write article =
form.save(commit=False) and what does the argument, (commit=False)
mean?
Saving a modelform inserts/updates the data in the database and returns the model istance (in this case an article instance). A modelform maps a form to a model. However, sometimes you may want to add some extra stuff that does not come directly from the form. So, to prevent two updates, you do not commit to the database by specifying commit=False, the changes will be made to the database when you do a .save() on instance, instead.
Where does request.user come from and what does it do? request.user refers to the currently logged in user (who is making this request).
I could also use an explanation for article.save() - inserts/updates the article fields to the database.
where does messages.success come from? messages framework is just for passing error/success/informative messages using cookies and sessions.