Can a non-form web page be included in a django SessionWizardView?
For example, I want the user to FillOut Form1, Form2, Then View a web page (in same session) (click next), and then Form3? All this while maintaining the same session.
If so, how is this best accomplished? Any examples or snippets?
There's a fairly easy hack for this. Create a plain old form that has one field that is hidden from the user, has no content, and isn't required.
I do this:
class BlankForm(forms.Form):
nothing = forms.CharField(required=False, widget=HiddenInput)
Include it in your SessionWizardView call just like the other pages:
SessionWizardView.as_view([Form1, Form2, BlankForm, Form3])
In the template page you can use some logic like this to display info:
{% if wizard.steps.current == '2' %}
Whatever you want to show on the BlankForm
{% endif %}
Related
I'm creating a django-based website where page content is stored in a model textfield with a detail view of the model displaying it. How can I put {% url %} tags in the content to link to other pages without hard coding links?
Putting the tag into the textfield will just print the tag as plain text. (or if inside an href create a broken link)
Other options are
parsing the content manually inside the view and replacing the tags with the correct url
using some django supplied string parser to create the links before sending to the template
maybe there is a way to do it in the template with a filter or tag around the variable.
I could probably do the manual way but I am hoping there is a django way that I am missing.
class Page(models.Model):
content = models.TextField(blank=True)
class PageView(DetailView):
model=Page
context_object_name='page'
{% extends "base.html" %}
{% block content %}
{{ page.content|safe }}
{% endblock %}
Edit for clarity:
Content in admin
What it renders
What it should render
Edit 2:
I was able to find a solution to the second option thanks to this answer on another question. Using that template_from_string function I rendered the page content as a template then replaced the content in the context with the rendered result.
class PageView(DetailView):
model=Page
context_object_name='page'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Add to context here
context['page'].content = template_from_string(context['page'].content).render(context)
return context
your url's will have a name as shown below-
path('page//',PageView.as_view, name="page-detail")
and in your Page Detail
hope this is what your asking for
Let see if I understood you well, do you want django to show you a url as such and not as plain text?
If you want to avoid django to show you the data as plain text, you can use the escape filter as follows: {{string | escape}}
Check this page for more details about django filters and tags
I am using django-filter to filter a ListView and would like to display a "Clear all filters" link if any filters are applied.
Due to the generic nature of the filtering system I haven't yet found a straightforward way to achieve this.
The only thing I came up with so far is to return the regular queryset in the get_queryset method of the view if a "clear" flag is present in the request, however this doesn't actually clear the filters - it just returns all the data.
Does anyone have a solution/idea for this?
Update: Solution
After Jerin's comment I decided to solve this problem in 2 separate parts:
has filter:
I check if any of the fields I defined in my filter class are in the request. My solution looks a bit different as I'm using class based views so I abstracted it away in a mixin but if you're using simple views like here, you could just do:
def product_list(request):
f = ProductFilter(request.GET, queryset=Product.objects.all())
has_filter = any(field in request.GET for field in
set(f.get_fields()))
return render(request, 'my_app/template.html', {
'filter': f,
'has_filter': has_filter
})
clear all filters:
A simple redirect to your list view:
{% if has_filter %}
{% trans 'Clear all filters' %}
{% endif %}
Here is the mixup version of the answer (combination of mine and Chris)
You could place a Clear all filters button and that will redirect to your default ListView (/host/end/point/).
But some non-filter parameters (such as pagination or something else) may occur in URL. So the better option is, check for any filter fields in URL and if so, display the filter clearing link
The opted solution is,
def product_list(request):
f = ProductFilter(request.GET, queryset=Product.objects.all())
has_filter = any(field in request.GET for field in set(f.get_fields()))
return render(request, 'my_app/template.html', {
'filter': f,
'has_filter': has_filter
})
and in template,
{% if has_filter %}
{% trans 'Clear all filters' %}
{% endif %}
Just make a button and point to the base search field.
<a class="btn btn-warning" href="{% url 'App:FilterView' %}">Reset</a>
If your FilterSet instance is available on the template you can check for filter.is_bound like this:
{% if filter.is_bound %}
Clear filters
{% endif %}
If you are using the FilterMixin or the FilterView, your FilterSet instance will be available as filter to the template as above.
I like this simple solution, however when I attempt to use it the current filter parameters are some how getting appended to the url even though it's the base url in the anchor.
So hovering over the button my link (determined using {% url 'app:view' %} shows
localhost/app/view correctly
However when clicking the button the url in browser has the parameters appended
localhost/app/view/?filter1=val1&filter2=val2 etc.
Is django caching something? Is browser (Chrome) caching? Can I force something in the anchor to not use them?
Answered my own, but for anyone else passing by:
I had the anchor on a button within a the filter form, although it was not a submit button moving it outside the form gave the desired result.
i cant quite find it so i hope someone can help me out.
I found the option of using the
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth" )
In django (1.5). But now its not clear for me how i should use it. Should i still put the request in my views, or can i with this enabled use the user_object in my template without sending an extra variably with the Requestcontect
For example:
My view at the moment:
def user_characters(request, user_id):
characters = Character.objects.filter(user=user_id)
user = User.objects.get(id=user_id)
return render_to_response('characters.html',
{'characters': characters, "user": user},
context_instance=RequestContext(request))
My template:
{% extends "base.html" %}
{% block mainframe %}
{% if characters|length < 3 %}
<p>New Character(WN)</p>
{% endif %}
And then the rest of my view.
I notice in almost every view i make i want the user_object send with it.
Can someone please give me an example of how this works?
With kind regards
Hans
django.contrib.auth.context_processors.auth context processor is enabled by default, you don't have to add anything. When you use RequestContext(), a context variable user is available in all templates that you can use. To get id {{userd.id}}.
To check user is authenticated or not, do
{% if user.is_authenticated %}
{# handle authenticated user #}
{%else%}
{# handle anonymous non-authenticated users #}
{%endif%}
You should not expose the user id in the url, you wont need it anyway, if you use django sessions- and the authentication framework. You can always check the logged in user via request.user in your serverside view. With the context processor your should be able to access the user with user.desiredattribute, but you should not need it for the url you try to create.
The docs on this seem pretty clear to me:
https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.RequestContext
If you want context processors to function, you must ensure that you're using a RequestContext instance. You can do that by explicitly creating it in your views, as you show, or (more conveniently, in my opinion) by using the render shortcut rather than render_to_response as documented here:
https://docs.djangoproject.com/en/dev/topics/http/shortcuts/#render
With the django.contrib.auth.context_processors.auth context processor in place, the user will always be available in the context variable user. At least, assuming your template is being rendered with a RequestContext instance.
You absolutely should not trust a variable obtained from the URL to determine the user if you have any kind of controlled information. With the system you have shown, anyone can view anyone's data simply by editing the URL. That might be OK for a totally insecure application, but it's much more normal to look at request.user.
I'm doing a website in html and base (where all pages extend) I want
to put a session of social network icons. As this session is base on
html it should be displayed on all pages of the website.
I do not want
to put this session in a static html, I want to do in django using
models. This is already done.
Question: Do I have to put the session of social network icons on each view, or can I make a separate view and all others extend this view?
How can I do this?
Try using an inclusion tag. You can create a function for doing all of the work to create the sessions and then associate that with a particular block of HTML.
templatetags/session.py
#register.inclusion_tag('includes/session_box.html')
def output_session_box(...):
...
return { .. }
The associated template file, includes/session_box.html, would have the HTML like any template.
And then your base.html would have:
{% load session %}
{% output_session_box ... %}
Use RequestContext and a context_processor to inject template variables into every view using RequestContext.
It's as simple as a python function accepting request as an arg, and returning a dictionary to be passed into your template.
https://docs.djangoproject.com/en/dev/ref/templates/api/#django.template.RequestContext
def my_processor(request):
return {'foo': 'bar'}
TEMPLATE_CONTEXT_PROCESSORS = (
# add path to your context processor here.
)
I generally have a per-project processor for the basics... It's exactly how django adds {{ user }} or {{ STATIC_URL }} to every template.
For one of my models, I want to show extra content in the change_form. Basically, my model looks like this:
class News(models.Model):
...
class NewsFromSource(models.Model):
news = models.ForeignKey(News)
...
I want to add a 'search' button that, when clicked, triggers a web service request to an external news source, pulls down the available content, and lists all the news pieces contained. The user can then select one of the pieces to "attach" to the News currently edited in the admin interface (i.e. create a new NewsFromSource based on the content downloaded through the web service).
I am done with the web service. What is the best approach to implementing the search-button, list display for the results (I have a view and template that work, need to get those into the form somehow) and the saving part?
What I ended up doing is the following:
1)
I created a view for fetching search results, which boils down to this:
#/myproject/admin/views.py
#never_cache
def news_search(request):
#...query web service
if 'q' in request.POST:
search_term = request.POST['q']
else:
search_term = ''
news = NewsSearch()
news.search(search_term)
return render_to_response( 'news_search_results.html',
{ 'q': search_term,
'news': news.result_list,
'page': page,
'page_left': news.page_left,
'page_right': news.page_right}
)
2) I mapped the view:
#/myapp/urls.py
...
url(r'^myapp/news/search/$', views.news_search),
3) I extended change_form.html for the news model with the following code:
#/myproject/templates/admin/myapp/news/change_form.html
{% extends "admin/change_form.html" %}
{% block after_field_sets %}
...
{% csrf_token %}
<input type="text" name="q" id="news-search-term">
<div id="news-search-results"></div>
...
function submitSearchForm() {
$.post("/myapp/news/search/",
{ 'q': $('#news-search-term').val(),
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val() },
function(data){
$('#news-search-results').html(data);
}
);
}
{{ block.super }}
{% endblock %}
4) I created an html template for displaying the results (news_search_results.html, see 1)
So basically I am sending an AJAX request from the admin page to a custom view to retrieve results from the webservice which then are displayed in a div.
Each element in the results list has a button that sends another request that stores the element with the news id as a ForeignKey.
I have no idea whether this is particularly against Django principles. But it seems to work alright.
Suggestions on doing this in a more "Djangonian" way are welcome.
We'll assume you have a related News model. Add that field to raw_id_fields of the modeladmin we're going to hack, then:
Overload the change_form template for this model, extend admin/change_form.html in admin/yourapp/yourmodel/change_form.html
Add javascript in that template to:
Hide the input and magnifier icon from the news raw id field form raw, you can do that in css too
Add something like a span with a button style in that form row that will open a popup when it is clicked
The popup it should open should be your working view/template with a form to select the news
When the user selects a news, the popup should do an ajax post request to get the news id, and close itself
the value is set to the raw id field input that is hidden, this is pretty tough but fear not someone (disclamer: I) published an article with the whole technical details, also found another one but I didn't test it
It's going to be quite some work. Patience and perseverance will be your best qualities for this mission B)