Sup, need to use a function in a different class without losing the model, while still being able to change the function(not important, I can rewrite func into more flexible func). Can't solve this issue at least 10 hours. Google didnt help =( I know code is a little dirty, I will clean that :D
Don't worry
I have same header with form and another form in all pages.
Need form from class head in class stockpage. And everyone template and future classes as well.
Views
class head(View):
template_name = "dental/mainpage.html"
model = signup
def get(self,request):
if request.method == 'GET':
form = UserSign
return render(request, "dental/mainpage.html", {"form": form})
def FormSign(self,request):
if request.method == 'POST':
form = UserSign
if form.is_valid():
body = {
'Name': form.cleaned_data['Name'],
'email': form.cleaned_data['email'],
'Number': form.cleaned_data['Number'],
}
info_user = "\n".join(body.values())
send_mail(
'Sign',
info_user,
'eric1122221#mail.ru',
['eric1122221#mail.ru'],
fail_silently=False)
return render(request, "dental/mainpage.html", {"form": form}) #self.template_name
return render(request, "dental/mainpage.html", {"form": form})
class stockpage(ListView):
template_name = "dental/stocks.html"
model = stock
context_object_name = "stocks"
HTML
signuphtml
{% load static %}
{%block css_files %}
<link rel="stylesheet" href="{% static "signup.css" %}">
{% endblock %}
{% block content %}
<section id="forms">
<form action="" method="post">
{% csrf_token %}
<div id="txt" class="form-control {% if form.errors %}invalid{% endif %}">
{{ form.label_tag }}
{{ form }}
{{ form.errors }}
</div>
<div id="buttsig">
<button id="b4" type="submit">записаться</button>
</div>
</form>
</section>
{% endblock content %}
mainpage.html
{% extends 'main.html' %}
{% load static %}
{%block css_files %}
<link rel="stylesheet" href="{% static "header.css" %}">
<link rel="stylesheet" href="{% static "mainpage.css" %}">
<link rel="stylesheet" href="{% static "signup.css" %}">
<link rel="stylesheet" href="{% static 'assets/css/bootstrap.css' %}">
{% endblock %}
{% block title %}{% endblock %}
{% block content %}
{% include "dental/includes/header.html" %}
<div ="d1">
<ul>
<li>blabla</li>
<li>blabla</li>
<li>blabla</li>
<li>blabla</li>
</ul>
</div>
{% include "dental/includes/signup.html" %}
{% include "dental/includes/tail.html" %}
{% endblock content %}
stocks html
{% extends 'main.html' %}
{% load static %}
{%block css_files %}
<link rel="stylesheet" href="{% static "header.css" %}">
<link rel="stylesheet" href="{% static "mainpage.css" %}">
<link rel="stylesheet" href="{% static "signup.css" %}">
<link rel="stylesheet" href="{% static 'assets/css/bootstrap.css' %}">
<link rel="stylesheet" href="{% static "stocks.css" %}">
{% endblock %}
{% block title %}{% endblock %}
{% block content %}
{% include "dental/includes/header.html" %}
<section id="contentstock">
{% for stock in stocks %}
<li>
<h4>{{ stock.title }}</h4>
<img src="{{ stock.image.url }}" alt="{{ stock.image }}"/>
<h4>{{ stock.content|linebreaks}}</p>
</li>
{% endfor %}
</section>
{% include "dental/includes/signup.html" %}
{% include "dental/includes/tail.html" %}
{% endblock content %}
Try adding separate view for handling the form with hidden field for url to redirect to. Django's default auth views work like this. Also custom context processor may help to provide the form for all pages without overriding all their get or get_context_data methods.
Consider the example:
forms.py:
class MyForm(forms.Form):
next_url = forms.CharField(widget=forms.HiddenInput, required=False)
name = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
context_processors.py:
def my_form_context_processor(request):
my_form = MyForm()
my_form.fields['next_url'].initial = request.get_full_path()
return {'my_form': my_form}
settings.py:
TEMPLATES = [
{
...
'OPTIONS': {
'context_processors': [
...
'my_app.context_processors.my_form_context_processor',
],
},
},
]
views.py:
class MyFormView(FormView):
form_class = MyForm
template_name = 'my_form.html'
def form_valid(self, form):
# ...
next_url = form.cleaned_data.get('next_url')
if not next_url:
next_url = reverse('my_app:home') # default
return HttpResponseRedirect(next_url)
class ViewA(TemplateView):
template_name = 'template_a.html'
class ViewB(TemplateView):
template_name = 'template_b.html'
template_a.html:
{% include "my_form.html" %}
<h1>A</h1>
template_b.html:
{% include "my_form.html" %}
<h1>B</h1>
my_form.html:
<form action="{% url 'my_app:my_form' %}" method="POST">
{% csrf_token %}
{{ my_form.as_p }}
<p><input type="submit" value="Go!"></p>
</form>
Related
$ Hello, I was trying to use "GCBV Generic Class Based View" for edit a post, but it seems not working and event it django can't find my HTML and I don't know why , Hope I get some support ….
$ edit button link
{% if post.created_by == user %}
<div class="mt-3">
<a class="btn btn-success float-end"
href="{% url 'edit_post' post.topic.board.pk post.topic.pk post.pk %}">Edit</a>
</div>
{% endif %}
$ edit HTML Page
{% extends 'base.html' %}
{% load static %}
{% block title %}Edit Post{% endblock %}<!-- | Page-title-->
{% block content %}
<link rel="stylesheet" href="{% static 'css/boards.css' %}">
<div class="newtopic">
<div class="container container-newtopic w-50">
<h1>Edit Post</h1>
<br>
{% include 'parts/alerts.html' %}
<div aria-label="breadcrumb">
<ol class="breadcrumb n1-head">
<li class="breadcrumb-item">Boards</li>
<li class="breadcrumb-item"><a href="{% url 'topics' post.topic.board.pk
%}">
{{post.topic.board.name}}</a></li>
<li class="breadcrumb-item active" aria-current="page"><a href="">Edit
Post</a></li>
</ol>
</div>
<form method="POST" action="" novalidate class="mb-4">
{% csrf_token %}
{% include 'includes/form.html' %}
<button type="submit" class="btn main-btn w-100 rounded-pill mt-5">
Save Changes
</button>
</form>
</div>
</div>
{% endblock %}
$ Views.py
#method_decorator(login_required, name='dispatch')
class PostUpdateView(UpdateView):
model = Post
fields = ('message',)
template_name = 'edit_post.html'
pk_url_kwarg = 'post_id'
context_object_name = 'post'
def form_valid(self, form):
post = form.save(commit=False)
post.updated_by = self.request.user
post.updated_date = timezone.now()
post.save()
return redirect('topic_posts', board_id=post.topic.board.pk, topic_id=post.topic.pk)
$ Urls.py
urlpatterns = [
path('<int:board_id>/topics/<int:topic_id>/posts/<int:post_id>/edit',
views.PostUpdateView.as_view(), name="edit_post"),
]
$error message
TemplateDoesNotExist at /boards/4/topics/24/posts/28/edit
edit_post.html
Request Method: GET
Request URL: http://localhost:8000/boards/4/topics/24/posts/28/edit
Django Version: 4.0.5
Exception Type: TemplateDoesNotExist
Exception Value: edit_post.html
I keep getting the above error (in the title) for my DeleteView.
Strangely my UpdateView, UpdateObject form and update_object template are identical to my DeleteView, DeleteObject form and delete_object template respectively. I'm not sure why bootstrap is giving me an error for this form and not my update form?
Here are the files:
forms.py:
from django import forms
from . import models
from django.forms import ModelForm
class CreateBouquetForm(ModelForm):
class Meta:
model = models.Bouquet
exclude = ('price',)
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
class UpdateBouquetForm(ModelForm):
class Meta:
model = models.Bouquet
exclude = ('price',)
class DeleteBouquetForm(ModelForm):
class Meta:
model = models.Bouquet
exclude = ('price',)
`
views.py:
class UpdateBouquet(UpdateView):
model = models.Bouquet
form_class = forms.UpdateBouquetForm
template_name = 'products/update_bouquet.html'
success_url = reverse_lazy('products:shop')
def form_valid(self,form):
self.object = form.save(commit=False)
result = 0
for flower in self.object.flower.all():
result += flower.price
self.object.price = result
self.object.save()
return super().form_valid(form)
class DeleteBouquet(DeleteView):
model = models.Bouquet
form_class = forms.DeleteBouquetForm
template_name = 'products/delete_bouquet.html'
success_url = reverse_lazy('products:shop')
products/update_bouquet.html:
{% extends 'site_base.html' %}
{% load bootstrap3 %}
{% block content_block %}
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" class="btn btn-outline-success" value="Save bouquet and continue shopping">
</form>
<h6>Back to bouquet</h6>
{% endblock %}
products/delete_bouquet.html:
{% extends 'site_base.html' %}
{% load bootstrap3 %}
{% block content_block %}
<h5>Are you sure you want to delete your bouquet?</h5>
<form method="POST">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" class="btn btn-outline-success" value="Delete">
</form>
<h6><a class="btn btn-outline-danger" href="{% url 'products:detail_bouquet' pk=bouquet.pk %}">Cancel</a></h6>
{% endblock %}
urls.py:
url(r'^bouquet/(?P<pk>\d+)/update/$',views.UpdateBouquet.as_view(),name="update_bouquet"),
url(r'^bouquet/(?P<pk>\d+)/delete/$',views.DeleteBouquet.as_view(),name="delete_bouquet"),
Here's what the error page says:
Error during template rendering
In template C:\Users\joann\Desktop\Flowers_Storefront\storefront\templates\site_base.html, error at line 8
Parameter "form" should contain a valid Django Form.
1 <!DOCTYPE html>
2 {% load static %}
3 {% load bootstrap3 %}
4 <html lang="en" dir="ltr">
5 <head>
6 <meta charset="utf-8">
7 <title></title>
8 <link href="https://cdn.jsdelivr.net/**npm/bootstrap#5.0.0-beta1/dist/css/boo**tstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
9 <link rel="stylesheet" href="{% static "/css/css_master.css" %}">
10 <link rel="preconnect" href="https://fonts.gstatic.com">
11 class="container-fluid">
...etc....
Thanks in advance if you can help!
DeleteView does not do any form handling and so does not add a "form" key to the context. Remove form_class from your view and remove the bootstrap_form tag from your template
class DeleteBouquet(DeleteView):
model = models.Bouquet
template_name = 'products/delete_bouquet.html'
success_url = reverse_lazy('products:shop')
{% extends 'site_base.html' %}
{% block content_block %}
<h5>Are you sure you want to delete your bouquet?</h5>
<form method="POST">
{% csrf_token %}
<input type="submit" class="btn btn-outline-success" value="Delete">
</form>
<h6><a class="btn btn-outline-danger" href="{% url 'products:detail_bouquet' pk=bouquet.pk %}">Cancel</a></h6>
{% endblock %}
I created an inline relation between Reader and Book models.
I imported the formset in my template successfully but I can not create a new Book form by clicking a link related to my addtext attribute in the below script. In otherwords, for one Reader I want to be able to create more than one Book form by clicking a link.
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'jquery.formset.js' %}"></script>
<script type="text/javascript">
$('table.book tr.formset_row').formset({
addText: 'Add new Book',
deleteText: 'Delete',
prefix: 'reader_book_set',
animateForms: true
});
</script>
The whole template is this:
{% extends 'base.html' %}
{% load bootstrap3 %}
{% load static %}
<!-- Latest compiled and minified JavaScript -->
{% block content %}
<div class="col-md-12 text-center">
<h2>Create / Edit Reader </h2>
</div>
<hr>
<form class="well" method="post" action="">
{% csrf_token %}
{% bootstrap_form form %}
<table class="table book">
{{ formset.management_form }}
{% for form in formset.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle row1 row2 %} formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'jquery.formset.js' %}"></script>
<script type="text/javascript">
$('table.book tr.formset_row').formset({
addText: 'Add new Book',
deleteText: 'Delete',
prefix: 'reader_book_set',
animateForms: true
});
</script>
{% buttons %}
<button type="submit" class="btn btn-primary">
Submit
</button>
{% endbuttons %}
</form>
<hr>
{{ form.media }}
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/forms.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/base.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/widgets.css' %}"/>
<script type="text/javascript" src="/admin/jsi18n/"></script>
<script type="text/javascript" src="/static/admin/js/core.js"></script>
<script type="text/javascript" src="/static/admin/js/admin/RelatedObjectLookups.js"></script>
<script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.min.js"></script>
<script type="text/javascript" src="/static/admin/js/jquery.init.js"></script>
<script type="text/javascript" src="/static/admin/js/actions.min.js"></script>
<script type="text/javascript" src="/static/admin/js/calendar.js"></script>
<script type="text/javascript" src="/static/admin/js/admin/DateTimeShortcuts.js"></script>
{% endblock %}
Here is my view:
class ReaderBookCreateView(LoginRequiredMixin, CreateView):
model = Reader
fields = '__all__'
template_name='test/test.html'
def get_context_data(self, **kwargs):
data = super(ReaderBookCreateView, self).get_context_data(**kwargs)
if self.request.POST:
data['formset'] = BookFormSet(self.request.POST)#bound the formset with data
else:
data['formset'] = BookFormSet()#empty formset
return data
def form_valid(self, form):
context = self.get_context_data()
formset = context['formset']
with transaction.atomic():
self.object = form.save()
if formset.is_valid():
formset.instance = self.object
formset.save()
return super(ReaderBookCreateView, self).form_valid(form)
def get_success_url(self, **kwargs):
return reverse('client_list')
Here is how it looks. I would like to have a link Add new Book above the submit button for creation of the new Book form for the current reader.
Any help will be appreciated.
It was as usual in these situations a javascript issue. I solve it.
My project could not found the path for jquery.formset.js file.
Use F12 always when you trying to debug javascript.
I thought for whatever reason this would be easy to do, but I looked deeper and it appears there is no straightforward way to allow users to execute custom admin actions on the "change" view of an instance (i.e. when you are just viewing the edit screen for a single instance, not the list of instances).
Am I overlooking an easy way to do this? Or is my only choice to override one of the admin templates (and probably the ModelAdmin.add_view method)?
Here is update and improvement of this answer. It works with django 1.6 and redirects to where you came from.
class ActionInChangeFormMixin(object):
def response_action(self, request, queryset):
"""
Prefer http referer for redirect
"""
response = super(ActionInChangeFormMixin, self).response_action(request,
queryset)
if isinstance(response, HttpResponseRedirect):
response['Location'] = request.META.get('HTTP_REFERER', response.url)
return response
def change_view(self, request, object_id, extra_context=None):
actions = self.get_actions(request)
if actions:
action_form = self.action_form(auto_id=None)
action_form.fields['action'].choices = self.get_action_choices(request)
else:
action_form = None
extra_context=extra_context or {}
extra_context['action_form'] = action_form
return super(ActionInChangeFormMixin, self).change_view(request, object_id, extra_context=extra_context)
class MyModelAdmin(ActionInChangeFormMixin, ModelAdmin):
......
Template:
{% extends "admin/change_form.html" %}
{% load i18n admin_static admin_list admin_urls %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/changelists.css" %}" />
{% endblock %}
{% block object-tools %}
{{ block.super }}
<div id="changelist">
<form action="{% url opts|admin_urlname:'changelist' %}" method="POST">{% csrf_token %}
{% admin_actions %}
<input type="hidden" name="_selected_action" value="{{ object_id }}">
</form>
</div>
{% endblock %}
Here's what I ended up doing.
First, I extended the change_view of the ModelAdmin object as follows:
def change_view(self, request, object_id, extra_context=None):
actions = self.get_actions(request)
if actions:
action_form = self.action_form(auto_id=None)
action_form.fields['action'].choices = self.get_action_choices(request)
else:
action_form = None
changelist_url = urlresolvers.reverse('admin:checkout_order_changelist')
return super(OrderAdmin, self).change_view(request, object_id, extra_context={
'action_form': action_form,
'changelist_url': changelist_url
})
Basically we're just gathering the data needed to populate the actions dropdown on the change view.
Then I just extended change_form.html for the model in question:
{% extends "admin/change_form.html" %}
{% load i18n adminmedia admin_list %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/changelists.css" />
{% endblock %}
{% block object-tools %}
{{ block.super }}
<div id="changelist">
<form action="{{ changelist_url }}" method="POST">{% csrf_token %}
{% admin_actions %}
<input type="hidden" name="_selected_action" value="{{ object_id }}">
</form>
</div>
{% endblock %}
This is almost identical to how the admin actions section is outputted on the change list view. The main differences are: 1) I had to specify a URL for the form to post to, 2) instead of a checkbox to specify which object(s) should be changed, the value is set via a hidden form field, and 3) I included the CSS for the change list view, and stuck the actions in a div with id of #changelist -- just so the box would look halfway decent.
Not a great solution, but it works okay and requires no additional configuration for additional actions you might add.
What I did was create my own MYAPP/templates/admin/MYMODEL/change_form.html template:
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block object-tools %}
{% if change %}{% if not is_popup %}
<ul class="object-tools">
<li><a href="{% url MY_COMMAND_VIEW original.id %}" class="historylink" >MY COMMAND</a></li>
<li>{% trans "History" %}</li>
{% if has_absolute_url %}<li>{% trans "View on site" %}</li>{% endif%}
</ul>
{% endif %}{% endif %}
{% endblock %}
So I basically only changed the block "object-tools" where the history-link and the "view on site"-link are. the rest of the original change_form.html remains untouched.
BTW: "original.id" is the id of the model you are editing.
I'd like to deliver special versions of my django site for different (mobile-)browser.
What are possible solutions to do this?
In your view, do smthg like this
def map(request, options=None, longitude=None, latitude = None):
if 'iPhone' in request.META["HTTP_USER_AGENT"]:
user_agent = 'iPhone'
elif 'MSIE' in request.META["HTTP_USER_AGENT"]:
user_agent ='MSIE'
else: user_agent=''
print user_agent
return render_to_response('map/map.html',
{
'user_agent': user_agent
})
and in your template
{% ifnotequal user_agent "iPhone" %}
{% ifequal user_agent "MSIE" %}
{% include 'map/map_ie.html' %}
{% else %}
{% include 'map/map_default.html' %}
{% endifequal %}
{% else %}
{% include 'map/map_iphone.html' %}
{% endifnotequal %}
best practice: use minidetector to add the extra info to the request, then use django's built in request context to pass it to your templates like so.
from django.shortcuts import render_to_response
from django.template import RequestContext
def my_view_on_mobile_and_desktop(request)
.....
render_to_response('regular_template.html',
{'my vars to template':vars},
context_instance=RequestContext(request))
then in your template you are able to introduce stuff like:
<html>
<head>
{% block head %}
<title>blah</title>
{% if request.mobile %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-mobile.css">
{% else %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-desktop.css">
{% endif %}
</head>
<body>
<div id="navigation">
{% include "_navigation.html" %}
</div>
{% if not request.mobile %}
<div id="sidebar">
<p> sidebar content not fit for mobile </p>
</div>
{% endif %>
<div id="content">
<article>
{% if not request.mobile %}
<aside>
<p> aside content </p>
</aside>
{% endif %}
<p> article content </p>
</aricle>
</div>
</body>
</html>