here is my view.py
class categAdmin(admin.ModelAdmin):
change_form_template = 'category_forms.html'
list_display = ['title']
model = Category
fields = ['status','title','category_post','body', 'photo',
'url','slider','Gallery','lists','pk_tree','video','maps']
# def render_change_form(self, request, context, **kwargs):
# post = Post.objects.all()
# context['eve'] = post
# return super(categAdmin,self).render_change_form(request, context, **kwargs)
def item_add(request, self, post_id):
tree = post_id
return self.add_view(request, extra_context={'tree': tree})
i am getting error item_add() missing 1 required positional argument: 'request'
You need to swap self and request parameters.
def item_add(self, request, post_id):
tree = post_id
...
Always remember that methods are bound to objects and whenever you call methods, python implicitly passes the self argument(the object on which the method is being called) to the method call, In your example:
class CategAdmin:
def item_add(self, request, post_id):
pass
would be the signature format, note that the self object is the first parameter in the method signature. So when you do
categoryAdmin = CategAdmin()
categoryAdmin.item_add(request,123)
this is what will be called by the python interpreter CategAdmin.item_add(categoryAdmin,request,123)
One more feedback would be to improve your coding style, i.e follow some conventions like always start class names with Capital letter, give meaningful names to class and methods and variables.
This makes your code more readable and via this debugging will be way faster.
Cheers!
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.
I have a little question about request attribute in my function located in a python file (not my view):
def my_function(model, request):
instance = model.objects.filter(application=request.cur_app, display=True).order_by('order')
return instance
In this same file, I call my function like this:
for element in my_function(my_model):
... do something ...
But I get this issue:
my_function() missing 1 required positional argument: 'request'
I don't understand How I can solve this issue, because if I add 'request' in my loop, I get:
name 'request' is not defined
Thank you !
Update:
I have a middleware.py file which contains this:
class MultiSiteMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.cur_app = WebApplication.objects.get_current(request)
return self.get_response(request)
And this is this middleware that I want to get in my menu.py file in this function:
def list_of_edition():
""" Return list of editions
:return queryset
"""
instance = NavbarMenuSettings.objects.filter(application=MultiSiteMiddleware, display=True).order_by('order')
return instance
When you run this function
my_function
you must given two params model and request
model = ...
request = ...
my_function(model,request)
django function base view 1st positional argument is request,
def funtionbaseview(request, arg1, arg2)
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 have googled around trying to figure out and understand how this works, yet I still haven't grasped this quite right. What I want to do is pass a value into a form to then use for a query. I have a session variable called menu_term, which determines the choices in the form.
from views.py
def manage_groups(request):
form = CourseGroupForm(request,current_term=request.session.get('menu_term'))
return render_to_response("accounts/group_management.html", {'form':form}, context_instance=RequestContext(request))
from forms.py
class CourseGroupForm(ModelForm):
def __init__(self, current_term, *args, **kwargs):
super(CourseGroupForm, self).__init__(*args, **kwargs)
courseslist = Course.objects.filter(term=current_term, num_in=settings.LAB_COURSES).order_by('description').distinct();
print(courseslist)
self.fields['courses'].queryset = forms.ChoiceField(label='Select Course', choices=courseslist)
class Meta:
model = CourseGroup
fields = ['name','courses'];
The error I am getting is:
__init__() got multiple values for keyword argument 'current_term'
For the benefit of anyone else coming across this, what are the proper ways of defining a form that takes a value passed in from outside?
Thanks,
Good Day
MJ
Its important to pop the kwarg you instantiate your form with before calling the forms super __init__
class CourseGroupForm(ModelForm):
def __init__(self, current_term, *args, **kwargs):
current_term = kwargs.pop('current_term')
super(CourseGroupForm, self).__init__(*args, **kwargs)
The above assumes current_term is always present.
as #vishen pointed out, check your arguments, you are initializing your form with request as the value for current_term
The error is happening because in your model form init decleration
class CourseGroupForm(ModelForm):
def __init__(self, current_term, *args, **kwargs)
current_term is the first argument that the form is expecting to find, but because you are passing through the request object first and then the current_term after that, your effiectely passing the following
form = CourseGroupForm(current_term=request,current_term=request.session.get('menu_term'))
Hence the multiple values for keyword argument 'current_term' error message.
Why do we have template_name = None as class variable here?(from django source code)
It's because if self.template_name is None, would raise an error?
(self.template_name would look for instance variable and if it's not there, would return the class variable)
If so, wouldn't it be better to have def __init__(self): self.template_name = None ?
class TemplateResponseMixin(object):
"""
A mixin that can be used to render a template.
"""
template_name = None
response_class = TemplateResponse
def render_to_response(self, context, **response_kwargs):
"""
Returns a response with a template rendered with the given context.
"""
return self.response_class(
request = self.request,
template = self.get_template_names(),
context = context,
**response_kwargs
)
def get_template_names(self):
"""
Returns a list of template names to be used for the request. Must return
a list. May not be called if render_to_response is overridden.
"""
if self.template_name is None:
raise ImproperlyConfigured(
"TemplateResponseMixin requires either a definition of "
"'template_name' or an implementation of 'get_template_names()'")
else:
return [self.template_name]
TemplateResponseMixin is a mixin which is not using an init, to make it easier to use in a mutiple inheritence. It does not need its own state, so it does not need a constructor. This also makes the inheritence easier because you don' t need to call a constructor on it in your subclass.
The template_name is set as a class instance obviously because there is no constructor. It implies that it should be set from the subclass. Also, changing the value of it will affect all future instances of that mixin.