I need to autoincrement value in my checkbox and reset value when I generated new massive of checkbox
forloop.count dont reset
{% for ans in Answ %}
{% if ans.question_id_id == Questions.id %}
<input type="hidden" value="{{ Questions.id }}" name="id">
<div class="form-check" ><label><input type="checkbox" value="{{ ans.id }}" name="answer"> {{ ans.answer }} </label></div>
{% endif %}
{% endfor %}
views.py
class AnswerQuestionView (LoginRequiredMixin, DetailView):
login_url = '/login'
redirect_field_name = 'redirect_to'
model = Question
template_name = 'index.html'
context_object_name = 'Questions'
slug_field = 'pk'
def get_context_data(self, **kwargs):
context = super(AnswerQuestionView, self).get_context_data(**kwargs)
context['user_group'] = self.request.user.groups.values_list()[0][1]
context['Answ'] = QuestAnswer.objects.all()
return context
This is one of the many reasons why you should not do filtering in the template. Another very important one is performance: as the number of answers will grow, eventually the template rendering will take a lot of time.
You can filter in the view with:
class AnswerQuestionView(LoginRequiredMixin, DetailView):
login_url = '/login'
redirect_field_name = 'redirect_to'
model = Question
template_name = 'index.html'
context_object_name = 'question'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user_group'] = self.request.user.groups.values_list()[0][1]
context['answers'] = QuestAnswer.objects.filter(question_id=self.object)
return context
You probably can even use the related name:
class AnswerQuestionView(LoginRequiredMixin, DetailView):
login_url = '/login'
redirect_field_name = 'redirect_to'
model = Question
template_name = 'index.html'
context_object_name = 'question'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user_group'] = self.request.user.groups.values_list()[0][1]
context['answers'] = self.object.questionanswer_set.all()
return context
Note: Normally one does not add a suffix …_id to a ForeignKey field, since Django
will automatically add a "twin" field with an …_id suffix. Therefore it should
be question, instead of question_id.
Related
I'm using ListView in my Class Based Views and I want to sort the goods by the selected field by the user, but I couldn't find the information I needed
view
class Shop(ListView):
template_name = 'essense/shop.html'
context_object_name = 'items'
paginate_by = 9
allow_empty = False
def get_queryset(self):
return Item.objects.all()
def get_context_data(self, *, object_list=None, **kwargs):
***context***
return context
def get_ordering(self):
ordering = self.request.GET.get('orderby',)
print(ordering)
return ordering
template
<form action="{% url 'shop' %}" method="get" id="sortProduct">
<div class="product-sorting d-flex">
<p>Sort by:</p>
<select type="submit" name="select">
<option type="submit" name="orderby" value="price">Price: $$ - $</option>
<option type="submit" name="orderby" value="-price">Price: $ - $$</option>
</select>
<input type="submit" class="d-none" value="">
</div>
</form>
You should not override the get_queryset, since there is where the ordering logic is happening. You can specify the model with the model attribute [Django-doc]:
class Shop(ListView):
model = Item
template_name = 'essense/shop.html'
context_object_name = 'items'
paginate_by = 9
allow_empty = False
# no get_queryset
def get_ordering(self):
return self.request.GET.get('orderby',)
or if you want to filter the queryset by making a super call:
class Shop(ListView):
model = Item
template_name = 'essense/shop.html'
context_object_name = 'items'
paginate_by = 9
allow_empty = False
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).all()
def get_ordering(self):
return self.request.GET.get('orderby',)
Note that it is not very safe to let a user select an arbitrary order by. Hashed passwords can be retrieved if one for example orders on user__password for example. Usually it is better to retain a list of fields that are allowed to order by.
enter code hereI'm having some problems to solve a problem. I have a template, which allows the user to change some of their account settings. My goal is to initialize the form, with the user's default values, and he can keep or change them (by after submit form). However, until now the page does not render these values. I'm using a class based view, CreateView, for this purpose.
My code is listed below.
Here, is my CreateView.
class DetailUserInfoView(LoginRequiredMixin ,CreateView):
model = CustomUser.CustomUser
template_name = 'users/InfoUser.html'
login_url = settings.LOGOUT_REDIRECT_URL
context_object_name = 'user'
form_class = CustomUserChangeForm
def get_object(self):
self.model = self.request.user
return self.model
def get_initial(self):
initial = super(DetailUserInfoView, self).get_initial()
initial = initial.copy()
initial[config.USERNAME] = self.request.user.username
initial[config.FIRST_NAME] = self.request.user.first_name
initial[config.LAST_NAME] = self.request.user.last_name
return initial
def get_form_kwargs(self):
kwargs = {'initial': self.get_initial()}
return kwargs
def get_context_data(self, **kwargs): #GET OBJECT ACTS AFTER THAN GET_OBJECT --> EXAMPLE OF GET_CONTEXT_DATA, I DIDN'T NEED THIS
context = super(DetailUserInfoView, self).get_context_data(**kwargs)
context['username'] = self.request.user.username
return context
Here the form.
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = CustomUser.CustomUser
fields = ('email', 'password', 'first_name', 'last_name', 'username', 'userType')
And finally an extract of template.
<div id="infoMayOverride">
<form class="getOverridedValues" method="post">
{% csrf_token %}
<div id="usernameData">
<label>{{ form.username.label_tag }}</label> <!--MODEL ON CREATEUSERVIEW IS CUSTOMUSER, AND NOW I NEED TO USE THIS FIELDS AND INHERITED FIELDS FROM USER CLASS-->
<input type="text" id="usernameInput" value="{{ form.username }}">
</div>
<div id="firstNameData">
<label>{{ form.first_name.label_tag }}</label>
<input type="text" id="firstNameInput" value="{{ form.first_name }}">
</div>
<div id="lastNameData">
<label>{{ form.last_name.label_tag }}</label>
<input type="text" id="lastNameInput" value="{{ form.last_name }}">
</div>
<div id="divBtnChangeProfile">
<input type="submit" class="btnChangeProfile" value="Atualizar Profile">
</div>
</form>
</div>
I'd appreciate it if you could help me. I am new to the Django environment, and have tried many approaches, and I have not yet been able to solve this problem.
--------------------------- Update ------------------------------------
Now, i can get initial values. But to view them i need to write on input form: form.username.initial, and with this i can't after submit form to update user values.
Anyone knows how to solve this type of problem??
I finally got this problem solved. I will make my solution available, since it can help other people.
I had to make some changes to the code I provided behind.
Below is the code of view.
class DetailUserInfoView(LoginRequiredMixin, UpdateView):
model = CustomUser.CustomUser
template_name = 'users/InfoUser.html'
login_url = settings.LOGOUT_REDIRECT_URL
context_object_name = 'user'
form_class = CustomUserChangeForm
def get_object(self, queryset=None):
return self.request.user
def get_form_kwargs(self):
kwargs = super(DetailUserInfoView, self).get_form_kwargs()
u = self.request.user
kwargs['username_initial'] = u.username
kwargs['fName_initial'] = u.first_name
kwargs['lName_initial'] = u.last_name
return kwargs
def get_context_data(self, **kwargs): #GET OBJECT ACTS AFTER THAN GET_OBJECT --> EXAMPLE OF GET_CONTEXT_DATA, I DIDN'T NEED THIS
context = super(DetailUserInfoView, self).get_context_data(**kwargs)
form_class = self.get_form_class()
form = self.get_form(form_class)
context['form'] = form
return context
My form (with init function, to set initial values on form, and is called by def get_form_kwargs(self)).
class CustomUserChangeForm(UserChangeForm):
def __init__(self, *args, **kwargs):
username_initial = kwargs.pop('username_initial', None)
fName_initial = kwargs.pop('fName_initial', None)
lName_initial = kwargs.pop('lName_initial', None)
super(CustomUserChangeForm, self).__init__(*args, **kwargs)
self.fields['username'].initial = username_initial
self.fields['first_name'].initial = fName_initial
self.fields['last_name'].initial = lName_initial
class Meta(UserChangeForm.Meta):
model = CustomUser.CustomUser
fields = ('username', 'email', 'first_name', 'last_name')
And finnaly, in template I replace the tag input with {{ form.username }}.
I hope it can help someone who has the same problem.
I doing a form of filtering by the foreignkey field with two search conditions: OR and AND and multiple choices.
forms.py
class EmployeeSkillFilter(forms.ModelForm):
skills = forms.ModelMultipleChoiceField(queryset=Technology.objects.all(), )
class Meta:
model = Employee
fields = ['skills']
templates.py
<form method="get" enctype="multipart/form-data">
{% csrf_token %}
<input type="checkbox" name="and" value="AND"> Choice and<br>
<input type="checkbox" name="or" value="OR"> Choice OR<br>
{{ skill_filter }}
<button type="submit" class="btn btn-info" type="button">Go!</button>
</form>
views.py
class AccountList(AuthorizedMixin, ListView):
model = Employee
template_name = 'employee_list.html'
def get_queryset(self, *args, **kwargs):
condition_and = self.request.GET.get('and', None)
condition_or = self.request.GET.get('or', None)
skill = self.request.GET.get('skills', None)
if condition_and and skill:
object_list = self.model.objects.filter(skills__name_id=skill) ??????
if condition_or and tech:
object_list = self.model.objects.filter(
Q(skills__name_id=skill) |
Q(skills__name_id=skill)
) ?????
else:
object_list = self.model.objects.all()
My urls looks like
localhost://....or=OR&skills=5&skills=4&skills=3
The problem is that when I select multiple objects in a form, I don't know how to pass them all to the condition
skills__name_id=skill
Use the __in lookup [Django-doc] lookup, and in case of and logic, count the number of matches:
from django.db.models import Count
class AccountList(AuthorizedMixin, ListView):
model = Employee
template_name = 'employee_list.html'
def get_queryset(self, *args, **kwargs):
condition_and = self.request.GET.get('and', None)
condition_or = self.request.GET.get('and', None)
skills = self.request.GET.getlist('skills')
if condition_and:
object_list = self.model.objects.filter(
skills__in=skills
).annotate(
nskills=Count('skills')
).filter(
nskills=len(skills)
)
elif condition_or:
object_list = self.model.objects.filter(
skills__in=skills
).distinct()
else:
object_list = self.model.objects.all()
I use Django class-based views. And I have two classes: one for displaying form in the page, and second for handling it:
views.py:
class CommentFormView(CreateView):
form_class = AddCommentForm
model = Comment
success_url = '/'
def form_valid(self, form):
form.instance.author = self.request.user
form.instance.post = ????
return super(CommentFormView, self).form_valid(form)
class BlogFullPostView(BlogBaseView, DetailView):
model = Post
template_name = 'full_post.html'
pk_url_kwarg = 'post_id'
context_object_name = 'post'
def get_context_data(self, **kwargs):
context = super(BlogFullPostView, self).get_context_data(**kwargs)
context['form'] = AddCommentForm(initial={'post': self.object})
return context
full_post.html:
<form action="/addcomment/" method="post" >
{% csrf_token %}
{{ form }}
<button type="submit" >Add comment</button>
</form>
urls:
url(r'^blog/post/(?P<post_id>\d+)/$', BlogFullPostView.as_view()),
url(r'^addcomment/$', CommentFormView.as_view()),
And in def form_valid I need to fill field post, which value I have passed in BlogFullPostView in get_context_data: initial={'post': self.object}
But how can I get it in CommentFormView?
I have solved it in this way: Firstly, I try to use get_initial method. But I it does not return anything. So, I decide to hide auto filled field post - I make it as hidden field. So, then CreateView easily can create Comment object:
widgets = {
'content': forms.Textarea(),
'post': forms.HiddenInput(),
}
I want to create a listview with various optional filters. My url should be look like this:
shop/category_6/?manufacturer_id=3
And it works well when I put this url just in to the browser form. But when i try to add this option to a template it gives me NoReverseMatch. My template:
{% for manufacturer in manufacturer_list %}
<p>{{manufacturer.1}}</p>
{% endfor %}
It is my view:
class ItemListView(ListView):
model = Item
context_object_name = 'item_list'
template_name = 'shop/item_list.html'
def get_queryset(self, **kwargs):
full_item_list=Item.objects.all()
queryset=full_item_list.filter(category__id=int(self.kwargs['category_id']))
manufacturer_id = self.request.GET.get('manufacturer_id')
if manufacturer_id:
queryset=queryset.filter(manufacturer__id=int(manufacturer_id))
return queryset
def get_context_data(self, **kwargs):
context = super(ItemListView, self).get_context_data(**kwargs)
context['category']=get_object_or_404(Category, pk=self.kwargs['category_id'])
context['manufacturer_list'] = self.get_queryset(**kwargs).values_list('manufacturer__id', 'manufacturer__name').distinct().order_by('manufacturer__name')
return context
What is my mistake?
You didn't configure GET params... May be shop/category_6/?manufacturer_id=3
{{manufacturer.1 }}