Field 'id' expected a number but got 'create'. Request Method: - django-forms

I create a form where users can create a team. At first, the creation is working. But, after I worked out the team-detail-view I cannot create a team again.
Here is the detail-view:
def team(request, id, **kwargs):
team = get_object_or_404(Team, id=id)
if request.method == "POST":
team.instance.team = team
return redirect(reverse('team-detail', kwargs={
'id': team.id
}))
context = {
'team': team,
}
return render(request, 'club.html', context)
And the now the create-view:
def team_create_view(request, id):
title = 'Create'
form = TeamCreateForm(request.POST or None, request.FILES or None)
coach = get_coach(request.user)
if request.method == 'POST':
if form.is_valid():
new_team = form.save()
return redirect(reverse("club", kwargs={'id': form.instance.id }))
else:
form = TeamCreateForm()
context = {'title': title,'form': form}
return render(request, "team_create.html", context)
url.py
path('team/<id>/', team, name='team-detail'),
path('team/create/', team_create_view, name='team-create'),

Related

How to generate a schema for a custom pagination in django rfw with drf-spectacular?

I am struggling to properly generate the schema for my custom pagination in django rest framework.
I am using drf-spectacular for the schema generation. My custom pagination includes a total-pages field which does not come with djangos PageNumberPagination.
The response is correctly serialized and returned and includes the total-pages, but the schema in my swagger docs does not include the field.
Here is my code:
pagination.py
from rest_framework import pagination
from rest_framework.response import Response
class CustomPagination(pagination.PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
page_query_param = 'p'
def get_paginated_response(self, data):
return Response({
'page_size': self.page_size,
'total_objects': self.page.paginator.count,
'total_pages': self.page.paginator.num_pages,
'current_page_number': self.page.number,
'next': self.get_next_link(),
'previous': self.get_previous_link(),
'results': data,
})
Here is my view:
views.py
#extend_schema_view(
get=extend_schema(
parameters=[OpenApiParameter("q", OpenApiTypes.STR, OpenApiParameter.QUERY),],
request=TestStandardSearchSerializer,
responses=TestStandardSerializer
)
)
class TestStandardSearchView(ListAPIView):
serializer_class = TestStandardSearchSerializer
queryset = TestStandard.objects.all()
pagination_class = CustomPagination
def get(self, request, *args, **kwargs):
query = self.request.query_params.get('q')
queryset = SearchQuerySet().all().filter(content=query).order_by('acronym')
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
def get_serializer_class(self):
if self.request.method == 'GET':
return TestStandardSearchSerializer
The response schema from my swagger doc is the following:
PaginatedTestStandardList
{
count integer example: 123
next string($uri) nullable: true example: http://api.example.org/accounts/?p=4
previous string($uri) nullable: true example: http://api.example.org/accounts/?p=2
results [TestStandard{...}]
}
The standard django pagination is correctly ínserted in the schema, but not my custom pagination response.
What I expected/wanted is to have my customized pagination response correctly integrated with the total-pages field on the same level as 'count', 'next' and 'previous'.
What I tried...
I have a working solution with drf_yasg using the PaginatorInspector providing a custom schema. But this is not available in drf-spectacular.
I also used inline_serializer with a custom response in #extend_schema_view such as:
responses={
200: inline_serializer(
name='PaginatedTestStandardSearchResponse',
fields={
'total-pages': serializers.IntegerField(),
'results': TestStandardSearchSerializer()
},
This resulted in a schema where total-pages is nested within results.
I am using:
drf-spectacular 0.21.2
Django 3.2.12
django-rest-swagger 2.2.0
djangorestframework 3.12.4
Any help is appreciated. I just recently started with django rfw and openapi schema generation. Sorry if I had missed something obvious here.
You need to overwrite the method get_paginated_response_schema in your CustomPagination. For the reference about how to compose it, you can see it on file pagination.py inside rest_framework package.
If you want to know how does that works, you could find it inside drf-spectacular package on file openapi.py, method _get_response_for_code. I hope that solve your problem.
I ended up with overwriting get_paginated_response().
This finally resolved my issue. Now the correct pagination parameters are shown in the swagger documentation.
This is my custom paginator:
from rest_framework import pagination
from rest_framework.response import Response
class CustomPagination(pagination.PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
page_query_param = 'p'
def get_paginated_response(self, data):
print(data)
print()
return Response({
'count': self.page.paginator.count,
'next': self.get_next_link(),
'previous': self.get_previous_link(),
'page_size': self.page_size,
'total_objects': self.page.paginator.count,
'total_pages': self.page.paginator.num_pages,
'current_page_number': self.page.number,
'results': data,
})
def get_paginated_response_schema(self, schema):
return {
'type': 'object',
'properties': {
'count': {
'type': 'integer',
'example': 123,
},
'next': {
'type': 'string',
'nullable': True,
'format': 'uri',
'example': 'http://api.example.org/accounts/?
{page_query_param}=4'.format(
page_query_param=self.page_query_param)
},
'previous': {
'type': 'string',
'nullable': True,
'format': 'uri',
'example': 'http://api.example.org/accounts/?
{page_query_param}=2'.format(
page_query_param=self.page_query_param)
},
'page_size' : {
'type': 'integer',
'example': 123,
},
'total_pages': {
'type': 'integer',
'example': 123,
},
'current_page_number': {
'type': 'integer',
'example': 123,
},
'results': schema,
},
}

How to pass 2 variables using json dumps to an ajax function?

I want to pass two variable: scenario_name and scenario_id from my view to my ajax function in the html code.
So basically in the database, each Organization can have multiple scenarios. The organization and scenario models have 2 fields each: an id field and a name field.
And my other doubt is, once I pass it to ajax, how do I access the variables passed?
my views.py
from django.shortcuts import render, redirect
from Organization.models import Organization
from django.http import HttpResponse
from Scenario.models import Scenario
import json
from django.core import serializers
def alertindex(request):
return render(request, 'alertindex.html', {
'Organization': Organization.objects.all(),
})
def get_scenario(request):
org_id = request.GET.get('org_id')
organization = Organization.objects.get(pk=int(org_id))
scenario = organization.scenario_set.all()
scenarios = serializers.serialize("json", scenario)
return scenarios
urls.py
from . import views
from django.conf.urls import url
urlpatterns = [
# Add alert url
url(r'^$', views.alertindex, name='alertindex'),
# Bind data in scenario drop down
url(r'^/Scenario$', views.get_scenario, name='Get_Scenario'),
]
my ajax function
var orgID = $(this).val();
var scenarios = '{{ scenarios }}'
$.ajax({
type: "GET",
url: "{% url 'Get_Scenario' %}",
data: { org_id: orgID},
success: function () {
var udata = "";
for (var i = 0; i < scenarios.length; i++) {
udata = udata + "<option value='"+ scenarios[i].scenario_id + "'>" + scenarios[i].scenario_name + "</option>"
$("#txtScenario").append(udata);
}
},
});
The url Get_Scenario links me to my view having the function get_scenario.
The error that I am facing is " str' object has no attribute 'get' "
Traceback:
File "/Users/anirudhchakravarthy/anaconda3/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
File "/Users/anirudhchakravarthy/anaconda3/lib/python3.6/site-packages/django/utils/deprecation.py", line 97, in call
response = self.process_response(request, response)
File "/Users/anirudhchakravarthy/anaconda3/lib/python3.6/site-packages/django/middleware/clickjacking.py", line 26, in process_response
if response.get('X-Frame-Options') is not None:
AttributeError: 'str' object has no attribute 'get'
Any help will be greatly appreciated.
You can use JsonResponse. Here's sample code.
(It's better to check try/exception and send 404 when not found object)
from django.http import JsonResponse
def get_scenario(request):
org_id = request.GET.get('org_id')
# you can do your own validation
try:
organization = Organization.objects.get(pk=int(org_id))
scenario = organization.scenario_set.all()
scenarios = serializers.serialize("json", scenario)
except ObjectDoesNotExist:
data = {
'result': 'fail',
}
return JsonResponse(status=404, data)
data = {
"scenarios": scenarios,
# add more data you want
}
return JsonResponse(data)
For more information about JsonResponse, just check here

Pass date year month slug in html template ajax post request

I have a blogost, comment and like model. The like model has a genericforeignkey field so I can link likes to blogposts and comments.
The view is working correctly however I am having trouble passing the parameters in the ajax request
urls.py
urlpatterns =[
url(r'^$',views.home, name = 'home'),
url(r'^blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/(?P<day>[0-9]{1,2})/(?P<slug>[-\w]+)/$',
views.blog,
name = 'view_blogpost_with_pk'),
url(r'^blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/(?P<day>[0-9]{1,2})/(?P<slug>[-\w]+)/ajax/like/$',VotesView.as_view(model=BlogPost, vote_type=Like.LIKE),
name='blog_like'),
url(r'^blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/(?P<day>[0-9]{1,2})/(?P<slug>[-\w]+)/ajax/dislike/$', VotesView.as_view(model=BlogPost, vote_type=Like.DISLIKE),
name='blog_dislike'),
]
blog.html
<ul>
<li data-id="{{ like_obj.id }}" data-type="blog" data-action="like" title="Like">
<span class="glyphicon glyphicon-thumbs-up"></span>
<span data-count="like">{{ like_obj.votes.likes.count }}</span>
</li>
<li data-id="{{ like_obj.id }}" data-type="blog" data-action="dislike" title="Dislike">
<span class="glyphicon glyphicon-thumbs-down"></span>
<span data-count="dislike">{{ like_obj.votes.dislikes.count }}</span>
</li>
</ul>
And the javascript. Just including dislike, like is very similar
<script>
function dislike()
{
var dislike = $(this);
var type = dislike.data('type');
var pk = dislike.data('id');
var action = dislike.data('action');
var like = dislike.prev();
$.ajax({
url : '/home/blog/2017/10/1/git/ajax/dislike/',
method : 'POST',
data : { 'obj' : pk },
success : function (json) {
dislike.find("[data-count='dislike']").text(json.dislike_count);
like.find("[data-count='like']").text(json.like_count);
}
});
return false;
}
<script>
$(function() {
$('[data-action="like"]').click(like);
$('[data-action="dislike"]').click(dislike);
});
</script>
So at the moment this working great except when i replace url with
url: '{% url "home:blog_dislike" year=obj.year month=obj.month day=obj.date
slug=obj.slug %}'
I get
django.urls.exceptions.NoReverseMatch: Reverse for 'blog_like' with keyword
arguments '{'year': '', 'month': '', 'day': '', 'slug': ''}' not found. 1
pattern(s) tried: ['home/blog/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/(?
P<day>[0-9]{1,2})/(?P<slug>[-\\w]+)/ajax/like/$']
views.py
def blog(request,year,month,day,slug):
if request.method == 'GET':
blogpost = BlogPost.objects.get(date__year=year, date__month=month, date__day=day,slug=slug)
form = BlogPostForm()
comments = Comment.objects.filter(comment_body_id=blogpost).order_by('-date') #Link comments to blogpost // comment_body is foreignkey to blogpost model
c = comments.count()
args = {'bpost': blogpost,'form':form,'comments':comments,'c':c}
return render(request,'home/blog.html',args)
if request.method == 'POST':
blogpost = BlogPost.objects.get(date__year=year, date__month=month, date__day=day,slug=slug)
form = BlogPostForm(request.POST)
if form.is_valid():
comment = form.save(commit = False)
comment.comment_body = blogpost
comment.save()
text = form.cleaned_data['comment']
form = BlogPostForm()
return redirect(request.build_absolute_uri())
else:
form = BlogPostForm()
args = {'form':form,'text':text}
return render(request, 'home/blog.html', args)
class VotesView(View):
model = None
vote_type = None
def post(self,request, year, month, day, slug):
obj = self.model.objects.get(date__year=year, date__month=month, date__day=day,slug=slug)
try:
x = Like.objects.get(content_type=ContentType.objects.get_for_model(obj), object_id=obj.id, user=request.user)
if x.vote is not self.vote_type:
x.vote = self.vote_type
x.save(update_fields = ['vote'])
result = True
else:
x.delete()
result = False
except Like.DoesNotExist:
obj.votes.create(user=request.user, vote=self.vote_type)
result = True
return HttpResponse(
json.dumps({
"result": result,
"like_count": obj.votes.likes().count(),
"dislike_count": obj.votes.dislikes().count(),
"sum_rating": obj.votes.sum_rating()
}),
content_type="application/json"
)
Thank you for any help

Django: TypeError: 'Like' object is not iterable (Ajax request)

I am not getting a clear picture regarding the Model (Like) object is not iterable.
Error
liked, created = Like.objects.create(question=create_id)
TypeError: 'Like' object is not iterable
model.py
class Question(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length= 200)
description = models.TextField()
location = models.CharField(max_length=150)
tags = TaggableManager()
time = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.title
class Like(models.Model):
user = models.ManyToManyField(User, related_name='likes')
question = models.ForeignKey(Question)
date = models.DateTimeField(auto_now_add=True)
likecount = models.IntegerField(default=0)
urls.py
url(r'^like/$', 'apps.question.views.like', name='like'),
views.py
def like(request):
vars = {}
if request.method == 'POST':
user = request.user
tutorial_id = request.POST.get('tutorial_id', None)
create_id = get_object_or_404(Question, id=tutorial_id)
liked, created = Like.objects.create(question=create_id)
try:
user_liked = Like.objects.get(question=create_id, user=user)
except:
user_liked = None
if user_liked:
user_liked.likecount -= 1
liked.user.remove(request.user)
user_liked.save()
else:
liked.user.add(request.user)
liked.likecount += 1
liked.save()
return HttpResponse(simplejson.dumps(vars, user),
mimetype='application/javascript')
template
<button type="button" class="btn btn-request" name="{{question.id}}" id="like">Request</button>
<script>
$('#like').click(function(){
$.ajax({
type: "POST",
url: "{% url 'like' %}",
data: {'tutorial_id': $(this).attr('name'), 'csrfmiddlewaretoken': '{{csrf_token}}'},
dataType: "text",
success: function(response) {
alert('You liked this')
},
error: function(rs, e) {
alert(rs.responseText);
}
});
})
</script>
What I am missing here, can anyone explain me?
Thanks!
Like.objects.create(question=create_id)
Returns a single object (a Like).
So, doing like, created = Like.objects.create(question=create_id) doesn't work because there's only one item on the right, so it can't be unpacked (like if you did like, created = 1).
The method that returns the object and a created boolean object is get_or_create:
like, created = Like.objects.get_or_create(question=create_id)

XHR status returns 0 in ajax call to a django generic view

This is totally weird because I don't know why is returning this error when I replicated the same code for one section to another, only change the title of some generic views (UpdateView) and never execute the get function for return my form for edit a single customer, that's the code:
urls
from django.conf.urls import patterns, include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from . import views
from . import forms
from . import invoice
urlpatterns = patterns('',
url(r'^pedidos/',views.PedidosListView.as_view(),name="pedidos_list"),
url(r'^pedidos/add',views.add_pedido, name="pedido_add"),
url(r'^pedidos/edit/(?P<pedido_id>\d+)',views.edit_pedido, name="pedido_edit"),
url(r'^pedidos/delete/(?P<pedido_id>\d+)',views.delete_pedido, name="pedido_delete"),
url(r'^pedido/(?P<pk>\d+)',forms.DetailPedido.as_view(), name="pedido_detail"),
url(r'^pedido-pdf/(?P<pk>\d+)',invoice.detalle_pedido_pdf, name="pedido_detail_pdf"),
url(r'^clientes/',views.ClientesListView.as_view(),name="clientes_list"),
url(r'^clientes/edit/(?P<pk>\d+)$',forms.ClienteUpdateView.as_view(), name="clientes_edit"),
url(r'^empleados/edit/(?P<pk>\d+)$',forms.EmpleadoUpdateView.as_view(),name="edit"),
url(r'^empleados/',views.EmpleadoListView.as_view(),name="list"),
)
forms
class ClienteUpdateView(UpdateView):
form_class = ClienteModelForm
model = Cliente
template_name = 'ventas/form.html'
def get(self, request, **kwargs):
self.object = Cliente.objects.get(pk=self.kwargs['pk'])
form_class = self.get_form_class()
form = self.get_form(form_class)
context = self.get_context_data(object=self.object, form=form)
return self.render_to_response(context)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.save()
return HttpResponseRedirect('ventas/clientes_list.html')
def form_invalid(self,form):
if self.request.is_ajax():
return HttpResponseBadRequest(json.dumps(form.errors),
mimetype="application/json")
javascript
$(".edit").click(function(ev){
ev.preventDefault();
var url = $(this).data('form');
$.ajax({
url: url,
success: function(data, status){
$('body').append($('<div id="myModal" class="modal hide fade">' + data + '</div>').modal());
$("#myModal").find(".datePicker" ).datepicker({ dateFormat: "dd/mm/yy" });
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(xhr.status);
console.log(xhr.responseText);
console.log(thrownError);
}
})
return false; // prevent the click propagation
});
html
<button data-form="{% url 'ventas:clientes_edit' c.id %}" class="edit btn btn-mini btn-info">
If in ajax url change the value for 'ventas/empleados/edit/someid' (the same that I replicated for do ClienteUpdateView, I can retrieve the form for employee edit but I can't do the same for customer, I'm missing something that I'm not able now to notice? It's driving my nuts! Any ideas?
Regards!

Resources