How to reverse_lazy to a view/url with variable? - python

I've got a DeleteView I use for removing objects from a model. It is launched via a button in a table. It works fine.
class DeleteAssignment(DeleteView):
model = Assignment
success_url = reverse_lazy('company')
I just want to have it return to it's parent view on success. I currently have it redirecting to the parent's parent (company), as this view doesn't require a variable. This would be simple, but the parent view requires a variable farm_id to render, this is captured from the url like "/farm/18"
url(r'^farm/(?P<farm_id>.+)', views.farm, name='farm'),
I've solved this with forms on the page by having them redirect to the view farm with the variable farm_id.
return redirect(farm, farm_id=farm_id)
How could I do this with the success_url for my DeleteView?
Example for nickie:
views.py
#login_required
def farm(request, farm_id=None):
user = request.user
company_id = user.profile.company_id
farm_id = farm_id
farm_filter = Farm.objects.filter(farm=farm_id)
farm_current = farm_filter[0]
# farm_company =
serial_filter = Sensor.objects.filter(assignment__farm__company_id__isnull=True)
assignment_filter = Assignment.objects.filter(farm=farm_id)
farm_instance = Farm.objects.get(farm=farm_filter[0].farm)
update_farm_form = UpdateFarmForm(instance=farm_instance)
assign_sensor_form = AssignmentForm()
if request.method == 'POST' and 'updatefarm' in request.POST:
update_farm_form = UpdateFarmForm(request.POST, instance=farm_instance)
if update_farm_form.is_valid():
update_farm_form.save()
return redirect(farm, farm_id=farm_id)
else:
if request.method == "POST" and 'assignsensor' in request.POST:
assign_sensor_form = AssignmentForm(request.POST)
if assign_sensor_form.is_valid():
assignment = assign_sensor_form.save()
if user.is_staff is True:
assignment.company_id = farm_filter[0].company_id
else:
assignment.company_id = user.profile.company_id
assignment.save()
return redirect(farm, farm_id=farm_id)
else:
assign_sensor_form = AssignmentForm(request.POST)
return render(request, 'users/farm_template.html', {'company_id': company_id, 'farm_filter': farm_filter, 'farm_current': farm_current, 'serial_filter': serial_filter, 'assignment_filter': assignment_filter, 'update_farm_form': update_farm_form, 'assign_sensor_form': assign_sensor_form})
urls.py
from django.conf.urls import url, include
from django.contrib.auth import views as auth_views
from apps.dashboard import views
from apps.dashboard.views import DeleteAssignment, DeleteFarm
urlpatterns = [
url(r'^company/', views.company_view, name='company'),
# url(r'^test/', views.test),
# url(r'^test2/', views.test2, name='test2'),
# url(r'^farms/', views.add_farms),
url(r'^manual-signup/', views.signup_manual),
url(r'^signup/(?P<company_id>.+)', views.signup_company),
url(r'^settings/', views.update_profile),
url(r'^create-company/', views.create_company),
url(r'^create-sensor/', views.create_sensor),
url(r'^assign-sensor/', views.assign_sensor),
url(r'^login/$', auth_views.login, {'template_name': 'login.html'}, name='login'),
url(r'^logout/$', auth_views.logout, {'next_page': '/login'}, name='logout'),
url(r'^$', views.main),
# url(r'^company/(?P<company_id>.+)/farm/(?P<farm_id>.+)', views.farm),
url(r'^farm/(?P<farm_id>.+)', views.farm, name='farm'),
url(r'^unit/(?P<sensor_id>.+)', views.unit),
# url(r'^company/(?P<company_id>.+)', views.company),
url(r'^download/', views.download),
# url(r'^export/xls/$', views.export_users_xls),
url(r'^live/', views.live),
url(r'^data/', views.data),
url(r'^debug/', views.debug),
url(r'^delete-assignment/(?P<pk>\d+)/$', DeleteAssignment.as_view(), name='delete-assignment', ),
url(r'^delete-farm/(?P<pk>\d+)/$', DeleteFarm.as_view(), name='delete-farm', ),
url(r'^', include('django.contrib.auth.urls'))
]
This is view redirects to itself upon successful form submission. This reloads tables based on the user submission without having to deal with js for now.
The farm_id in return redirect(farm, farm_id=farm_id) is captured from the url, via the appropriate line in urls.py url(r'^farm/(?P<farm_id>.+)', views.farm, name='farm'),
This is all I want to do with the delete view, instead of the success url simply being a view, a view with a variable like I did above.

Yes, you can do this with success_url in this way:
class DeleteAssignment(DeleteView):
. . . . .
. . . . .
. . . . .
def get_success_url(self):
# if you are passing 'pk' from 'urls' to 'DeleteView' for company
# capture that 'pk' as companyid and pass it to 'reverse_lazy()' function
companyid=self.kwargs['pk']
return reverse_lazy('company', kwargs={'pk': companyid})
This should work perfectly.

As Nickie suggested in the comments: https://docs.djangoproject.com/en/1.11/ref/class-based-views/mixins-editing/#django.views.generic.edit.DeletionMixin.success_url
Solved this with success_url = "/farm/{farm_id}"

The following works:
reverse_lazy('name_of_your_view', kwargs={'key': value})
Not documented either in the man page or in docstring, was suggested by AI.

Related

AttributeError: type object 'AuthorDetailView' has no attribute 'as_views'

I'm a beginner in python-django coding. Currently I am following this guide and doing the challenging part for the author page (https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views) but I am facing a issue of AttributeError: type object 'AuthorDetailView' has no attribute 'as_views'.
Below are my codes:
In urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('books/', views.BookListView.as_view(), name='books'),
path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),
path('authors/', views.AuthorListView.as_view(), name ='authors'),
path('authors/<int:pk>', views.AuthorDetailView.as_views(), name='author-detail'),
]
In views.py:
from django.shortcuts import render
# Create your views here.
from .models import Book, Author, BookInstance, Genre
def index(request):
"""View function for home page of site."""
# Generate counts of some of the main objects
num_books = Book.objects.all().count()
num_instances = BookInstance.objects.all().count()
# Available books (status = 'a')
num_instances_available = BookInstance.objects.filter(status__exact='a').count()
# The 'all()' is implied by default.
num_authors = Author.objects.count()
context = {
'num_books': num_books,
'num_instances': num_instances,
'num_instances_available': num_instances_available,
'num_authors': num_authors,
}
# Render the HTML template index.html with the data in the context variable
return render(request, 'index.html', context=context)
from django.views import generic
class BookListView(generic.ListView):
model = Book
paginate_by = 5
class BookDetailView(generic.DetailView):
model = Book
class AuthorListView(generic.ListView):
model = Author
paginate_by = 5
class AuthorDetailView(generic.DetailView):
model = Author
Would appreciate if someone can help me. Thank you
you have a typo mistake.
it's as_view() not as_views().
path('authors/<int:pk>', views.AuthorDetailView.as_view(), name='author-detail'),
try this.

How to use redirect with parameter in Django?

I have this function in views.py:
def detel_kar(request, id):
detel = {}
detel['detels'] = DipPegawai.objects.filter(PegID=id)
detel['kels']=DipKeluargaPeg.objects.filter(PegID_id=id)
return render(request, 'karyawan/detel_kar.html', detel)
I then have a function to insert data with parameter id by getting a primary key from elsewhere.
def tambah_kel(request, id):
kar = DipPegawai.objects.get(PegID=id)
if request.method == "POST":
kel=DipKeluargaPeg(PegID=kar)
form = datakeluarga(request.POST,instance=kel)
if form.is_valid():
form.save(commit=True)
return redirect('detel_kar')
else:
form = datakeluarga()
return render(request, 'karyawan/tambah_kel.html', {'form': form, 'kars': kar})
How to redirect to detel_kar view? if i use this code in tambah_kel function
return redirect('detel_kar')
it will return anerror
Reverse for 'detel_kar' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
urls.py
from django.conf.urls import url
from . import views
urlpatterns=[
url(r'^$', views.index, name='index'),
url(r'^tambah/$', views.tambah, name='tambah_kar'),
url(r'^karyawan/detel_kar/(?P<id>\d+)/$',views.detel_kar, name='detel_karyawan'),
url(r'^karyawan/edit_kar/(?P<id>\d+)/$',views.edit_kar, name='edit_karyawan'),
url(r'^karyawan/del_kar/(?P<id>\d+)/$',views.del_kar, name='del_karyawan'),
url(r'^karyawan/tambah_kel/(?P<id>\d+)/$',views.tambah_kel, name='tambah_keluarga'),
]
In your urls.py, you have defined:
url(r'^karyawan/detel_kar/(?P<id>\d+)/$',views.detel_kar, name='detel_karyawan'),
i.e., the view that calls the function detel_kar() is named 'detel_karyawan'. This is the name you need to use in your redirect:
return redirect('detel_karyawan')
However the view expects an ID, so you must supply an ID when calling it:
return redirect('detel_karyawan', id=id)
(Where id is determined based on the logic in your view).

Couldn't load admin interface due the error below

I've got following code and got two issues.
1. I couldn't get joins added up and not showing up on the page.
2. Admin interface is not loading.
I've re-created the DB checked the code thoroughly and really need help.
Views.py.
from django.conf import settings
from django.shortcuts import render, HttpResponseRedirect, Http404
from.models import Join
from .forms import EmailForm, JoinForm
def get_ip(request):
try:
x_forwarded = request.META.get("HTTP_X_FORWARDED_FOR")
if x_forwarded:
ip = x_forwarded.split(",")[0]
else:
ip = request.META.get("REMOTE_ADDR")
except:
ip = ""
return ip
import uuid
def get_ref_id():
ref_id = str(uuid.uuid4())[:11].replace('-', '').lower()
try:
id_exists = Join.objects.get(ref_id=ref_id)
get_ref_id()
except:
return ref_id
def home(request):
try:
join_id = request.session['join_id_ref']
obj = Join.objects.get(id=join_id)
except:
obj = None
form = JoinForm(request.POST or None)
if form.is_valid():
new_join = form.save(commit=False)
email = form.cleaned_data['email']
new_join_old, created = Join.objects.get_or_create(email=email)
if created:
new_join_old.ref_id = get_ref_id()
if not obj == None:
new_join_old.friend = obj
new_join_old.ip_address = get_ip(request)
new_join_old.save()
return HttpResponseRedirect("/%s" %(new_join_old.ref_id))
context = {"form": form}
template = 'home.html'
return render(request, template, context)
def share(request, ref_id):
#try:
join_obj = Join.objects.get(ref_id=ref_id)
friends_referred = Join.objects.filter(friend=join_obj)
count = join_obj.referral.all().count()
ref_url = settings.SHARE_URL + str(join_obj.ref_id)
context = {"ref_id": join_obj.ref_id, "count": count, "ref_url": ref_url}
template = "share.html"
return render(request, template, context)
#except:
#raise Http404
Error message I am getting after commenting out exception is:
DoesNotExist at /admin
Join matching query does not exist. Lookup parameters were {'ref_id': u'admin'}
Urls.py includes following.
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^$', 'joins.views.home', name='home'),
url(r'^(?P<ref_id>.*)$', 'joins.views.share', name='share'),
)
Your regular expression in line
url(r'^(?P<ref_id>.*)$', 'joins.views.share', name='share'),
matches admin/ as well you should use something less "greedy".

Django - No Reverse Match at /

I'm trying to get the absolute url for particular items in my model.
models.py
class BannerAds(models.Model):
name = models.CharField(max_length=256)
phone = models.CharField(max_length=20)
def __unicode__(self):
return self.name
#permalink
def get_absolute_url(self):
from django.core.urlresolvers import reverse
return reverse('index', args=[str(self.name)])
views.py
def banners(request):
context = RequestContext(request)
all_banners = BannerAds.objects.all()
content_dict = {'banners': all_banners,}
return render_to_response('templates/banner.html', content_dict, context)
def index(request):
context = RequestContext(request)
banner_list = BannerAds.objects.all()
city_list = Cities.objects.order_by('name')
offer_list = NewOffers.objects.order_by('offer_add_date')[:5]
context_dic = {'banner_list': banner_list,
'cities': city_list,
'offers': offer_list,
}
return render_to_response('templates/index.html', context_dic, context)
urls.py
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^$', views.index, name='index'),
url(r'^advertise/', views.advertise, name='advertise'),
url(r'^about/', views.about, name='about'),
url(r'^listing/', views.listing, name='listing'),
url(r'^search/', views.search, name='search'),
url(r'^add/', views.add_listing, name='add'),
url(r'^offers/', views.offers, name='offer'),
url(r'^add_listing/$', views.add_listing, name='add_listing'),
url(r'^listing/(?P<listing_url>\w+)/$', views.listing, name='category'),
url(r'^testimonial/', views.testimonials, name='testimonial'),
url(r'^add_testimonial', views.add_testimonial, name='add_testimonial'),
url(r'^banner', views.banners, name='banners'),
)
I've entered test data as name=test, phone = testing.
When I try to open the page, it gives me a No Reverse Match at / error along with a
Reverse for '' with arguments '('Testing',)' and keyword arguments '{}' not found. 0 pattern(s) tried: []
Any idea what I'm missing? I'm pretty new to Django development so solutions with code examples would help me a lot.
Change the view banners to as you are passing args.
def banners(request, name):
context = RequestContext(request)
all_banners = BannerAds.objects.all()
content_dict = {'banners': all_banners,}
return render_to_response('templates/banner.html', content_dict, context)
Also, make sure you have made an entry in urls.py with name="banners"
Don't use both #permalink and reverse(). They do the same thing. Either drop the decorator, or just return the tuple of (view_name, args).
In fact, the documentation says that permalink is deprecated, so the best thing is just to remove it.
The url url(r'^$', views.index, name='index') does not accept any parameter so why are you passing args here reverse('index', args=[str(self.name)])?
If you want a detail view and wants the name to be optional parameter for index then you can do:
url(r'^(?:(?P<name>.+?)/)?$', views.index, name='index')
Also change the index view to this:
def index(request, name=None):
context = RequestContext(request)
banner_list = BannerAds.objects.all()
# now if name parameter is not None you may want to just pick single object
banner_obj = None
if name:
banner_obj = BannerAds.objects.get(name__exact=name)
city_list = Cities.objects.order_by('name')
offer_list = NewOffers.objects.order_by('offer_add_date')[:5]
context_dic = {'banner_list': banner_list,
'cities': city_list,
'offers': offer_list,
'banner_obj': banner_obj,
}
return render_to_response('templates/index.html', context_dic, context)
Or have a separate view which will serve for the detail of BannerAds.

newbie Django smart/chained menu trouble

i am trying to make a chained select menu, i have this model:
from django.db import models
class Health_plan(models.Model):
name = models.CharField(max_length=15)
class Doctors_list(models.Model):
name = models.CharField(max_length=30)
specialty = models.CharField(max_length=15)
health_plans = models.ManyToManyField(Health_plan, related_name="doctors")
location = models.CharField(max_length=15)
def __unicode__(self):
return self.name
And this is my forms.py:
class SpecForm(ModelForm):
a = Doctors_list.objects.values_list('specialty', flat=True)
unique = [('---------------','---------------')] + [(i,i) for i in set(a)]
specialty = forms.ChoiceField(choices=unique)
class Meta:
model = Doctors_list
class HealthForm(ModelForm):
hplan = ChainedForeignKey(
Health_plan,
chained_field="specialty",
chained_model_field="specialty",
show_all=False,
auto_choose=True
)
my urls.py:
from django.conf.urls import patterns, include, url
from testApp.views import spec_form
from testApp.views import health_form
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
url(r'^$', 'Medbook.views.home', name='home'),
# url(r'^Medbook/', include('Medbook.foo.urls')),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^hello/$', spec_form),
url(r'^hello/$', health_form),
)
and my views.py:
from django.shortcuts import render_to_response
from testApp.forms import SpecForm
from testApp.forms import HealthForm
def spec_form (request):
if request.method == 'POST':
form = SpecForm(request.POST)
if form.is_valid():
form.save()
else:
form = SpecForm()
return render_to_response('hello.html', {'form':form})
def health_form (request):
if request.method == 'POST':
form = HealthForm(request.POST)
if form.is_valid():
form.save()
else:
form = SpecForm()
return render_to_response('hello.html', {'form':form})
I am new to Django and i find this tricky. The user must select one specialty, and then should appear the health_plans that cover that specialty.
The health_plans have a manytomany relationship with the doctors. When a person chooses a specialty, the script should check wich doctors belong to that specialty and retrieve all the health plans hold by those doctors.
So far the only thing i get in the menu is: Health_plan object
Health_plan object
Health_plan object
I hope i made it clear, for my code it isn't.
Any help kindly appreciated
This has nothing to do with chained selects, and most of the code here is irrelevant. The issue is that, while Doctors_list has a __unicode__ method, Health_plan does not. Define one for that model too.
(Also note that the usual style for model names is CapWords: DoctorsList and HealthPlan. Although the former actually only refers to a single doctor, so it should just be Doctor.)

Categories