The idea is a user will create a post on this page and fill out the title and content.
Once they submit this form, a Post instance will be created with the inputs of the user for title and content. This instance will also have the id of the user associated to it.
I've done a print test which yields the outputs I'm looking for but it appears that the form is not valid. Any thoughts?
#Resolved - Thank you all
def post(self, request, locationname):
form = PostCreate(request.POST)
current_user = request.user
found_location = Location.objects.get(name = locationname)
if form.is_valid():
form = form.save(commit=False)
form.post_location = Location.objects.get(id = found_location.id)
form.author = Profile.objects.get(user_id = current_user)
form.save()
return HttpResponseRedirect(self.request.path_info)
#views.py
class LocationDetail(View):
def post(self, request, locationname):
current_user = request.user
user_profile = Profile.objects.get(user_id = current_user)
form = PostCreate()
found_location = Location.objects.get(name = locationname)
context = {"found_location": found_location, "form": form}
if request.method == "POST":
post_author = user_profile.user_id
post_title = request.POST['title']
post_content = request.POST['content']
print(post_author)
print(post_title)
print(post_content)
if form.is_valid():
Post.objects.create(
title = post_title,
content = post_content,
author_id = post_author,
)
form.save()
return render(request,'location-detail.html', context)
#forms.py + models.py
class PostCreate(ModelForm):
class Meta:
model = Post
fields = ['title', 'content']
class Profile(Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length = 30)
profile_location = models.CharField(max_length = 80, blank=True, null=True)
join_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Post(Model):
author = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name="posts")
title = models.CharField(max_length = 30)
content = models.CharField(max_length=300)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'{self.author} - {self.title}'
#template: location-detail.html
<form action="" method="POST">
{%csrf_token%}
{{form}}
<button type="submit">Submit</button>
</form>
You do not need to check if the request is a "POST" request since you are using class-based views. The post() method will be called by the dispatcher method inside of the base "View" class when you submit the form. Before checking if the form is valid, fill the instance of the form with the request data, then you can set the "author" field like so:
def post(self, request, locationname):
form = PostCreate(request.POST)
if form.is_valid():
# don't commit to database yet
form = form.save(commit=False)
# set author field
form.author = user_profile.user_id
# commit to database
form.save()
return redirect("<url_name>")
When .save(commit=False) is called, the form instance with the data is saved without committing to the database. Then, when the .save() method is called the second time, the data will be saved to the database. It is recommended to redirect to the desired url after a POST request. The <url_name> comes from the url in your 'urls.py' file that you want to redirect to.
More info can be found in the django docs here:
https://docs.djangoproject.com/en/3.2/topics/forms/
Try to revise this line:
user_profile = Profile.objects.get(user_id = current_user)
to
user_profile = Profile.objects.get(user_id = current_user.id)
Since the argument user_id needs an id value, not an object.
Related
I am trying to assign username to author field in Post model , Django spews out the following error:
"Post.author" must be a "User" instance.
model:
class Post(models.Model):
title = models.CharField(max_length=200)
image = models.ImageField(upload_to='',null=True,blank=True)
image_url = models.CharField(max_length=200,default=None,null=True,blank=True)
date = models.DateTimeField(default=timezone.now)
content = models.TextField()
author = models.ForeignKey(User, null=False, blank=False,on_delete=models.CASCADE)
categories = models.ManyToManyField(Category)
published = models.BooleanField()
def __str__(self):
return self.title
view:
#login_required
def new_post(request):
# Add a new post
if request.method != 'POST':
# No data submitted, create a blank form
form = PostForm()
else:
# Post data submitted, process data
form = PostForm(data=request.POST)
if form.is_valid():
new_post = form.save(commit=False)
new_post.author = request.user.username
new_post.save()
return redirect('elogs:posts')
#Display a blank or invalid form
context = {'form':form}
return render(request,'elogs/new_post.html',context)
form:
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title','content','image','image_url','published']
widgets = {
'title': forms.Textarea(attrs={'placeholder': 'Title..'}),
'content': forms.Textarea(attrs={'placeholder': 'What is on your mind?'}),
'categories': forms.TextInput()
}
I have solved this error just like this:
from django.contrib.auth import get_user_model
author = models.OneToOneField(get_user_model(),on_delete=models.CASCADE)
You're giving the username instead of the user itself:
new_post.author = request.user.username
A ForeignKey takes an instance of the given Model, User in this case.
I created my model that have authUser referenced as foreign key, then using django Form API i am trying to store data into my DB but my user field remains null.
I have used build-in FORM API to receive an uploaded file and before storing my file, i also store filename. I tried to do the same for userField but django throw ValueError.
Models.py
class sample(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True ,default=1)
submit_time = models.DateTimeField(auto_now=True)
file_name = models.CharField(max_length=1024)
score = models.FloatField(default=0.0)
is_pending = models.BooleanField(default=True)
is_complete = models.BooleanField(default=False)
json_URL = models.FilePathField()
sample = models.FileField(upload_to='samples/')
Views.py
#login_required
def upload(request):
if request.method == 'POST':
file = request.FILES['sample']
form = SampleForm(request.POST, request.FILES)
if form.is_valid():
new_sample = form.save(commit=False)
new_sample.file_name = file.name
new_sample.user = User.id #throws ValueError Cannot assign "sample.user" must be a "User" instance.
form.save()
return redirect('reports')
else:
print("form is invalid")
else:
form = SampleForm()
if request.method == 'GET':
return render(request, 'upload2.html', {'form': form})
forms.py
class SampleForm(forms.ModelForm):
class Meta:
model =sample
fields=('sample',)
my goal is to save the user id in my db so i know who uploaded the file.
You should use request.user to the new_sample.user object, or request.user.id (or request.user.pk) to the request.user_id attribute, like:
# …
new_sample = form.save(commit=False)
new_sample.file_name = file.name
new_sample.user = request.user
form.save()
return redirect('reports')
# …
By using User.id, you get a reference to the field of the User model, not an object.
I have a post and a category app in my django project. I have user authentication and users can create categories as well as posts. I am at a point where I am out of ideas and help would be appreciated. I want users to be able to reference only their own category and create posts in their categories not in another persons own. That is if a user creates more that one category he should be able to select from the list of his created category and not see another persons own.
category model
class Category(models.Model):
name = models.CharField(max_length = 120)
slug = models.SlugField(unique= True)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
post model
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1,related_name='posts_created') #blank=True, null=True)
title = models.CharField(max_length = 120)
slug = models.SlugField(unique= True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='category_created', null= True)
addition codes would be provided immediately on request. Thanks
View.py in post app
def create(request):
if not request.user.is_authenticated():
messages.error(request, "Kindly confirm Your mail")
#or raise Http404
form = PostForm(request.POST or None, request.FILES or None)
user = request.user
categories = Category.objects.filter(category_created__user=user).distinct()
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
create_action(request.user, 'Posts', instance)
messages.success(request, "Post created")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
"categories": categories,
}
template = 'create.html'
return render(request,template,context)
Form
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
"title",
"content",
"category",
]
html
{% if form %}
<form method="POST" action="" enctype="multipart/form-data">{% csrf_token %}
{{ form|crispy|safe }}
<input type="submit" name="submit" value="Publish">
</form>
{% endif %}
You probably want to list all the Categories to which a user has contributed on some view.
You can get all the Categories to which a user contributed in the following way:
user = request.user # assuming you're in a view
categories = Category.objects.filter(post__user=user).distinct()
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='category_created', null= True)
related_name='category_created' means that to access your post from a category you need to use 'category_created':
categories = Category.objects.filter(category_created__user=user).distinct()
or you can rename it to related_name='post' and then migrate.
Edit
View.py in post app
def create(request):
if not request.user.is_authenticated():
messages.error(request, "Kindly confirm Your mail")
#or raise Http404
form = PostForm(request, request.POST or None, request.FILES or None, )
user = request.user
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
create_action(request.user, 'Posts', instance)
messages.success(request, "Post created")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
"categories": categories,
}
template = 'create.html'
return render(request,template,context)
forms.py
class PostForm(forms.ModelForm):
def __init__(self, request, *args, **kwargs):
super (PostForm,self ).__init__(*args,**kwargs) # populates the post
self.fields['category'].queryset = Category.objects.filter(
category_created__user=request.user
).distinct()
I'm learning django and I'm trying to save the form using POST method and found its working fine, I'M not able to see the saved message in database(form is not submitted)
Models.py
class Post(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(max_length=10000)
pub_date = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=200, unique=True)
def __unicode__(self):
return self.title
def description_as_list(self):
return self.description.split('\n')
class Comment(models.Model):
title = models.ForeignKey(Post)
comments = models.CharField(max_length=200)
def __unicode__(self):
return '%s' % (self.title)
Forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'description')
editPostedForm = modelformset_factory(Post, PostForm)
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('comments',)
exclude = ('title',)
Views.py
def detail(request, id):
posts = Post.objects.get(id=id)
comments = posts.comment_set.all()
forms = CommentForm
if request.method == 'POST':
form = CommentForm(request.POST, instance=posts)
print form
if form.is_valid():
form.save(commit=False)
form.save()
else:
print form.errors
else:
form = PostForm()
return render(request, "detail_post.html", {'forms':forms,'posts': posts,'comments':comments})
Why is the post message is not being saved. I got status code 200 in console, also i get the entered data, but the form is not being saved...Any help is much appreciated
I think the problem is that your form excludes title field, but it's required according to Comment definition. You need to give the title to comment instance then save it:
def detail(request, id):
posts = Post.objects.get(id=id)
comments = posts.comment_set.all()
forms = CommentForm
if request.method == 'POST':
form = CommentForm(request.POST,instance=posts)
print form
if form.is_valid():
# create a comment instance in memory first
comment = form.save(commit=False)
# fill out the title field
comment.title = posts
comment.save()
else:
print form.errors
else:
form = PostForm()
return render(request, "detail_post.html", {'forms':forms,'posts': posts,'comments':comments})
Also, I don't know why you use plural form for one instance, like posts should be post because you use objects.get(), make your code more readable would save some confusion for other people.
I'm trying to make a model that's stores basic information about an Article also store the name of the currently logged in user, is this possible? or is it something that needs to be done in the views.py file.
Here's my code:
from django.db import models
from time import time
from django.contrib.auth.models import User
def get_upload_file_name(instance, filename):
return "uploaded_files/%s_%s" % (str(time()).replace('.','_'), filename)
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(User.get_username()) #AUTOMATICALLY STORE USERNAME
body = models.TextField()
pub_date = models.DateTimeField(auto_now=True)
likes = models.IntegerField(default=0)
thumbnail = models.FileField(upload_to=get_upload_file_name)
def __unicode__(self):
return self.title
Here's the function that handles the Article model located in views.py:
def create(request):
if request.POST:
form = ArticleForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect('/articles/all')
else:
form = ArticleForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_article.html', args)
How can I make it so that when a new article is created, the username should be stored as the "author" the same way the "pub_date" automatically stores the current date?
You'll need to take care of this in the view:
# views.py
def create(request):
if request.POST:
form = ArticleForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.author = request.user
instance.save()
return HttpResponseRedirect('/articles/all')
else:
form = ArticleForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_article.html', args)
# models.py
class Article(models.Model):
author = models.ForeignKey('auth.User')
You'll need to do it in the view, as the model has no idea where it is being created from. Pass commit=False to the form.save() method so it doesn't commit the data to the database, set the author from the request, and then save manually:
if form.is_valid():
article = form.save(commit=False)
article.author = request.user
article.save()
return HttpResponseRedirect('/articles/all')