Using a primary key within a form view (Django) - python

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

Related

ModelForm has no model class specified Error at Django

I tried to build a simple registration from using django, but somehow it does not work
here's my model :
class User(models.Model):
name = models.CharField(max_length=200,unique=True)
email = models.CharField(max_length=200,unique=True)
verified = models.BooleanField(default=False)
voted = models.BooleanField(default=False)
def __str__(self): return self.name
Here is my Form :
class User_data(forms.ModelForm):
class Meta():
form = User
fields = ("name", "email")
Here's my View.py :
def register(response):
form = User_data
if response.method == 'post':
form = User_data(response.POST)
if form.is_valid():
form.save(commit=True)
return index(response)
return render(response,'voting/voting.html', {
'form': form,
})
what did I miss? Thank you
You specify the model fo a ModelForm [Django-doc] with the model attribute in the Meta class, so:
class User_data(forms.ModelForm):
class Meta:
model = User # &leftarrow; model, not form
fields = ('name', 'email')
Furthermore a successful POST request normally should result in a redirect to implement the Post/Redirect/Get architectural pattern [wiki]:
from django.shortcuts import redirect
def register(request):
form = User_data
if request.method == 'POST': # &leftarrow; POST, not post
form = User_data(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect(index)
return render(request,'voting/voting.html', {
'form': form,
})

How to associate a username from the User model to another model in Django?

I currently have an index view with several input tags for a name, file and tags.
I'm trying to connect the model that handles that view (name: Uploaded) to the User model and associate the logged in users username to the Uploaded model.
Here's my view:
def index(request):
if request.method == 'POST':
form = FileUploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
else:
form = FileUploadForm
allTags = Tag.objects.all()
context = {'form': form, 'allTags': allTags}
return render(request, 'index.html', context)
and here's the Uploaded model:
class Uploaded(models.Model):
objects: models.Manager()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="users")
name = models.CharField(max_length=50)
file = models.FileField(upload_to=MEDIA_ROOT)
tags = TaggableManager()
def __str__(self):
return f"{self.name} {self.file}"
You can "patch" the .instance wrapped in the form with the logged in user:
from django.contrib.auth.decorators import login_required
#login_required
def index(request):
if request.method == 'POST':
form = FileUploadForm(request.POST, request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
else:
form = FileUploadForm()
allTags = Tag.objects.all()
context = {'form': form, 'allTags': allTags}
return render(request, 'index.html', context)
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

NOT NULL constraint failed: blog_userpost.user_id

Im trying to create a way for people to post their ideas but is giving me this error:
NOT NULL constraint failed: blog_userpost.user_id. I want the user to have to be registered and login in order to make/read the posts.
views.py:
#create view
#login_required(login_url='login')
def userposts_create_view(request):
form= UserPostForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
form = form.save()
form.save()
return HttpResponseRedirect("/Blog/posts/")
context= {'form': form,
}
return render(request, 'posts/userposts-create-view.html', context)
#list view
#login_required(login_url='login')
def userposts_list_view(request):
allposts= UserPost.objects.all()
context= {'allposts': allposts,
}
return render(request, 'posts/userposts-list-view.html', context)
#detail view
#login_required(login_url='login')
def userposts_detail_view(request, url=None):
post= get_object_or_404(UserPost, url=url)
context= {'post': post,
}
return render(request, 'posts/userposts-detail-view.html', context)
models.py
This are the categories I want the post to have, I can 'create' the post but whenever I submit it gives me the error.
User= settings.AUTH_USER_MODEL
class UserPost(models.Model):
user= models.ForeignKey(User, null=False,editable=False, verbose_name='Usuario', on_delete=models.CASCADE)
title= models.CharField(max_length=500)
content= models.TextField()
categories = models.ManyToManyField(Category, verbose_name='Categorias', blank=True,related_name="articles")
created_at = models.DateTimeField(auto_now_add=True, verbose_name='Creado el ')
updated_at = models.DateTimeField(auto_now=True, verbose_name='Actualizado el ')
def save(self, *args, **kwargs):
super(UserPost, self).save(*args, **kwargs)
forms.py
from django import forms
from .models import UserPost
class UserPostForm(forms.ModelForm):
class Meta:
model= UserPost
fields= ["title", "content","categories"]
One simple way is to use model's manager instead of form.save(). So in your condition (i.e. if form.is_valid()) you can use something like:
def userposts_create_view(request):
form= UserPostForm(request.POST or None)
if form.is_valid():
data = form.cleaned_data
categories = data.pop('categories', None)
user_post = UserPost.objects.create(**data, user=request.user)
if categories:
user_post.categories.add(*categories)
return HttpResponseRedirect("/Blog/posts/")
context= {'form': form}
return render(request, 'posts/userposts-create-view.html', context)

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

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

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