Passing template variables from URL to FormPreview in Django - django

I'm a Django noob and fear the answer to my question is fairly obvious, but hoping someone can help.
I'm building an app that includes the same form on every page, with the content surrounding the form and the model instance to which the form data is tied dependent on a value passed in the URL. Works fine using the standard Form class and (URL, 'template.html', myapp.view) in URLconf, like so:
url(r'^listings/(?P<listing_id>\d+)/submit$', 'myapp.views.lister'),
With FormPreview, however, instead of calling the view in the URLconf, you're calling the subclass with the view functionality baked in.
url(r'^listings/(?P<listing_id>\d+)/submit$', PickFormPreview(PickForm)),
From what I can gather from the docs, FormPreview uses parse_params to pass values captured in the URL to state.self, which I believe is a dictionary. Unfortunately given my level of experience, I can't figure out from this barebones understanding how to customize my FormPreview subclass how to pass the listing_id captured in the URL to a template variable in my form.html template called by FormPreview. Do I somehow need to override parse_params? Or somehow pass state.listing_id? Or am I missing it entirely?
Any help much appreciated!

You're on the right track. The parse_params method in FormPreview does not do anything, but it is the correct method to override in your subclass.
The following example saves listing_id to self.state.listing_id, which is available in the template context.
class PickFormPreview(FormPreview):
def parse_params(self, *args, **kwargs)
"""
Saves listing_id from the url to state
"""
self.state['listing_id'] = kwargs['listing_id']
Then in your template, you access it as:
Listing {{ state.listing_id }}

Related

How to Django reverse to pages created in Wagtail?

I have a Wagtail model for an object.
class ObjectPage(Page):
# fields, not really important
I want to make the object editable by front-end users, so I have also created a generic update view to accomplish this. My question is how I can use Django's reverse() function to point to the edited object in my get_success_url() method:
class EditObjectPage(LoginRequiredMixin, UpdateView):
# model, template_name, and fields defined; not really important
def get_success_url(self):
return("ObjectPage", kwargs={"slug" : self.object.slug}) # doesn't work
return("object_page_slug", kwargs={"slug" : self.object.slug}) # also doesn't work
I know how to do this when I'm explicitly defining the URL name in my urls.py file, but in this case, the URL is created as a Wagtail page and is handled by this line of my urls.py:
url(r"", include(wagtail_urls)),
I've been searching the documentation for whether Wagtail pages are assigned names that can be reversed to, but I'm finding nothing in the official documentation or here on StackOverflow.
The page object provides a get_url method - get_success_url should be able to accept this directly, so there's no need to use reverse.
def get_success_url(self):
return self.object.get_url()
Internally the URL route used by get_url is wagtail_serve, so if you absolutely need to go through reverse, you could replicate the logic there.

Django | Triggering a function from list in template

I'm trying to make a facebook like Newsfeed.
I have a Post which contains all post. After sending it from the view I load the posts to the templates with {% for p in posts %}, for each post I add 2 buttons (share, like) and an input (comment).
How can I know which of them was clicked so I can send the post.id back to the view, including the name, and value and trigger a function to handle them in the database?
I want to know after I click an input what was it, what it included and for which post it belongs.
The way I would have approached this is something as follows:
I would have specific views to handle share and like functionalities, I would rather have them as two separate views. For them you then create urls, definitely you will be also providing post identifier as a parameter to this url.
For eg:
class LikePost(View):
def post(self, request, post_id, *args, **kwargs):
code
For this class, you can then have a url like ^/post/(?P<post_id>\d+)/$.
Now for more simplicity in your Post model class you can write a model method that returns you the url for LikePost view for an instance of post.
Something like this:
def like_post_url(self):
return reverse('appname:reversename-for-url', args=(self.id,))
So now when you loop posts in template you can simply assign this url as value for href in anchor tag you use for button. So every button will have its own url for share, like and also for input.
I think this should make it clear on how you can proceed with simplicity.

Access request in django custom template tags, using the tag decorator

There is a question with the same title and problem: Access request in django custom template tags
The solution proposed, for instance pass takes_context = True to the decorator works perfectly well for tag helpers (simple_tag, inclusion_tag and assignment_tag) but not with the low-level tag decorator.
#register.tag(takes_context=True)
def mytag(parser, token):
...
raises the exception :
tag() got an unexpected keyword argument 'takes_context'
2 questions :
is there a reason why the tag decorator does accept the takes_context argument ?
how can I access the template context with this decorator (and thus the request object) ?
Answer to the 2 sub-questions:
Is there a reason why the tag decorator does accept the takes_context argument ?
It's because, as you said, tag is run at a lower level, parser-level of the template. There is no context at that point.
How can I access the template context with this decorator (and thus the request object) ?
I don't think you can. Again, because it's a parser-level thing. An interesting example is the block tag. In order to be able to override block tags, it uses the extend tag to pass on some info.
I'm struggling with similar situation. The only thing I can think of is making middleware for process_request that resets some global/singleton context which I access in tags. However this wont help if a template is rendered outside a request, like in a command.
#register.tag takes only two arguments: the name and the compilation function. I think you can try to pass request through the token argument in the compilation function.
UPD:
You can also access it in the Node render method
class TestTagNode(template.Node):
def render(self, context):
return context['request'].user
#register.tag
def test_tag(parser, token):
return TestTagNode()

Django: Form in base template

Hi Stackoverflow people,
In my Django project I created a form to register users. This forms can be called through a specific url -> view method. Once the user has filled in the form, presses submit, the same view method will be called and if form.is_valid() is true, then ... simply a standard form, nothing special.
Now, I would like to integrate this little form on every page, and therefore I would like to add it to the base template. I have read that I could populate the form variable through a context_processor, but could I define the process after the submission of the form?
I have created the context_processor.py (as below), added the context_processor to the TEMPLATE_CONTEXT_PROCESSOR dir in the settings (as described here):
from app.forms import Form
def registration_form(request):
return {
registration_form : Form()
}
First of all, the form variable won't be displayed.
And secondly, how do I manipulate the form submission?
I think I misunderstanding the context_processor of Django and would be more than happy about comments on the overall process.
Thank you!
how are you trying to access to form in your template? you probably don't want to use a function name as your dictionary key, maybe you want
return {
'registration_form': Form(),
}
not sure what you mean by manipulate the form submission, but i guess you'd need all the form processing logic in your context processor
if request.POST:
form = Form(request.POST)
# validate etc
instead of creating context processor, create template tag for the purpose and place the tag in base.html
for form submission and displaying errors use ajax, and front-end validations.

Django URL configuration

I have a purchase page, it can take an optional argument as a gift, if it is a gift, the view passes a gift form to the template and if not, a regular purchase form.
my old regular url, which redirects to two seperate views:
(r'^(?P<item>[-\w]+)/purchase/$', 'purchase_view'),
(r'^(?P<item>[-\w]+)/purchase/gift$', 'gift_view'),
and the views was like this:
def purchase_view(request,item):
....use purchase form
def gift_view(request,item):
....use giftform
It is a bad design indeed, as both views having are almost everything same but the forms used.
I have also thougt about using GET and giving gift as a GET param however it wasnt a good idea as I am using POST method for these pages, especially would cause issue after validation.
How can I make this a single url and a single view?
Thanks
urls.py
url(r'^(?P<item>[-\w]+)/purchase/$', 'purchase_view', name='purchase_view'),
url(r'^(?P<item>[-\w]+)/purchase/(?P<gift>gift)/$', 'purchase_view', name='gift_view'),
views.py
def purchase_view(request, item, gift=False):
if gift:
form = GiftForm
else:
form = PurchaseForm
...