I have a django create view and I want to call the __init__ of the form class and I don't know how to do that.
class PersonCreateView(CreateView):
model = Person
form_class = PersonForm
In the form class I made some logic to redefine the queryset of some combos. My problem is that I don't know how to call the __init__ method, or any other method, of the PersonForm
Thanks in advance for any help.
You shouldn't call it yourself. You can override get_form_kwargs to provide extra arguments to pass to the form instantiation.
class PersonCreateView(CreateView):
model = Person
form_class = PersonForm
def get_form_kwargs(self, *args, **kwargs):
form_kwargs = super(PersonCreateView, self).get_form_kwargs(*args, **kwargs)
form_kwargs['my_extra_queryset_param'] = get_my_extra_queryset()
return form_kwargs
The init method is actually called automatically by the class when a new instance of the object is instantiated.
Consider the following example:
class House():
__init__(self,x,y):
self.x = x
self.y = y
self.z = x*y
To call init, we just do the following:
h = House(5,7)
This will create the object and automatically invoke the init function. It works the same way for django views.
I see Daniel beat me to an answer, perhaps his is more what you're looking for. Anyways, hope this helps a little at least!
Related
It's an example that's as similar as possible, and it's not exactly the same as the actual code.
But I believe it's easy to understand.
class Fruits:
...
def get_sample_data(self, df):
...
data = {
'put_file_attachment': >here<,
}
...
class DataInputForm(forms.Form):
attachment = forms.FileField()
class MyView(FormView):
template_name = 'view.html'
form_class = DataInputForm
def get_success_url(self):
return str(
reverse_lazy("milk")
)
def post(self, request, *args, **kwargs):
get_file = request.FILES.get('attachment')
...
k = Fruits()
k.load_data()
return self.render_to_response(context)
I would like to bring the attachment(In fact, get_file) that the user attached to the web class Fruits's >here<
In other words, I would like to save the file(get_file) in DB column (put_file_attachment) by the user's attachment. How can I get a value passed to a request from another class to another class?
I tried to get 'get_file' by creating a MyView object in the Fruit class, but it doesn't work.
Is that possible in this structure or Am I not understanding the concept of request??
The variable must be explicitly passed to the class for it to be available. It's currently in a different scope, so it won't be available.
So, either refactor your Fruits class to take your file as an argument to your constructor (ie, __init__), or pass it in some other way, such as a parameter to your load_data method.
Here I'd like to pass a **kwargs dictionary when instantiating my PlayerForm objects and be able to access it when calling __init__() method. This is what I've done below but it's not working.
This is somewhere in my views.py file:
context = {'player_form': PlayerForm(kwargs={'user': request.user})}
This is in my forms.py file
from .models import Game, Player
class PlayerForm(forms.ModelForm):
class Meta:
model = Player
fields = ['game', 'username']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if kwargs.get('user'):
self.fields['game'].queryset = Game.objects.exclude(player__user=user)
You can use kwargs using ** operator.
Try using below code:
context = {'player_form': PlayerForm(**{'user': request.user})}
I'm little confused about which of the following functions called the other one
is
___init____(self,*args,**kwargs) called get_forms_kwargs(self)
or
get_forms_kwargs(self) called ___init____()
as I made the following mixin:
class RequestformattachMixin(object):
def get_form_kwargs(self):
kwargs=super().get_form_kwargs()
kwargs['request']=self.request
print(kwargs)
return kwargs
and removed the get_forms_kwargs(self) from the CBV in view.py and instead updated the CBV to let it inherit from the mixin
class LoginView(NextUrlMixin,RequestformattachMixin,FormView):
form_class = login_page
template_name = 'login.html'
success_url = '/'
and didn't call the get_forms_kwargs(self) in CBV and it's working with no errors.
please need an explanation for that.
I'm trying to define a variable in my view like this:
class PostMessageView(LoginRequiredMixin, generic.TemplateView):
url_redirect = None
def post(self, request, *args, **kwargs):
return redirect(self.url_redirect)
I know this is not the good way, and there are build-in classes for that, but my problem is not here. My problem is about pure Python (I guess). If I make a descendant, I can do it like that, it works:
class ContactDetailView(PostMessageView):
template_name = 'my_home/contact_detail.html'
url_redirect = 'my_profile_contact_detail'
My problem is when I want to change url_redirect with a dynamic value, like:
class ContactDetailView(PostMessageView):
template_name = 'my_home/contact_detail.html'
def get_context_data(self, **kwargs):
self.url_redirect = self.request.build_absolute_uri(self.request.path)
Then I get argument of type 'NoneType' is not iterable because, I guess, self.url_redirect doesn't overwrite url_redirect.
How to do it properly in Python?
You can use a property for this:
class ContactDetailView(PostMessageView):
template_name = 'my_home/contact_detail.html'
#property
def url_redirect(self):
return self.request.build_absolute_uri(self.request.path)
This url_redirect method essentially acts like an attribute of the class. Using the decorator version like this will make it a getter only. You can use property as a method instead, if you wanted to make a setter as well.
The issue is that get_context_data() is not called as it should be called by your post() method.
This should work:
def post(self, request, *args, **kwargs):
self.get_context_data()
return redirect(self.url_redirect)
However, get_context_data() is supposed to return a dictionary of data to pass to the template, it is not supposed alter the object state.
I would like to dynamically change the form_class of an UpdateView CBV in Django 1.6.
I've tried to do this using the get_context_data(), but that didn't help since the form is already initialized. So it will need to happen during __init__, I guess.
Here's what I've tried on __init__:
class UpdatePersonView(generic.UpdateView):
model = Person
form_class = ""
def __init__(self, *args, **kwargs):
super(UpdatePersonView, self).__init__(*args, **kwargs)
person = Person.objects.get(id=self.get_object().id)
if not person.somefield:
self.form_class = OneFormClass
elif person.somefield:
self.form_class = SomeOtherFormClass
I'm stuck with a 'UpdatePersonView' object has no attribute 'kwargs' error message when executing person = Person.objects.get(id=self.get_object().id).
When manually specifying the id (e.g. id=9), then the setup works.
How can I get the args/kwargs inside the init method that I'm overriding? Particularly I would need access to the pk.
You should simply override get_form_class.
(Also I'm not sure why you're querying for person: that object is the same is self.get_object() already, so there's no point getting the ID of that then querying again.)
def get_form_class(self):
if self.object.somefield:
return OneFormClass
else:
return SomeOtherFormClass