Get the currently logged in Django user in a models.py file? - python

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')

Related

Django form.is_valid() issue

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.

Using a primary key within a form view (Django)

I have a form that is associated with a model, and want to specify the form data using the model's PK to log the response.
However, when I do this, I get the error: QuestionRecordSubmitView() got an unexpected keyword argument 'pk'
urls.py
path('survey/<int:pk>/record_submit_question/', views.QuestionRecordSubmitView, name='survey-question-submit-record')
views.py
def QuestionRecordSubmitView(request):
model = Question
if request.method == 'POST':
form = PostAudio(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('survey-share', kwargs={"pk": form.question}))
else:
form = PostAudio()
return render(request, 'survey/question_audio_submit.html')
models.py
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
response_file = models.FileField(blank=True, upload_to='audio_responses')
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
forms.py
class PostAudio(forms.ModelForm):
class Meta:
model = Choice
fields = ('response_file',)
The view should accept a pk parameter, the primary key that is captured from the path. Furthermore, you should specify the question_id of the instance:
from django.shortcuts import redirect
def QuestionRecordSubmitView(request, pk):
if request.method == 'POST':
form = PostAudio(request.POST, request.FILES)
if form.is_valid():
form.instance.question_id = pk
form.save()
return redirect('survey-share', pk=pk)
else:
form = PostAudio()
return render(request, 'survey/question_audio_submit.html')

django wont store authUser referenced as foreign key in my model

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.

django unable to saved forms in database

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.

How to add info to request.POST?

When a user creates something using a form, all of the info is submitted through a form which is sent through an AJAX call to the following view:
def goal_create(request):
if request.method == 'POST':
user = request.user
request.POST[user] = user.id
errors = form_validate(request, AddGoalForm, Goal)
I get an error when I try to modify request.POST dict and add a user's id to the model instance. I want to add it, so in the next step (when it goes to form_validate), it will create a new model instance for me.
Here is form_validate, which validates the form according to a ModelForm.
def form_validate(request, form, model):
form = form(request.POST)
if form.is_valid():
new = form.save()
else:
return form.errors.items()
Here is the model I'm working with:
class Goal(models.Model):
goal_name = models.CharField(max_length=200, blank=False)
user = models.ForeignKey(User, null=True, blank=True)
created_at = models.DateField(auto_now_add=True)
updated_at = models.DateField(auto_now=True)
Another issue is that even though goal_name has attribute blank=False, and I create a new goal with a blank goal_name, it says that the form is_valid() and saves the form.
if request.method == 'POST':
user = request.user
post_values = request.POST.copy()
post_values['user'] = user.id
form = MyForm(post_values)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('success'))
return HttpResponseRedirect(reverse('error'))
p.s This is a quick fix but not a very elegant method to use. Though there are no issues when you would use this
forms.py
class GoalForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(GoalForm, self).__init__(*args, **kwargs)
def save(self, commit=True):
obj = super(GoalForm, self).save(commit=False)
obj.user = self.user
if commit:
obj.save()
return obj
views.py
#login_required
def add_goal(request):
form = GoalForm(user=request.user, data=request.POST)
if form.is_valid():
obj = form.save()
return HttpResponse('ok')
return HttpResponse('errors')

Categories