Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/utils/deprecation.py", line 138, in __call__
response = self.process_response(request, response)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/middleware/clickjacking.py", line 27, in process_response
if response.get("X-Frame-Options") is not None:
AttributeError: 'int' object has no attribute 'get'
Here is my code,
#views.py
class BookList(generic.View):
model = Book
def get(self, request, *args, **kwargs):
books = Book.objects.all()
if request.GET.get('Add') == 'Add':
query = request.GET.get('hidden-book')
book = Book.objects.filter(pk=query).update(moved=True)
return book
context = {'books': books}
return render(request, 'main.html', context)
#main.html
<form method="GET" action="">
<input type="hidden" name="hidden-book" value="{{ book.id }}/>
<input type="submit" name="Add" value="Add"/>
</form>
#models.py
class Book(models.Model):
moved = models.BooleanField(default=False)
When the user presses the 'Add' input button, it should change the moved attribute in book to True. For background, I have an application that has a list of books, each with their own add button, that upon clicking an add button, the book is added to another list of books. My code works, but when I click the add button an AttributeError at / 'int' object has no attribute 'get' is raised. When I go back to 127.0.0.1:8000/, the book has been moved from the first to second list.
Since I don't know what's causing the error, I assumed it was the query = request.GET.get('hidden-book') line because it's getting an id which is an int. I tried putting this in a try/except block, but nothing changed. I also tried to change {{ book.id }} to {{ book }} to get a string instead, but it also didn't work.
the root cause is
return book
get() needs to return a http response like
return render(...)
some lines below, not a query object
this should do it:
class BookList(generic.View):
model = Book
def get(self, request, *args, **kwargs):
if request.GET.get('Add') == 'Add':
query = request.GET.get('hidden-book')
book = Book.objects.filter(pk=query).update(moved=True)
books = Book.objects.all()
context = {'books': books}
return render(request, 'main.html', context)
Related
When I render the empty form it is not attaching any media to it. i.e. the CKEditor is not displayed. The element looks like it is missing the css/js - it's like it doesn't get set up properly.
Note : the other sections are displayed correctly.
Where to start? Problem with Django's Empty Form method? Problem with CKEditor? Me :)
<div class="container">
<button type ="button" class="btn-info btn-lg" id="add_section">Add Section</button>
{{form.media }}
{{form|crispy }}
{{sections.media}}
<div>
{{sections.empty_form}}
</div>
<div id = 'section_management'> {{ sections.management_form }} </div>
{% for section in sections %}
{{ section|crispy }}
{% endfor %}
<button class="btn btn-info ml-2" type="submit">Update</button>
Cancel
</div>
Here's my Forms
class SectionForm(forms.ModelForm):
content = RichTextFormField()
class Meta:
model = Section
fields = ('content',)
empty_permitted=True
def __init__(self, *args, **kwargs):
print('section form called')
super().__init__(*args, **kwargs)
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ('title','category','span')
def __init__(self, *args, **kwargs):
self.is_superuser = kwargs.pop('is_superuser', None)
super().__init__(*args, **kwargs)
if self.is_superuser == False:
self.fields.pop("span")
view code
class ArticleUpdateView(LoginRequiredMixin,UserPassesTestMixin,UpdateView):
template_name = 'articles/ArticleUpdate.html'
form_class = ArticleForm
model = Article
SectionFormSet = inlineformset_factory(Article, Section, form=SectionForm, extra=0, can_delete=False, fields=('content',))
#if i always pass back at least 1 extra section form, I can grab the html for it in Jquery */
#if i do not pass back extra=0 how would i get the html in jquery for the extra form?
def test_func(self):
article = self.get_object()
if self.request.user == article.author or self.request.user.is_superuser :
return True
else:
return False
def get_context_data(self, **kwargs):
print('get context data called update view')
'''
section_form
'''
context = super().get_context_data(**kwargs)
if self.request.POST:
context['sections'] = self.SectionFormSet(self.request.POST,instance=self.object)
else:
context['sections'] = self.SectionFormSet(instance=self.object)
return context
def get_section_form(self): #we know we can access this in the template
return SectionForm()
def save_sections(self):
print('save sections called update view')
try:
context = self.get_context_data()
section_form = context['sections']
if section_form.is_valid():
# section_form.instance = self.object #if im passing instance in the factory, do I need it here to?
section_form.save()
except Exception as e:
print('failed to save section: ' + str(e))
def form_valid(self, form):
print('form valid called update view')
form.instance.author = self.request.user
response = super().form_valid(form) #save article form
self.save_sections()
return response
def get_success_url(self):
return reverse_lazy('index')
Basically, what I've done so far to overcome this problem is by accessing the form directly from the template, bypassing the inlineFormSet to get an empty form....(hope that makes sense).
I go directly to the view :
{{view.get_section_form}}
with this method in the view
def get_section_form(self): #we know we can access this in the template
return SectionForm()
I have subsequently found out I can do this in the template as well :
{{sections.media}}
{{sections.form}}
The above also passes an empty form - with the media filled in- as long as you pass the model form into the factory to start of with.
These are work-arounds for me currently, but would appreciate a proper answer as to why empty_form doesn't work properly.
My further investigation into this was basically comparing what is returned via accessing the formset to return an empty form, or using the modelForm directly.
Django docs :
empty_form¶
BaseFormSet provides an additional attribute empty_form which returns a form instance with a prefix of __prefix__ for easier use in dynamic forms with JavaScript.
If you replace prefix on the generated html -- everything works. No idea why. You can replace it with anything, i.e. prefix1
at which point CKEditor starts to display the formset correctly.
Hey guys I am trying to send a follow request through the django notifications and the person at the other end will be either accepting or rejecting the request. But I have a problem that when the person at the other end accepts the request, this error is showing
ValueError at /accounts/users/2/accept_follower/
The view accounts.views.accept_follow_request didn't return an HttpResponse object. It returned None instead.
and he is following himself. I tried printing out the current_user and user in send_follow_request function and it is showing the 2 users correctly, but in the accept_follow_request function, both the users are same! How to change that?
This is the code I have now.
def send_follow_request(request, id):
current_user = request.user
user = Account.objects.get(id=id)
notify.send(request.user, recipient=user, verb='has sent you a follow request', target=user)
return redirect('posts:userprofile', user.username)
def accept_follow_request(request, id):
current_user = request.user
user = Account.objects.get(id=id)
contact, created = Contact.objects.get_or_create(user_from=request.user, user_to=user, follow_status='AC')
if user != request.user:
create_action(request.user, 'started following', user)
notify.send(request.user, recipient=user, verb='started following you')
return redirect('all_user_notifications')
This is the notification view
class AllNotificationsList(LoginRequiredMixin, NotificationViewList):
def get_queryset(self, *args, **kwargs):
if get_config()['SOFT_DELETE']:
qset = self.request.user.notifications.active()
else:
qset = self.request.user.notifications.all()
return qset
Can anyone tell me where the problem is?
This is the form I have in the notificaion template:
{% if notice.target == user %}
<form action="{% url 'accept_follow_request' user.id %}">
<button class="btn-sm btn-success" type="submit">Accept</button>
Cancel
</form>
This is the model I have
class Contact(models.Model):
user_from = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='rel_from_set', on_delete=models.CASCADE)
user_to = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='rel_to_set', on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True, db_index=True)
follow_status = models.CharField(choices=FOLLOW_STATUS, max_length=10)
#USER_FROM IS THE ONE WHO IS FOLLOWING AND USER_TO IS ONE BEING FOLLOWED
class Meta:
ordering = ('-created',)
def __str__(self):
return f'{self.user_from} follows {self.user_to}'
following = models.ManyToManyField('self', through=Contact, related_name='followers', symmetrical=False)
#adding the above field to User Model class
user_model = get_user_model()
user_model.add_to_class('following', models.ManyToManyField('self', through=Contact, related_name='followers',
symmetrical=False))
url:
path('<int:id>/accept_follower/', views.accept_follow_request, name='accept_follow_request'),
Traceback:
C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\exception.py in inner
response = get_response(request) …
▼ Local vars
Variable Value
exc
ValueError("The view accounts.views.accept_follow_request didn't return an HttpResponse object. It returned None instead.")
get_response
<bound method BaseHandler._get_response of <django.core.handlers.wsgi.WSGIHandler object at 0x039FC6E8>>
request
<WSGIRequest: GET '/accounts/users/2/accept_follower/'>
C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py in _get_response
raise ValueError( …
▼ Local vars
Variable Value
callback
<function accept_follow_request at 0x04D19E80>
callback_args
()
callback_kwargs
{'id': 2}
middleware_method
<bound method CsrfViewMiddleware.process_view of <django.middleware.csrf.CsrfViewMiddleware object at 0x03A2B3D0>>
request
<WSGIRequest: GET '/accounts/users/2/accept_follower/'>
resolver
<URLResolver 'socialwebsite.urls' (None:None) '^/'>
resolver_match
ResolverMatch(func=accounts.views.accept_follow_request, args=(), kwargs={'id': 2}, url_name=accept_follow_request, app_names=[], namespaces=[], route=accounts/users/<int:id>/accept_follower/)
response
None
self
<django.core.handlers.wsgi.WSGIHandler object at 0x039FC6E8>
view_name
'accept_follow_request'
wrapped_callback
<function accept_follow_request at 0x04D19E80>
Thanks!
It does seem that user == request.user as in that case you are not returning any response ( you have if but not else)
I would guess that constructed URL for accept_follower has wrong id in URL ( notified user instead of id of user that requested follow)
This would be reason you are following yourself
contact, created = Contact.objects.get_or_create(user_from=request.user, user_to=user, follow_status='AC')
so something in a line of following ( instead user.id (its the target) send id of sender ):
{% if notice.target == user %}
<form action="{% url 'accept_follow_request' notice.actor.id %}">
<button class="btn-sm btn-success" type="submit">Accept</button>
Cancel
</form>
I've been struggling with class views all day after starting on them yesterday. My issue is constantly getting 'str' object has no attribute 'visible_fields', so the 'form' item below is not really a form:
template-
<form action="" method="post">
{% csrf_token %}
{{form|bootstrap}}
<input type="submit" name="submit" value="Add new article"/>
</form>
view-
class ArticleCreateView(CreateView):
model = Article
template_name = 'index/add_article.html'
form_class = ArticleForm
def post(self, request, *args, **kwargs):
article_form = self.get_form()
if article_form.is_valid():
article = article_form.save(commit=False)
title = article_form.cleaned_data['title']
url = article_form.cleaned_data['url']
title = process_title(url)
article.title = title
article.save()
return redirect("index:article_list")
else:
form = ArticleForm()
print type(form)
print dir(self)
return render(request, 'index/add_article.html')
The worst part is printing type(form) shows it is <class 'index.forms.ArticleForm'>. I'm trying to just have it redirect to the list view if the form saved, and replay the form with the error (You already have an article with that URL) if the form is bad. I heard class views are easier to work with and huge projects I've read through use them, but they really seem worse than the old views. I assume that's because I'm not using them well
Every example I've seen has a template getting a "form" somehow, like
class RangeCreateView(CreateView):
model = Range
template_name = 'dashboard/ranges/range_form.html'
form_class = RangeForm
def get_success_url(self):
if 'action' in self.request.POST:
return reverse('dashboard:range-products',
kwargs={'pk': self.object.id})
else:
msg = render_to_string(
'dashboard/ranges/messages/range_saved.html',
{'range': self.object})
messages.success(self.request, msg, extra_tags='safe noicon')
return reverse('dashboard:range-list')
def get_context_data(self, **kwargs):
ctx = super(RangeCreateView, self).get_context_data(**kwargs)
ctx['title'] = _("Create range")
return ctx
then like magic in range_form.html:
{% include "dashboard/partials/form_fields.html" with form=form %}
My issue here is I need to process the title of the form, with
def process_title(url):
def _search_for_title(url):
try:
r = requests.get(url)
content = r.text
t = html.document_fromstring(content)
return t.find(".//title").text
except IOError:
return None
title = _search_for_title(url)
return title or 'None'
This kind of ruins the purpose of a class based view. It seems I should be processing the title by overriding 'clean' in the form itself?
Otherwise, how can I make this view pass a form object, render it in the template, and just re-render the template if the form didn't pass?
And how can I access the form in the template?
Thank you
You do it by following the example view, rather than overriding post instead as you are doing.
In your case, simply displaying and processing a form is the default behaviour of a CreateView. So there is no need to override any methods at all. Your view should just be:
class ArticleCreateView(CreateView):
model = Article
template_name = 'index/add_article.html'
form_class = ArticleForm
In a blog-ish part of my django app, editing an existing entry results in creating a new entry. It should modify the existing entry.
I have a simple model:
class BlogEntry(models.Model):
...
slug = models.SlugField(unique=True)
and a simple form for editing it:
class BlogEntryForm(forms.ModelForm):
...
slug = forms.CharField(required=False, widget=forms.HiddenInput())
class Meta:
model = BlogEntry
fields = (..., 'slug')
and the view, somewhat simplified, is also straight-forward:
class BlogEditView(View):
#method_decorator(login_required)
def get(self, request, slug=None):
context = {
'user': request.user,
}
if slug is None:
print('Creating new entry.')
context['entry'] = BlogEntryForm()
context['entry'].publication_date = datetime.datetime.now()
return render(request, 'blog/edit.html', context)
print('Using existing entry.')
entry = get_object_or_404(BlogEntry, slug=slug)
context['entry'] = BlogEntryForm(instance=entry)
return render(request, 'blog/edit.html', context)
#method_decorator(login_required)
def post(self, request):
blog_entry_form = BlogEntryForm(request.POST)
if blog_entry_form.is_valid():
blog_entry = blog_entry_form.save(commit=False)
if blog_entry.slug is None or blog_entry.slug == '':
print('New entry, slug is empty.')
blog_entry.creation_date = datetime.datetime.now()
blog_entry.slug = slugify(blog_entry.title) + '_' + hex(random.randint(0, 1e10))
blog_entry.author = request.user
blog_entry.save()
return redirect(reverse('blog/article', args=[blog_entry.slug]))
...
In get(), I confirm with the print's that I am taking the correct branch. If the entry exists, I set entry with the instance. In post(), however, I always take the new entry branch.
The layout has the typical hidden element loop.
{% for hidden in form.hidden_fields %}
{{ hidden }} hidden
{% endfor %}
though, suspiciously, when I look at the served html, I don't see the slug entry, so it's no surprise that it's not getting passed through.
Anyone see what I'm missing?
You should add the slug argument to the post() method as well. This will allow you to get the blog entry to edit from the database and pass this entry to the form as an instance argument:
#method_decorator(login_required)
def post(self, request, slug=None):
blog_entry = BlogEntry.objects.filter(slug=slug).first()
blog_entry_form = BlogEntryForm(request.POST, instance=blog_entry)
...
UPDATE: To pass the slug argument to the post() method you should use the empty action attribute of the <form> tag:
<form action="" method="POST">
In this case the form will be submitted to the url from which it was loaded. So the slug argument for the POST request will be the same as for the GET.
Can anyone help me with this. I don't understand this error
IndexError at /customerList/
tuple index out of range
and it came from this code
self.Customer = get_object_or_404(customer, name__iexact=self.args[0])
I want to be able to do ListView some of the fields from two forms that is from customerForm (F_NAME, L_NAME) and buildingForm (B_USE, B_TYPE). Any help is very much is very very much appreciated. Thank u.
Traceback:
File "c:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "c:\Python27\lib\site-packages\django\views\generic\base.py" in view
48. return self.dispatch(request, *args, **kwargs)
File "c:\Python27\lib\site-packages\django\views\generic\base.py" in dispatch
69. return handler(request, *args, **kwargs)
File "c:\Python27\lib\site-packages\django\views\generic\list.py" in get
114. self.object_list = self.get_queryset()
File "f:\iqgit\amon\amonsolution\solution\views.py" in get_queryset
59. self.Customer = get_object_or_404(customer, name__iexact=self.args[0])
Exception Type: IndexError at /customerList/
Exception Value: tuple index out of range
views.py
class customerListView(ListView):
template_name = "customerList.html",
model = customer
context_object_name = "customer_list"
def get_queryset(self):
self.Customer = get_object_or_404(customer, name__iexact=self.args[0])
return building.objects.filter(Customer=self.Customer)
def get_context_data(self, **kwargs):
context = super(customerListView, self).get_context_data(**kwargs)
context['building_list'] = building.objects.all()
return context
forms.py
class customerForm(forms.ModelForm):
F_NAME = forms.CharField(widget=forms.TextInput()
L_NAME = forms.CharField(widget=forms.TextInput()
EMAIL = forms.CharField(widget=forms.TextInput()
ADD = forms.CharField(widget=forms.TextInput()
class Meta:
model = customer
class buildingForm(forms.ModelForm):
CUSTOMER = forms.CharField(widget=forms.TextInput()
B_FLOORSPACE = forms.CharField(widget=forms.TextInput()
B_YEAR = forms.CharField(widget=forms.TextInput()
B_USE = forms.ChoiceField(widget=forms.RadioSelect(), choices=c.Use)
B_TYPE = forms.ChoiceField(widget=forms.RadioSelect(), choices=c.Type)
class Meta:
model = building
exclude = ('CUSTOMER',)
urls.py
url(r'^customerList/',customerListView.as_view(), name= "customerList_view"),
customerList.html
...some of code...
{% for customer in customer_list %}
<tr class = {% cycle "row_even" "row_odd" %}>
<td>{{ customer.id }}</td>
<td class ="name"> {{ customer.F_NAME }} {{ customer.L_NAME }}</td>
<td class ="b_use"> {{ building.B_USE }}{{ building.B_TYPE }}</td>
...some of code...
You are trying to call a positional argument (self.args[0]) passed from the URL conf but you haven't added any positional arguments to your actual url. If you look at how a request is processed, you will notice that:
4 . Once one of the [url] regexes matches, Django imports and calls the given view, which is a simple Python function. The view gets passed an HttpRequest as its first argument and any values captured in the regex as remaining arguments.
You aren't passing any arguments (neither positional or named) to your view so there is nothing in self.args or self.kwargs. You need to change your URL to something like:
url(r'^customerList/(\w+)/',customerListView.as_view(), name= "customerList_view"),
or ideally make use of named arguments such as:
url(r'^customerList/(?P<name>\w+)/',customerListView.as_view(), name= "customerList_view"),
so that you can instead use self.kwargs.get("name", None)