Get user in the form - python

I have a model
class someModel(models.Model):
.....
.....
user = models.OneToOneField(User, on_delete=models.CASCADE)
#User is the field that I need from the form
.....
.....
Here I have fields that have to be filled and the user field that is connected to the users table
In my forms
class someForm(forms.ModelForm):
class Meta:
model = someModel
fields = [....., 'user']
widgets = { .... }
I want to pass the user from my view but I don't know how to do that and I cant find it online. Form fails because the user is not passed.
#login_required
def someView(request):
organisator= request.user
if request.method == "POST":
cl_form = SomeModel(data=request.POST, initial={'user': organisator})
if cl_form.is_valid():
cl_form.save(commit=True)
else:
print(cl_form.errors)
return HttpResponseRedirect(reverse('someviewfromurls'))
else:
cl_form = someForm(initial={'user':organisator})
return render(request, 'somefile.html', context=
{"cl_form": cl_form})

You can try like this:
if cl_form.is_valid():
instance = cl_form.save(commit=False)
instance.user = request.user
instance.save()

Related

associate the user with the post Django and MySQL

I am trying to associate the user with the post. I have two models students is for user and sublists is for user posts with a foreign key(author). I am using MySQL database and using forms to store data into them. when my form.author execute in my HTML file it gives me a list of ids for all users in the databse but I am already logged in and i want to post as the logged in user without choosing. If remove it says my form is not valid which make sense since im not inputing for form.author.Since I'm using MySQL, I'm not using the built-in User authentication method, but instead comparing both email and password with the login form input. Spend too much time on this but hard to get around with this one. Any help would be appreciated
my views.py look like this
def addnew(request):
if request.method == 'POST':
form = Sublist(request.POST)
if form.is_valid():
try:
form.save()
messages.success(request, ' Subscirption Saved')
name = sublist.objects.get(name=name)
return render (request, 'subscrap/main.html', {'sublist': name})
except:
pass
else:
messages.success(request, 'Error')
pass
else:
form = Sublist()
return render(request, 'subscrap/addnew.html', {'form': form})
#login_required(login_url='login')
#cache_control(no_cache=True, must_revalidate=True, no_store=True)
def main(request):
return render(request, 'subscrap/main.html')
def mod(request):
student = students.objects.all()
return render(request, 'subscrap/mod.html' , {'students': student})
My Models.py
class students(models.Model):
fname = models.CharField(max_length=50)
lname = models.CharField(max_length=50)
password = models.CharField(max_length = 50 , null = True)
passwordrepeat = models.CharField(max_length = 50, null = True)
email = models.EmailField(max_length=150)
class Meta:
db_table = "students"
class sublist(models.Model):
author = models.ForeignKey(students, related_name='sublist' ,on_delete=models.CASCADE)
name = models.CharField(max_length=150)
cost = models.IntegerField(default = 0)
renewalcycle = models.IntegerField(default = 0)
class Meta:
db_table = "sublist"
Since I'm using forms here's my forms.py
lass StudentForm(forms.ModelForm):
class Meta:
model = students
fields = "__all__"
class Studentlogin(forms.Form):
email = forms.EmailField(max_length=150)
password = forms.CharField(max_length = 50, widget=forms.PasswordInput)
class Sublist(forms.ModelForm):
class Meta:
model = sublist
fields = "__all__"
Exclude the Author from the Sublist form:
class Sublist(forms.ModelForm):
class Meta:
model = sublist
exclude = ['author']
In the addnew method, you associate the .instance.author with the request.user:
#login_required(login_url='login')
def addnew(request):
if request.method == 'POST':
form = Sublist(request.POST)
if form.is_valid():
form.instance.author = request.user
form.save()
messages.success(request, ' Subscirption Saved')
return redirect('some_view')
else:
messages.error(request, 'Error')
else:
form = Sublist()
return render(request, 'subscrap/addnew.html', {'form': form})
Note: Models in Django are written in PascalCase, not snake_case,
so you might want to rename the model from sublist to Sublist.
Note: Usually a Form or a ModelForm ends with a …Form suffix,
to avoid collisions with the name of the model, and to make it clear that we are
working with a form. Therefore it might be better to use SublistForm instead of
Sublist.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the students directly. For more information you can see the referencing the User model section of the documentation.

Django ModelForm: Defining a value not passed into the template

I have a ModelForm, and I want to only pass some of the fields into the template. I would like to save one particular field to define after the POST request has been sent. Here is the ModelForm:
class CreateListingForm(ModelForm):
class Meta:
model = models.ListingModel
fields = ['name', 'image', 'description', 'price', 'category']
widgets = {
'description': Textarea()
}
And here is the Model:
class ListingModel(models.Model):
name = models.CharField(max_length=30)
image = models.ImageField(upload_to='images')
description = models.CharField(max_length=1000)
price = models.PositiveIntegerField()
category = models.CharField(max_length=15)
objects = models.Manager()
owner = models.CharField(max_length=100)
In the next code block, I am attempting to define the owner field according to the current user logged in (request.user.username):
#login_required(redirect_field_name=login_view)
def create_listing(request):
if request.method == "GET":
return render(request, "auctions/createlisting.html", {
"CreateListingForm": forms.CreateListingForm()
})
elif request.method == "POST":
form = forms.CreateListingForm(request.POST, request.FILES)
if form.is_valid():
try:
form.owner = request.user.username
print(form.owner)
form.save(commit=True)
except Exception:
return HttpResponseRedirect(reverse("create_listing_error"))
return HttpResponseRedirect(reverse("index")) #TODO
Now, when I say print(form.owner), the result is correct. However when I save the ModelForm, the owner field is left blank. Am I not defining the value of the owner field correctly?
You should not confuse the ModelForm with the instance it is wrapping. The fact that it prints something for form.owner is not that strange, you first set an attribute named .owner, an attribute that did not exists before. You should set the .owner of the .instance of the form:
#login_required(redirect_field_name=login_view)
def create_listing(request):
if request.method == 'POST':
form = forms.CreateListingForm(request.POST, request.FILES)
if form.is_valid():
form.instance.owner = request.user.username
form.save()
return redirect('name-of-some-view')
else:
form = forms.CreateListingForm()
return render(request, 'auctions/createlisting.html', {
'CreateListingForm': form
})
Where 'name-of-some-view' should be replaced by the name of some view to which you redirect in case the form was valid.
You should however consider changing the CharField of owner to a ForeignKey [Django-doc]. Imagine that later the user changes their username, then your ListingModels do no longer refer to a real user.

Unable to find newly saved instances in database

I'm making a stock portfolio app as a personal project. I have a form StockSymbolForm used for buying stocks. It has the fields: username, stock_symbol, and stock_qty.
I've set username to be the current user that's currently using the app - so they only need to fill stock_symbol and stock_qty.
After a valid form is submitted, I go to my admin page to check, but I don't see my new stock_symbol and stock_qty added to my model.
Here's my code:
views.py:
class PortfolioStockListView(ListView):
model = StockPortfolio
template_name = 'stocks.html'
def post(self, request):
current_user = StockPortfolioUser.objects.filter(username=request.user).first()
if request.method == 'POST':
symbol_form = StockSymbolForm(request.POST, initial={'username': current_user})
if symbol_form.is_valid():
symbol_form = StockSymbolForm(request.POST, instance=current_user)
model_instance = symbol_form.save(commit=True)
model_instance.timestamp = timezone.now()
model_instance.save()
return redirect('/')
else:
return render(request, 'stocks.html', {'symbol_form': symbol_form})
else:
symbol_form = StockSymbolForm()
return render(request, 'stocks.html', {'symbol_form': symbol_form})
models.py:
class StockPortfolioUser(models.Model):
username = models.OneToOneField(User, on_delete=models.CASCADE)
usercash = models.PositiveIntegerField(default=100000)
class StockPortfolio(models.Model):
username = models.ForeignKey(StockPortfolioUser, on_delete=models.CASCADE)
stock_symbol = models.CharField(max_length=5)
stock_qty = models.PositiveIntegerField(default=0)
forms.py:
class StockSymbolForm(ModelForm):
class Meta:
model = StockPortfolio
fields = ('stock_symbol' , 'stock_qty')
labels = {'stock_symbol': 'Stock Symbol', 'stock_qty': 'Quantity'}
How do I save the model instance properly? and why is it not saving at the moment?
In your views.py file change this
model_instance = symbol_form.save(commit=False)
model_instance.username = request.user.id
model_instance.timestamp = timezone.now()
model_instance.save()
In StockSymbolForm change this
fields = ('username', 'stock_symbol' , 'stock_qty')
Well, you don't ever seem to be setting the username. You set a timestamp, which doesn't exist as a field, but not the actual username field.
model_instance = symbol_form.save(commit=True)
model_instance.userame = request.user
model_instance.save()
As an aside, that field should be called user, as it points to the whole User object not just the username.

Django : ModelForm with OneToOneField

I have 2 models linked by a OneToOneField :
class User(models.Model):
name = models.CharField(max_length=100, unique=True)
email = models.EmailField(blank=True)
base = models.OneToOneField(BaseUser)
...
class BaseUser(models.Model):
enabled = models.BooleanFiled(default=True)
...
I use a ModelForm to display the user's attributes :
class UserForm(ModelForm):
class Meta:
model = User
fields = ['name', 'email', ...]
And in my views :
class UserCreate(generic.CreateView):
model = User
template_name = 'user/create.html'
success_url = reverse_lazy('users:list')
form_class = UserForm
I would like to change the enabled attribute in the user's template, but I have just access to the User's fields (name, email...).
How can I make it please ?
You can render 2 forms in your template:
def user_create(request):
if request.method == "POST":
user_form = UserForm(data=request.POST)
baseuser_form = BaseUserForm(data=request.POST)
if user_form.is_valid() and baseuser_form.is_valid():
base_user = baseuser_form.save()
user = user_form.save(commit=False)
user.base = base_user
user.save()
return redirect(reverse_lazy('users:list'))
else:
....
else:
user_form = UserForm()
baseuser_form = BaseUserForm()
return render_to_response('user/create.html', {'user_form': user_form, 'baseuser_form': baseuser_form})
If you only have one additional field you want to add, you could add it to the UserForm.
class UserForm(ModelForm):
enabled = forms.BooleanField(default=True)
class Meta:
model = User
fields = ['name', 'email', ...]
Then, in your form_valid method you can set the value for the base_user. Since it's a create view, I'm assuming you have to create it first.
class UserCreate(generic.CreateView):
def form_valid(self, form):
base_user = BaseUser.objects.create(
enabled=form.cleaned_data['enabled']
)
form.instance.base = base_user
return super(UserCreate, self).form_valid(form)
If you want to add more than one extra field, then you probably want separate forms for BaseUser and User. In this case, extending CreateView gets a bit tricky, and it might be simpler to use a function based view like in Rohit's answer.

Django, save ModelForm

I have created a model Student which extends from the Django User and is a foreign key to another model while it has an integer field called year. What i'm trying to do is to save a form, which has 2 fields. The one is the course id and the another one is the the integer field year. When I'm clicking submit, i'm getting an error Cannot assign "u'2'": "Student.course" must be a "Course" instance.
models.py
class Student(models.Model):
user = models.OneToOneField(User)
course = models.ForeignKey(Course)
year = models.IntegerField(validators=[MinValueValidator(1),
MaxValueValidator(7)])
view.py
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
forms.py
class SelectCourseYear(forms.ModelForm):
course = forms.CharField()
year = forms.IntegerField(required=True)
class Meta:
model = Student
fields = ['user', 'course', 'year']
You dont need to redefine fields in the ModelForm if you've already mentioned them in the fields attribute. So your form should look like this -
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
fields = ['course', 'year'] # removing user. we'll handle that in view
And we can handle the form with ease in the view -
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
student = form.save(commit=False)
# commit=False tells Django that "Don't send this to database yet.
# I have more things I want to do with it."
student.user = request.user # Set the user object here
student.save() # Now you can send it to DB
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
course has to be an instance of a Course model, not just the primary key of the instance. You can still accept an id in the form as a text input, but you're going to need to retrieve the actual course instance and assign the value.
You'll need to verify that the course id is valid, so putting that code into the clean method isn't a bad idea. Notice also how the course field is excluded here? Otherwise the form will expect it to be present. You also don't need to re-define the year field, as the ModelForm will inherit that field from the Student model.
# forms.py
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
exclude = ['user', 'course']
course_id = forms.IntegerField()
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(SelectCourseYear, self).__init__(*args, **kwargs)
def clean_course_id(self):
course_id = self.cleaned_data.get('course_id')
try:
self.course = Course.objects.get(pk=course_id)
except Course.DoesNotExist:
raise forms.ValidationError('Sorry, that course id is not valid.')
return course_id
def save(self, commit=True):
instance = super(SelectCourseYear, self).save(commit=False)
instance.course = self.course
instance.user = self.user
if commit:
instance.save()
return instance
# views.py
def step3(request):
if request.method == 'POST':
form = SelectCourseYear(request.POST or None, user=request.user)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html",
RequestContext(request))
return render(request, 'registration/step3.html',)
Now, when you call .save() on the model, the course field will be assigned an instance of Course

Categories