Django CreateView - How do I call form class __init__? - python

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

How to get request value in another class in django?

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.

How do I pass **kwargs when instantiating an object and access it in the class's __init__() 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})}

__init__ .. get_form_kwargs(self) which function called the other

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.

Python beginner with class variables

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.

Updateview with dynamic form_class

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

Categories