I'm passing an instance of a model into a modelForm, but, within the view, when I print the form, the values within the model don't show up. Also, when the form is rendered on my template, the values from the instance don't show up.
Views.py
def support_ticket_view(request, id=None):
id = int(id)
instance = SupportTicket.objects.get(id=id, user=user)
form = SupportTicketEditForm(request.POST or None, request.FILES or None, instance=instance)
context = {
'form': form,
}
return render(request, 'accounts/support_ticket_view.html', context)
forms.py
class SupportTicketEditForm (forms.ModelForm):
def __init__(self, *args, **kwargs):
self.instance = kwargs.pop('instance',None)
super(SupportTicketEditForm, self).__init__(*args, **kwargs)
class Meta:
model = SupportTicket
fields = (
'image',
'body_question',
'urgency',
'question_type',
'status',
)
widgets = {
'image': ImageThumbnailFileInput
}
models.py
class SupportTicket(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
question = models.TextField(max_length=10000, null=True, blank=False)
def __str__(self):
return self.user.username
Removed the following:
def __init__(self, *args, **kwargs):
self.instance = kwargs.pop('instance',None)
super(SupportTicketEditForm, self).__init__(*args, **kwargs)
Thanks Daniel Roseman!
Related
class Post(models.Model):
cat_post = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True,null=True)
top_post = models.ForeignKey(TopicsCategory, on_delete=models.CASCADE, blank=True,null=True)
sub_post = models.ForeignKey(SubTopicsCategory, on_delete=models.CASCADE, blank=True,null=True)
class CreatePostView(CreateView):
model = Post
template_name = 'blog/create.html'
form_class = CreatePostForm
def get_context_data(self, *args, **kwards):
print(self.kwargs)
context = super(CreatePostView, self).get_context_data(**kwards)
context['btn'] = 'Add'
return context
def form_valid(self, form, *args, **kwargs):
if self.kwargs.get('category_slug') and len(self.kwargs) == 1:
category = Category.objects.get(slug=self.kwargs['category_slug'])
form.instance.cat_post = category
return super(CreatePostView, self).form_valid(form)
# передача в форму kwargs view
def get_form_kwargs(self):
kwargs = super(CreatePostView, self).get_form_kwargs()
kwargs.update({'view_kwargs': self.kwargs})
return kwargs
def get_success_url(self):
return reverse('topics_category_list', kwargs={'category_slug': self.kwargs['category_slug'], })
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['name', 'text', 'discussion']
# widgets = {
# 'cat_post': forms.HiddenInput(),
# }
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("view_kwargs")
super(CreatePostForm, self).__init__(*args, **kwargs)
def clean_name(self):
name = self.cleaned_data['name']
if self.request.get('category_slug') and len(self.request) == 1:
category = Category.objects.get(slug=self.request['category_slug'])
unique = Post.objects.filter(slug=slugify(self.cleaned_data['name']), cat_post=category.pk,discussion=False).exists()
if unique:
raise ValidationError(f'Post is not unique')
return name
**
I have duplicate sources in db here form_valid and clean_name.
How do I pass the form in the view form form_valid class instance that I got from the database to clean_name.
There will be posts for 2 models and requests will increase
The error
NameError: name 'request' is not defined
My forms.py
class PersonForm(forms.Form):
name = forms.CharField(required=False)
job_title = forms.CharField(required=False)
status = forms.TypedChoiceField(choices=Person.STATUS_CHOICES)
project = Project.objects.get(users=request.user, pk=self.kwargs.get('pk'))
company = forms.ModelChoiceField(queryset=project.companies.all(),required=False)
new_company = forms.CharField(required=False)
note = forms.CharField(required=False)
def __init__(self, *args, **kwargs):
super(PersonForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
visible.field.widget.attrs['class'] = 'form-control'
def clean(self):
return self.cleaned_data
views.py
class PersonCreate(LoginRequiredMixin, FormView):
template_name = 'person/person_form.html'
form_class = PersonForm
success_url = '/project/'
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
cleaned_data = form.clean()
active_project = self.request.session['active_project']
project = Project.objects.get(users=self.request.user, pk=self.request.session['active_project'])
if cleaned_data['name']:
person, created = Person.objects.get_or_create(
name=cleaned_data['name'],
job_title=cleaned_data['job_title'],
created_by=self.request.user,
status=cleaned_data['status'],
project=project
)
if cleaned_data['new_company']:
company, created = Company.objects.get_or_create(name=cleaned_data['new_company'], project=project, created_by=self.request.user)
company.persons.add(person)
company.save()
if cleaned_data['note']:
person.note_set.create(content=cleaned_data['note'], created_by=self.request.user)
person.save()
if cleaned_data['company']:
company = project.companies.get(name=cleaned_data['company'])
company.persons.add(person)
company.save()
return super().form_valid(form)
def get_success_url(self):
return self.request.POST.get('next', '/project/' + str(self.request.session['active_project']))
I want to filter the queryset on the forms.ModelChoiceField field company. Based on the companies of the project the user has access to. How would I do that? Can I access request.session data as well here?
You can't do that like this, because Django forms don't have access to the request at all.
So the best approach I can think of is to pass the user to the form and then use the data when initialized.
First you have to pass the user and pk in the view.
views.py:
# ...
form = PersonForm(user=request.user, pk=kwargs.get('pk'))
Then in your form, you can catch both kwargs and update the project with the correct value,
class PersonForm(forms.Form):
# your form fields code ...
def __init__(self, *args, **kwargs):
# get the user and pk
user = kwargs.pop('user', None)
pk = kwargs.pop('pk', None)
# update project field
super(PersonForm, self).__init__(*args, **kwargs)
self.fields['project'] = Project.objects.get(users=user, pk=pk)
for visible in self.visible_fields():
visible.field.widget.attrs['class'] = 'form-control'
In class-based views to update Form kwargs:
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update({"request": self.request})
return kwargs
I would like to know how I can do that : save an object in my database through Django model with custom field.
This is my modelclass :
class Document(EdqmTable):
language = models.CharField(max_length=2, verbose_name=_('language'), choices=LANGUAGE_CHOICES, null=False)
format = models.CharField(max_length=10, verbose_name=_('format'), choices=FORMAT_CHOICES, null=False)
title = models.CharField(max_length=512, verbose_name=_('document title'), null=False)
publication = models.ForeignKey(Publication, verbose_name=_('publication title'), null=False,
related_name='documents')
class Meta:
verbose_name = _('document')
verbose_name_plural = _('documents')
def save(self, *args, **kwargs):
self.title = f"{self.publication.pub_id}-{self.format.upper()}"
super(Document, self).save(*args, **kwargs)
I have a save method, which let to define my field title with combination between two fields.
title field is hidden in my django form and is set automatically by Django.
But, up to now, it doesn't work because my object is not saved into my database. Something is wrong in my save function ?
EDIT :
I edited my post with forms.py file and my view :
The field document.title is used in my django forms with formset like this :
class PublicationForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['category'].empty_label = _('Select a category') # Modify initial empty_label
class Meta:
model = Publication
fields = ['title', 'pub_id', 'category']
class DocumentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DocumentForm, self).__init__(*args, **kwargs)
self.fields['title'].widget = forms.HiddenInput()
for key in self.fields:
self.fields[key].required = True
class Meta:
model = Document
fields = ['publication', 'language', 'format', 'title', 'upload']
DocumentFormSet = inlineformset_factory(Publication, Document, form=DocumentForm, extra=1)
And my view according to this part :
class PublicationCreateView(EdqmCreateView):
""" Create publication with document form through formset """
model = Publication
template_name = 'freepub/publication_form.html'
def get_context_data(self, **kwargs):
context = super(PublicationCreateView, self).get_context_data(**kwargs)
context['document_form'] = DocumentFormSet(self.request.POST or None, self.request.FILES or None)
return context
def form_valid(self, form):
context = self.get_context_data()
document = context['document_form']
if document.is_valid():
self.object = form.save()
document.instance = self.object
document.save()
return super(PublicationCreateView, self).form_valid(form)
def get_success_url(self):
return reverse('publication-list-crud')
I have a model Course that has the following attr:
class Course(models.Model):
user= models.ForeignKey(
User,
on_delete=models.CASCADE,
)
# email= models.EmailField(default=user.email)
courseName= models.CharField(max_length=20, blank=False)
class Meta:
unique_together= ('user','courseName',)
def __str__(self):
return self.courseName
I have created a form where I want the user to enter just the courseName and after they POST it, I will add the requested user in the model as well.
This is my form which is getting passed on to the template via my ListView
forms.py
class CourseForm(forms.ModelForm):
class Meta:
model= Course
fields = ['courseName']
**Here is my views.py where I am struggling with **
class CoursesListView(ListView, FormMixin):
model = Course
form_class = CourseForm
template_name = "userApp/courseList.html"
def get_queryset(self):
return Course.objects.filter(user__exact=self.request.user)
def get_context_data(self,*args,**kwargs):
context= super(CoursesListView,self).get_context_data(*args, **kwargs)
context['courseForm'] = self.form_class
return context
def post(self,request, *args, **kwargs):
form = self.form_class(request.POST)
user = User.objects.get(username__exact=self.request.user)
**I want to add the user to my model.user field here**
return self.get(redirect, *args, **kwargs)
def get(self,request, *args, **kwargs):
self.object=None
self.form = self.get_form(self.form_class)
return ListView.get(self, request, *args, **kwargs)
So basically my question is how can I add the user in my model before calling form.is_valid().
something like this?
def post(self,request, *args, **kwargs):
form_data = copy.copy(request.POST)
form_data['user'] = User.objects.get(username__exact=self.request.user).pk
form = self.form_class(form_data)
# form handling follows
return self.get(redirect, *args, **kwargs)
This Answer was suggested by a user who deleted this answer. Didnt get his user id but whoever you were thanks a lot for the help!!!
Just use form.save(commit=False) and then make the necessary changes.
def post(self,request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
user = User.objects.get(username__exact=self.request.user)
instance = form.save(commit=False)
instance.user = user
instance.save()
I am using the django 1.3 on trunk, and start learning about class views.
I had this:
class Project(models.Model):
title = models.CharField(max_length=90)
slug = models.CharField(max_length=90)
description = models.TextField()
owner = models.ForeignKey(User)
class ProjectForm(ModelForm):
class Meta:
model = Project
exclude = ('owner',)
widgets = {
'description': Textarea(attrs={'cols': 40, 'rows': 20}),
}
class ProjectCreateView(CreateView):
model = Project
form_class = ProjectForm
def get(self, request, *args, **kwargs):
return super(ProjectCreateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return super(ProjectCreateView, self).post(request, *args, **kwargs)
I am trying, to get a form using model forms from django excluding the owner field, to get the field value after with the request.user property.
The form as it is, works. But how can make sure the ModelForm use request.user for the Project.owner field?
My first guess, was to override get_form_kwargs method from the view
class ProjectCreateView(CreateView):
# .....
def get_form_kwargs(self, **kwargs):
self.initial['owner': self.request.user})
kwargs = super(ProjectCreateView, self).get_form_kwargs(**kwargs)
return kwargs
But seem to have no effect on the data used by the model form
get_form_kwargs is supposed to return a dict of arguments for your form - you set self.initial, but you didn't attach it to kwargs:
def get_form_kwargs(self, **kwargs):
kwargs = super(ProjectCreateView, self).get_form_kwargs(**kwargs)
kwargs['initial']['owner'] = self.request.user
return kwargs