I'm in the process of making a Recipe Book. For some reason, whenever I try to pull up a recipe from the DB to edit it, I keep getting an error where it can't find the recipe I've specified. I'm using slugs, and my logic is that I'm going from a detailView where I've already pulled up the db information, to an updateView. I'm attempting to pass the recipe object I already pulled from the detailView to the updateView, but when I do, it keeps telling me that it can't find the recipe specified.
views.py:
The base views I'm calling here are only providing a default post method for handling a search so that I don't have to put it in for every view I create so I have some code reusability
class RecipeDetailView(BaseDetailView):
model = Recipe
template_name = 'RecipeBook/recipe_detail.html'
context_object_name = 'recipe_view'
queryset = None
slug_field = 'slug'
slug_url_kwarg = 'slug'
def get_context_data(self, *args, **kwargs):
context = super(RecipeDetailView, self).get_context_data()
recipe = self.object
recipe.ingredients = recipe.ingredients_list.split('\n')
context['recipe'] = recipe
return context
class RecipeEditView(BaseUpdateView):
model = Recipe
template_name = 'RecipeBook/edit_recipe.html'
context_object_name = 'recipe_edit'
queryset = None
slug_field = 'slug'
slug_url_kwarg = 'slug'
form_class = RecipeForm
def get_context_data(self, *args, **kwargs):
context = super(RecipeEditView, self).get_context_data()
recipe = self.object
print(recipe.name)
recipe.ingredients = recipe.ingredients_list.split('\n')
recipe.categories_list = ""
categories = Category.objects.filter(recipe=recipe)
for category in categories:
if category != categories[-1]:
recipe.categories_list += (category + ", ")
else:
recipe.categories_list += category
recipe_edit_form = RecipeForm(initial={'name': recipe.name, 'ingredients_list': recipe.ingredients,
'directions': recipe.directions, 'prep_time': recipe.prep_time,
'cook_time': recipe.cook_time, 'servings': recipe.servings,
'source': recipe.source, 'category_input': recipe.categories_list})
context['recipe'] = recipe
context['recipe_edit_form'] = recipe_edit_form
return context
models.py:
class Recipe(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100, default="")
ingredients_list = models.TextField(default="")
servings = models.IntegerField(default=0, null=True, blank=True)
prep_time = models.IntegerField(default=0, null=True, blank=True)
cook_time = models.IntegerField(default=0, null=True, blank=True)
directions = models.TextField(default="")
source = models.CharField(max_length=100, default="", null=True, blank=True)
categories = models.ManyToManyField(Category, blank=True)
slug = models.CharField(max_length=200, default="")
def __str__(self):
return self.name
urls.py
# ex: /Recipes/Grilled_Chicken/
path('Recipes/<slug>/', views.RecipeDetailView.as_view(), name='view_recipe'),
path('Recipes/<path:slug>/', views.RecipeDetailView.as_view(), name='view_recipe'),
# ex: /Recipes/edit/Steak/
path('Recipes/edit/<slug>/', views.RecipeEditView.as_view(), name='edit_recipe'),
path('Recipes/edit/<path:slug>/', views.RecipeEditView.as_view(), name='edit_recipe'),
link in recipe_detail.html:
Edit Recipe
I've been going nuts trying to figure it out. By everything that I have in here, the recipe that I'm pulling up in the detailView should be able to be passed to the editView, but every time I try to open up the edit_recipe page, it keeps telling me that it can't find the recipe specified. The URL that it generates shows the proper slug and link that it should though. I don't know what I'm missing at this point...
Try this way:
Edit Recipe
I ended up having to go back through and change the view to be a DetailView. That was the only way I could get the recipe instance to be pushed through. There's something very specific about using an update view with models that isn't very clear...
Once I changed to a DetailView, the page would populate with the form initialized to the recipe values. I could then make tweaks to make sure everything worked from there.
Thanks for those who responded, it at least got my brain working in a different direction to get this figured out.
Related
I'm getting a Cannot assign "<Product: Test Product>": "Reply.comment" must be a "Comment" instance. error at new_reply = Reply(content=content, author=self.request.user, comment=self.get_object()) and don't know what to do to fix it.
views.py:
class ProductFeedbackView(DetailView):
model = Product
template_name = 'store/product_feedback.html'
def get_context_data(self , **kwargs):
data = super().get_context_data(**kwargs)
connected_comments = Comment.objects.filter(product=self.get_object())
number_of_comments = connected_comments.count()
data['comments'] = connected_comments
data['no_of_comments'] = number_of_comments
data['comment_form'] = CommentForm()
connected_replies = Reply.objects.filter(comment=self.get_object())
number_of_replies = connected_replies.count()
data['replies'] = connected_replies
data['no_of_replies'] = number_of_replies
data['reply_form'] = ReplyForm()
return data
def post(self , request , *args , **kwargs):
if self.request.method == 'POST':
reply_form = ReplyForm(self.request.POST)
if reply_form.is_valid():
content = reply_form.cleaned_data['content']
new_reply = Reply(content=content, author=self.request.user, comment=self.get_object())
new_reply.save()
return redirect(self.request.path_info)
if self.request.method == 'POST':
comment_form = CommentForm(self.request.POST)
if comment_form.is_valid():
content = comment_form.cleaned_data['content']
new_comment = Comment(content=content, author=self.request.user, product=self.get_object())
new_comment.save()
return redirect(self.request.path_info)
models.py:
class Product(models.Model):
author = models.ForeignKey(User, default=None, on_delete=models.CASCADE)
title = models.CharField(max_length=120, unique=True)
description = models.CharField(max_length=300, blank=True, null=True)
class Comment(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, blank=True, null=True, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True,)
content = models.CharField(max_length=200, null=True, blank=False)
class Reply(models.Model):
comment = models.ForeignKey(Comment, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True,)
content = models.TextField(null=True, blank=False)
It's the same error as I pointed out in the other question you asked. Here is the line of code that is not working:
new_reply = Reply(content=content, author=self.request.user, comment=self.get_object())
The cause of this is also the same as your other question:
self.get_object() returns a Product instance as you defined model = Product on your View.
To fix this, you'll need to get the comment in your post method before creating the reply.
One solution for this could be posting the comment id with the reply data, for example as a hidden field. This id can then be used to get the comment instance where this reply belongs to. If you choose this solution, also make sure the comment actually belongs to this product as you don't want someone to just change the value of the comment id and be able to reply to any other comments.
Some additional feedback:
You don't need to check for the request method in the post method as it's already the post method.
You're now trying to save both a comment and reply whenever a post is done. You should either create different views for each post or add an if statement to check which form is posted. For example also using a hidden field with a value for that.
The comment model defines a product and an author relation. Both being null=True and blank=True. I think you always want a comment to belong to a product and an author. So you should remove those. Same for reply.
After a successful post, use a HttpResponseRedirect where you reverse the url of the product.
This is my first post to SO, so please let me know if I've missed any important details. I am working on updates to a home-grown dJango based ticketing system.
I have two "parent" models (ParentProjects and Projects) that capture details about work we want to track. Both models have a number of columns that store information in the associated tables as well as some FK relations.
The generic class-based detail view is used to view objects in the Project table while the ParentProject table is accessed by a function based view. The function-based view accomplishes the same task of loading parent project object values as the class-based detail view does for the project objects.
The problem I am having is that I cannot add a new entry to the IDTasks model that automatically inserts the Parent Project id. I am able to add a new IDTask from within the admin site (or from the "client" site if I enable the "parent" field within the modelform) by manually selecting the parent I wish to associate the IDTask to. I can also edit and save an existing IDTask from within the Parent Project detail view without any issues. However, when I attempt to add an IDTask using the createview, dJango reports a Not NULL constraint error and the new entry is not saved.
In addition to reviewing and trying many other solutions to this problem, I have disabling the code that automatically adds the logged in user id but am still getting the same null constraint error. What's strange is that I am using the same basic createview structures for adding FK objects to the Projects model and this works perfectly. I'm still getting comfortable with Django's class-based views, so must surely be missing something obvious.
Thank you for your help!
Here are the main views related to my issue:
# Detail view for Parent Projects (function-based)
def ParentProjectDetail(request,parent_id):
parents = ParentProject.objects.get(id=parent_id)
projects = Project.objects.filter(parent_project__pk=parent_id).order_by('project_phase', '-launch_date',)
return render(request, 'otis/parent_detail.html', context={'parents':parents, 'projects':projects })
# Detail View for Projects (class-based)
class ProjectDetailView(generic.DetailView):
model = Project
context_object_name = 'project'
template_name = 'otis/project_detail.html'
# Add parent progress report
class add_idtask_view(SuccessMessageMixin, CreateView):
model = IDTasks
template_name = 'otis/id_report_form.html'
form_class = idTaskForm
success_message = "Report added"
def form_valid(self, form):
idtaskform = form.save(commit=False)
idtaskform.user = self.request.user
self.parents_id = self.kwargs.get('parent_id')
form.instance.ParentProject = get_object_or_404(ParentProject,id=self.parents_id)
return super(add_idtask_view, self).form_valid(form)
def get_success_url(self):
return reverse_lazy('otis:parent_detail', kwargs={'pk': self.parents_id})
Here is the modelform:
class idTaskForm(ModelForm):
class Meta:
model = IDTasks
fields = ('parent_phase','complete','milestones','nextsteps','concerns')
widgets = {
'milestones': Textarea(attrs={'cols': 50, 'rows': 5, 'placeholder': 'Task details...'}),
'nextsteps': Textarea(attrs={'cols': 50, 'rows': 5, 'placeholder': 'Task details...'}),
'concerns': Textarea(attrs={'cols': 50, 'rows': 5, 'placeholder': 'Task details...'}),
}
labels = {
'parent_phase': mark_safe('<span class="required">Phase</span>'),
'complete': mark_safe('<span class="required">Percentage Complete</span>'),
'milestones': ('Milestones'),
'nextsteps': ('Next steps'),
'concerns': ('Concerns'),
}
Here are the two models being accessed:
# Parent Project Model
class ParentProject(models.Model):
class Meta:
verbose_name = "parent project"
verbose_name_plural = "parent projects"
ordering = ['title']
title = models.CharField('Name', max_length=100, null=True, blank=False)
parent_group = models.ForeignKey(ProjectGroups, on_delete=models.CASCADE, blank=True, null=True)
parent_type = models.ForeignKey(ProjectTypes, on_delete=models.CASCADE, null=True, blank=False)
description = models.TextField('description', blank=True)
term_due = models.ForeignKey(Terms, on_delete=models.CASCADE, blank=True, null=True)
term_year_due = models.ForeignKey(Years, on_delete=models.CASCADE, blank=True, null=True)
launch_date = models.DateField('launch date', blank=True, null=True)
parent_phase = models.ForeignKey(SDLCPhases, on_delete=models.CASCADE, null=True, blank=False)
history = HistoricalRecords()
def __str__(self):
return str(self.title)
def get_absolute_url(self):
return reverse('otis:parent_detail', kwargs={'pk': self.pk})
# Reports Model
class IDTasks(models.Model):
class Meta:
verbose_name = "Parent task"
verbose_name_plural = "Parent tasks"
ordering = ['updated_on']
parent = models.ForeignKey(ParentProject, on_delete=models.CASCADE)
parent_phase = models.ForeignKey(SDLCPhases, on_delete=models.CASCADE, null=True, blank=False)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
complete = models.IntegerField('percentage complete', blank=True, null=True, default=0)
milestones = models.TextField('milestones', blank=True)
nextsteps = models.TextField('next steps', blank=True)
concerns = models.TextField('concerns', blank=True)
updated_on = models.DateTimeField(auto_now_add=True, null=True)
history = HistoricalRecords()
def __str__(self):
return str(self.complete)
Here are the url patterns:
# url for the parent project detail view
path('parent_detail/<int:parent_id>/', views.ParentProjectDetail, name='parent_detail'),
# url for the create report accessed within the detail view
path('parent_detail/<int:parent_id>/add_id_report/', views.add_idtask_view.as_view(), name='add_id_report'),
Finally, the template link that invokes the modelform:
link_title
I was able to solve my initial problem by restructuring the view like so:
class add_idtask_view(SuccessMessageMixin, CreateView):
model = IDTasks
template_name = 'otis/id_report_form.html'
form_class = idTaskForm
success_message = "Report added"
def form_valid(self, form):
parents_pid = self.kwargs.get('parent_pid')
self.parent_id = parents_pid
form.instance.user = self.request.user
form.instance.parent_id = parents_pid
return super(add_idtask_view, self).form_valid(form)
def get_success_url(self):
return reverse_lazy('otis:parent_detail', kwargs={'parent_pid': self.parent_id})
The first thing I did was sort out what form fields and database fields I was trying to access. It seems I had confused these and not properly referenced them in my initial view.
Once these were working however, I started getting an error that stated the view was expecting an integer but was getting a string. It seems, for whatever reason, when I used the get_object_or_404 method, the view returns the title of the database object and not the primary key.
#Models.py
#BlogPost Model
class BlogPost(models.Model):
POST_CATEGORY = (
('Education','Education'),
('Tech','Tech'),
('Automobile','Automobile'),
('Other','Other')
)
title = models.CharField(max_length=150)
thumbnail = models.ImageField(upload_to='Blog Thumbnail')
category = models.CharField(max_length=100, choices = POST_CATEGORY )
content = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
slug = models.CharField(max_length=200, unique=True, null=True)
tags = models.CharField(max_length=150, null=True, blank=True)
writer = models.ForeignKey(User,on_delete=models.CASCADE,null=False)
def __str__(self):
return self.title
#BlogComment Model
class BlogComment(models.Model):
post = models.ForeignKey(BlogPost,on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.TextField()
parent = models.ForeignKey('self',on_delete=models.CASCADE,null=True)
timestamp = models.DateTimeField(auto_now_add=True)
#Views Code
def blogPost(request, slug):
post = BlogPost.objects.filter(slug=slug)
'''How to get comment for particularly this post'''
comments = BlogComment.objects.filter(post=post) # It is giving a wrong answer
'''The error I am getting
ValueError: The QuerySet value for an exact lookup must be limited to one result using slicing.'''
print(comments)
context = {
'Post':post,
'Comments':comments
}
return render(request,'blogpost.html',context)
How to get the comment for the particulary for this blog post? The error I am getting -" ValueError: The QuerySet value for an exact lookup must be limited to one result using slicing."
objects.filter() returns a queryset.
The filter method is expecting an instance of BlogPost (to get the id) or a integer-id since objects.filter(post=pk)
Use objects.get(), that way you get a instance of BlogPost, not a queryset:
post = BlogPost.objects.get(slug=slug)
comments = BlogComment.objects.filter(post=post)
Additions:
You can also handle the exception that could happen if the post does not exist by different ways. One of them is returning Http404, and here is the easiest way to do that:
from django.shortcuts import get_object_or_404
post = BlogPost.objects.get_object_or_404(slug=slug)
I'm trying to pass two models into a create view, where i am trying to get the the primary key from the URL to retrieve the details from a food truck model so it can be displayed in the page, and where a user can write a review about food truck. Also, I'd like a list of the reviews to be displayed on the page.
views.py
class TruckReviewView(CreateView):
model = Review
template_name = 'truckReviews/detail.html'
fields = ['speedOfService', 'qualityAndTaste', 'valueForMoney', 'comment']
def get_queryset(self):
self.pk = self.kwargs['pk']
queryset = super(TruckReviewView, self).get_queryset()
return queryset
def get_context_data(self, **kwargs):
context = super(TruckReviewView, self).get_context_data(**kwargs)
context['truck'] = FoodTrucks.objects.get(truckID=get_queryset())
context['reviews'] = Review.objects.get(truckID=get_queryset())
return context
urls.py
urlpatterns = [
path('', TruckListView.as_view(), name='reviews-home'),
path('truck/<int:pk>/', TruckReviewView.as_view(), name='truck-detail'),
path('about/', About.as_view(), name='reviews-about'),
]
models.py
class FoodTrucks(models.Model):
truckID = models.IntegerField(primary_key=True, unique=True, null=False)
name = models.CharField(max_length=25)
category = models.CharField(max_length=20)
bio = models.TextField()
avatarSRC = models.TextField(default=None)
avatarALT = models.CharField(max_length=20, default=None)
avatarTitle = models.CharField(max_length=20, default=None)
coverPhotoSRC = models.TextField(default=None)
coverPhotoALT = models.CharField(max_length=20, default=None)
coverPhotoTitle = models.CharField(max_length=20, default=None)
website = models.TextField(default=None)
facebook = models.CharField(max_length=100, default=None)
instagram = models.CharField(max_length=30, default=None)
twitter = models.CharField(max_length=15, default=None)
class Review(models.Model):
reviewID = models.AutoField(primary_key=True, unique=True, serialize=False, null=False)
truckID = models.ForeignKey(FoodTrucks, on_delete=models.CASCADE)
userID = models.ForeignKey(User, on_delete=models.CASCADE)
datePosted = models.DateTimeField(default=timezone.now)
speedOfService = models.IntegerField()
qualityAndTaste = models.IntegerField()
valueForMoney = models.IntegerField()
comment = models.TextField(max_length=128)
I've tried to use get_queryset to get the pk from the URL and pass the pk into get_context_data and target the specific truck with that ID in the database.
The difficulty comes from the fact that you combine a list view and create view. If you want to combine this into one view, then you need to do a bit mixing and matching with different mixins of the Class Based Views.
It can be done, but it's not trivial. If you're new to Django, then this may be overshooting things. I've renamed fields an such and did it as an exercise. I haven't bothered with the form submission, it shouldn't be that difficult to implement as the other views don't deal with the methods involved (form_valid, get_success_url, etc). You can use it as a guide to see what you should be learning. The above linked site is extremely convenient to see how things are mixed together.
The result below will provide the variables "foodtruck", "reviews" and "form" to the template.
import typing as t
from django.views import generic
from .models import FoodTruck, Review
from .forms import ReviewForm
if t.TYPE_CHECKING:
from django.http import HttpRequest, HttpResponse
from django.contrib.auth.models import AbstractUser
class AuthenticatedRequest(HttpRequest):
user: AbstractUser = ...
class FoodTruckDetailReviewListCreateView(
generic.list.MultipleObjectMixin, generic.edit.CreateView,
):
template_name = "foodtrucks/detail.html"
model = Review
list_model = Review
context_list_name = "reviews"
context_object_name = "foodtruck"
detail_model = FoodTruck
form_class = ReviewForm
def get(self, request: "AuthenticatedRequest", *args, **kwargs) -> "HttpResponse":
"""
Combine the work of BaseListView and BaseDetailView
Combines the get implementation of BaseListView and BaseDetailView, but
without the response rendering. Then hands over control to CreateView's
method to do the final rendering.
Some functionality is stripped, because we don't need it.
:param request: The incoming request
:return: A response, which can be a redirect
"""
# BaseListView
self.object_list = self.get_queryset()
# BaseDetailView
self.object = self.get_object()
context = self.get_context_data(
object=self.object, object_list=self.object_list
)
# CreateView sets self.object to None, but we override form_kwargs, so
# we can leave it at a value.
return self.render_to_response(context=context)
def get_template_names(self):
# Bypass logic in superclasses that we don't need
return [self.template_name]
def get_object(self, queryset=None):
# We provide the queryset to superclasses with the other model
return super().get_object(queryset=self.detail_model.objects.all())
def get_queryset(self):
# This only gets called by MultipleObjectMixin
pk = self.kwargs.get(self.pk_url_kwarg)
if pk is None:
raise AttributeError(
"Unable to filter on food truck: {} is missing in url.".format(
self.pk_url_kwarg
)
)
queryset = self.list_model.objects.filter(food_truck_id=pk)
# print(str(queryset.query))
return queryset
def get_context_data(self, **kwargs):
if "object" in kwargs:
kwargs[self.context_object_name] = kwargs["object"]
if "object_list" in kwargs:
kwargs[self.context_list_name] = kwargs["object_list"]
return super().get_context_data(**kwargs)
def get_form_kwargs(self):
# Bypass ModelFormMixin, which passes in self.object as instance if it
# is set.
return super(generic.edit.ModelFormMixin, self).get_form_kwargs()
And as a reference, this is what I changed the models to:
import uuid
from django.contrib.auth import get_user_model
from django.db import models
from django.utils import timezone
class FoodTruck(models.Model):
name = models.CharField(max_length=25)
category = models.CharField(max_length=20)
bio = models.TextField()
avatar_url = models.URLField(blank=True)
avatar_alt_text = models.CharField(max_length=20, blank=True)
avatar_title = models.CharField(max_length=20, blank=True)
cover_photo_url = models.URLField(blank=True)
cover_photo_alt_text = models.CharField(max_length=20, default="No photo provided")
cover_photo_title = models.CharField(max_length=20, default="No photo provided")
website = models.URLField(blank=True)
facebook = models.CharField(max_length=100, blank=True)
instagram = models.CharField(max_length=30, blank=True)
# https://9to5mac.com/2017/11/10/twitter-display-name-limit/
twitter = models.CharField(max_length=50, blank=True)
def __str__(self):
return self.name
class Review(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
food_truck = models.ForeignKey(
FoodTruck, on_delete=models.CASCADE, related_name="reviews"
)
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
posted_at = models.DateTimeField(default=timezone.now)
speed_of_service = models.IntegerField()
quality_and_taste = models.IntegerField()
value_for_money = models.IntegerField()
comment = models.TextField(max_length=128)
def __str__(self):
return "Review about {} by {}".format(
self.food_truck.name, self.user.get_full_name()
)
And finally the form (with a bit of trickery to inject bootstrap classes):
class ReviewForm(forms.ModelForm):
def __init__(self, **kwargs):
super().__init__(**kwargs)
for field in self.fields.values():
if not field.widget.is_hidden:
field.widget.attrs.setdefault("class", "form-control")
class Meta:
model = Review
exclude = ("uuid", "user", "food_truck", "posted_at")
First, there's not need to create a truckID and reviewID primary key fields because Django creates a unique id field for each object automatically on which you can simply do .get(id=1) or .filter(id=1) etc.
Just like it is completely useless to put ID in fields with Foreign Key or any relational fields because Django will automatically take the name and append _id to it. For instance, just user would become user_id or truck would be truck_id in backend on which you can do .get(user__id=1) or .get(user_id=1) for example.
You should review this section of your code. You're actually not doing anything with the primary key:
def get_queryset(self):
queryset = super().get_queryset()
try:
item = queryset.get(id=self.kwargs['pk'])
except:
...
else:
# Do something with item here
...
finally:
return queryset
or, with get_context_data:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
queryset = super().get_queryset()
try:
item = queryset.get(id=kwargs['pk'])
except:
...
else:
# Do something with item here
context['item'] = item
finally:
return context
I'm sorry but your question is a bit confusing. If you're trying to get details from a model you should use a DetailView. Also, on a DetailView assuming you want the details of a Review since you have the truck on a review you could simply override the get_context_data and set truck in the context by doing self.object.truck.
If you're trying to create a review then it's right to use the CreateView but that should only be for the Review model.
To list you should use a ListView.
So, to my understanding, you have a truckID and want to create a review for that. In that case, it'd have a CreateView for Review model.
Have a look at the CreateView, DetailView and ListView docs
I am using django-bootstrap-modal-forms and it works perfectly as in documentation when using fields form my model. Some of the fields are ForeignKeys and they are displayed properly for user to select a value from database table that is referenced by the key, but instead of that I need to put username of the current user.
I tried to change how the CreateView class handles fields, but with no luck. Probably doing something wrong.
models.py
class userSchoolYear(models.Model):
user_in_school = models.ForeignKey(get_user_model(), null=True, on_delete=models.CASCADE)
school = models.ForeignKey(sifMusicSchool, on_delete=models.CASCADE)
school_year = models.ForeignKey(sifSchoolYear, on_delete=models.CASCADE)
school_year_grade = models.CharField(max_length=4, choices=IZBOR_RAZREDA, default=None, null=True)
user_instrument = models.ForeignKey(instType, on_delete=models.CASCADE, default=None, null=True)
user_profesor = models.ForeignKey(profSchool, on_delete=models.CASCADE, default=None, null=True)
views.py
class SchoolYearCreateView(BSModalCreateView):
template_name = 'school_year.html'
form_class = SchoolYearForm
success_message = 'Success!'
success_url = reverse_lazy('school')
def __init__(self, *args, **kwargs):
self.form_class.user_in_school = 'johnny' ### HERE
print(user.username)
super().__init__(*args, **kwargs)
forms.py
class SchoolYearForm(BSModalForm):
class Meta:
model = userSchoolYear
fields = '__all__'
Thanks to the author Uroš Trstenjak I was able to find a solution. I was wrong trying to set field values from views.py, instead it should be done in forms.py. So, basically I had to write a init for the form and alter fields values. Uroš pointed out that at from level I can get current user from self.request.user and it did work.