django tables 2 - delete column and delete_item for inherited tables - django

I want to have one abstract function for all my tablelists (one for each model) and (one delete_item) function in view.
I don't know how to make the delete (column in this table) and pass the model to the delete_item function in the view
Tables.py
############ Abstract Table
class abs_Table(tables.Table):
SN = tables.Column(empty_values=(), orderable=False)
delete = tables.LinkColumn('delete_item', args=[A('pk'), ?????Model???], attrs={
'a': {'class': 'btn btn-small btn-dark'}
# })
def __init__(self, *args, **kwargs):
super(abs_Table, self).__init__(*args, **kwargs)
self.counter = itertools.count(1)
def render_SN(self, record):
pg = getattr(self, 'paginator', None)
if pg:
v = next(self.counter)
return v + self.paginator.per_page * (self.page.number-1)
else:
return next(self.counter)
class Meta:
model = None
fields = [ 'SN', 'id', 'delete', ]
attrs = {"class": "table-striped table-bordered", 'width': '100%'}
empty_text = "There are no Records matching the search criteria..."
Then for model Table
Tables.py
class ModelTable(abs_Table):
class Meta(abs_Table.Meta):
model = modelname
fields = abs_Table.Meta.fields+[selected_model_fields]
Views.py
def delete_item(request, pk, delmodel):
obj = get_object_or_404(delmodel, id=pk)
if request.method == "POST":
obj.delete()
return redirect("../")
else:
pass
context = {
'object': obj
}
return render(request, '/delete_confirmation.html', context)

For the Views part. It works for me after passing the model as string and then using apps.get_model to change it into a model.
views.py`
from django.apps import apps
def delete_item(request, pk, delmodel):
DeleteModel = apps.get_model("Myapp", delmodel)
obj = get_object_or_404(DeleteModel, id=pk)
if request.method == "POST":
obj.delete()
return redirect("../")
else:
pass
context = {
'object': obj
}
return render(request, '/delete_confirmation.html', context)
Still the confirmation is not handled correctly and the delete column in tables need to be improved.

Related

Django : "break" a class based view with intermediate "return render" won't work

I use a CB ListView for displaying objects. I want to add a session variable based on another models' PK during the execution of my ListView:
views.py
class ProduitListView(LoginRequiredMixin, ListView):
model = Produit
context_object_name = "produits"
paginate_by = 10
template_name = 'products/produits.html'
ordering = ['-mageid', ]
def get_context_data(self, *args, **kwargs):
context = super(ProduitListView, self).get_context_data(
*args, **kwargs)
# used for incoming products (sourcing cf URLS)
supplier_pk = self.kwargs.get('pk', None)
if supplier_pk:
set_incoming_supplier(self.request, supplier_pk)
context['avail_warehouses'] = Warehouse.objects.all()
context['js_warehouses'] = serialize(
'json', Warehouse.objects.all(), fields=('code', 'id', ))
context['title'] = 'Produits'
return context
set_incoming_supplier (in another APP)
#login_required
def set_incoming_supplier(request, pk):
supplier = Supplier.objects.filter(pk=pk).first()
supp = SupplierSerializer(instance=supplier).data
rs = request.session
if 'income' in rs:
if 'cur_supplier' in rs['income']:
prev_supplier = rs['income']['cur_supplier']
if supp != prev_supplier:
return render(request, 'sourcing/alert_supplier_change.html',
{'prev_supplier': prev_supplier, 'cur_supplier': rs['income']['cur_supplier']})
rs['income'] = {'cur_supplier': supp}
I thought the return render(request, 'sourcing/alert_supplier_change... could "break" my ListView and render my alert page but it doesn't. ListView seems to continue and finally renders my ProduitListView page.
Why doesn't this work ?
Finally found a solution that consists in using get() method within my CBV. In it, I evaluate my supplier with set_incoming_supplier() that returns a context or None. According to this evaluation, I render either the regular template or my alert template.
ProduitListView(LoginRequiredMixin, ListView):
class ProduitListView(LoginRequiredMixin, ListView):
model = Produit
context_object_name = "produits"
paginate_by = 10
template_name = 'products/produits.html'
ordering = ['-mageid', ]
def get_context_data(self, *args, **kwargs):
context = super(ProduitListView, self).get_context_data(
*args, **kwargs)
context['avail_warehouses'] = Warehouse.objects.all()
context['js_warehouses'] = serialize(
'json', Warehouse.objects.all(), fields=('code', 'id', ))
context['title'] = 'Produits'
return context
def get(self, request, *args, **kwargs):
supplier_pk = self.kwargs.get('pk', None)
if supplier_pk:
context = set_incoming_supplier(self.request, supplier_pk)
if context:
return render(request, 'sourcing/alert_supplier_change.html', context)
return super().get(request, *args, **kwargs)
set_incoming_supplier()
def set_incoming_supplier(request, pk):
supplier = Supplier.objects.filter(pk=pk).first()
supp = SupplierSerializer(instance=supplier).data
rs = request.session
if 'income' in rs:
if 'cur_supplier' in rs['income']:
prev_supplier = rs['income']['cur_supplier']
if supp != prev_supplier:
return {'prev_supplier': prev_supplier, 'cur_supplier': supp}
rs['income'] = {'cur_supplier': supp}
Maybe not the best way but it works well.

How to provide initial data to ForeignKey in ModelFormSet?

So I have this thing.
These are the relationships of my models
To define an event you have a Place, a QR Link and an ImageAlbum which have up to five Images.
An event may or may not have a Place
An event MUST have the main image which is marked by the main attr in the Image Form.
All the forms are in the same page, they all are processed with a single Submit
Now my troubles begin and end in the Forms Department, i have several Model Forms:
#FORMS FILE
class EventForm(ModelForm):
date_time_start = forms.DateTimeField(input_formats=["%Y-%m-%d"], required=True, widget=forms.DateTimeInput(format="%Y-%m-%d", attrs={"id": "cal_start", "placeholder": "yyyy-mm-dd"}))
has_place = forms.BooleanField()
class Meta:
model = Event
fields = ['title', 'subtitle', 'phrase', 'date_time_start', 'prices', 'has_place']
class BaseImageFormSet(BaseModelFormSet):
def clean_main(self):
"""Checks that there is only one main image"""
if any(self.errors):
return
boolean_arr = []
for form in self.forms:
if self.can_delete and self._should_delete_form(form):
continue
main_data = form.cleaned_data.get('main')
main = main_data if main_data is not None else False
if sum(boolean_arr) > 1:
raise ValidationError('There can only be one main image.')
boolean_arr.append(main)
class PlaceForm(ModelForm):
class Meta:
model = EventPlace
exclude = ['uuid', 'event']
class QRForm(ModelForm):
class Meta:
model = EventQR
exclude = ['uuid', 'event']
My headache is with the Images, I have to make a ModelFormSet of Images but I have to create first the album which connects the images to the event.
Here are my views:
#VIEWS FILE
class NewEventView(BaseView):
def get(self, request, *args):
ImageFormSet = modelformset_factory(
EventImage, fields=('image', 'main'),
extra=5, max_num=5, formset= BaseImageFormSet)
image_formset = ImageFormSet(prefix='images')
event_form = EventForm(prefix='event')
place_form = PlaceForm(prefix='place')
qr_form = QRForm(prefix='qr')
context = {'forms': {'Evento': event_form, 'Lugar': place_form,
'QR Links': qr_form}, 'image_formset': image_formset, }
return render(request, "events/events_add.html", context)
def post(self, request):
event_form = EventForm(request.POST, prefix='event')
if event_form.is_valid():
new_event = event_form.save(commit=False)
if event_form.cleaned_data['has_place']:
place_form = PlaceForm(request.POST, prefix='place')
if place_form.is_valid():
qr_form = QRForm(request.POST, prefix='qr')
if qr_form.is_valid():
new_album = EventAlbum(event=new_event)
ImageFormSet = modelformset_factory(
EventImage, fields=('image', 'main'),
extra=5, max_num=5, formset= BaseImageFormSet)
image_formset = ImageFormSet(request.POST, request.FILES,
prefix='images')
if image_formset.is_valid():
event_form.save()
new_album.save()
new_place = place_form.save(commit=False)
new_place.event = new_event
new_qr = qr_form.save(commit=False)
new_qr.event = new_event
new_place.save()
new_qr.save()
image_formset.save()
return HttpResponse('Ok', content_type='text')
else:
return Response(image_formset.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(qr_form.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(place_form.errors, status=status.HTTP_400_BAD_REQUEST)
else:
qr_form = QRForm(request.POST, prefix='qr')
if qr_form.is_valid():
new_album = EventAlbum(event=new_event)
ImageFormSet = modelformset_factory(
EventImage, extra=5, max_num=5, formset=BaseImageFormSet)
image_formset = ImageFormSet(
request.POST, request.FILES, prefix='images')
if image_formset.is_valid():
event_form.save()
new_album.save()
image_formset.save()
qr_form.save()
return HttpResponse('Ok', content_type='text')
else:
return Response(image_formset.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(qr_form.errors, status=status.HTTP_400_BAD_REQUEST)
return Response(event_form.errors, status=status.HTTP_400_BAD_REQUEST)
How would you do about saving the images?
And the whole event with its dependencies.
Please help i am stuck by now

I'm trying to override a django formtools wizard form widget, but it is just using the standard widget

I have the following form
class ProviderSignUp1(forms.ModelForm):
class Meta:
model = models.Provider
fields = [
'childcare_type_informal',
'childcare_type_accredited',
]
wigdets = {
'childcare_type_informal': PatchRadioSelect(
attrs={
'class':'form-control'
}
),
'childcare_type_accredited': PatchRadioSelect(
attrs={
'class':'form-control'
}
)
}
def clean(self):
cleaned_data = self.cleaned_data
if cleaned_data['childcare_type_informal'] == True and cleaned_data['childcare_type_accredited'] == True:
raise ValidationError("You must select only one type of childcare")
if cleaned_data['childcare_type_informal'] == False and cleaned_data['childcare_type_accredited'] == False:
raise ValidationError("You must select at least one type of childcare")
return super().clean()
The widget is defined as
from django.forms.widgets import RadioSelect
class PatchRadioSelect(RadioSelect):
template_name = 'userprofiles/form_widgets/radio.html'
option_template_name = 'userprofiles/form_widgets/radio_option.html'
And my wizard is:
PROVIDER_SIGNUP_TEMPLATES = {
'page0': 'userprofiles/provider_signup_wizard/page0.html',
'page1': 'userprofiles/provider_signup_wizard/page1.html',
'page2': 'userprofiles/provider_signup_wizard/page2.html',
'page3': 'userprofiles/provider_signup_wizard/page3.html',
'page4': 'userprofiles/provider_signup_wizard/page4.html',
'page5': 'userprofiles/provider_signup_wizard/page5.html',
'page6': 'userprofiles/provider_signup_wizard/page6.html',
'page7': 'userprofiles/provider_signup_wizard/page7.html',
'page8a': 'userprofiles/provider_signup_wizard/page8.html',
'page8b': 'userprofiles/provider_signup_wizard/page8.html',
'page9': 'userprofiles/provider_signup_wizard/page9.html',
'page10': 'userprofiles/provider_signup_wizard/page10.html',
}
PROVIDER_SIGNUP_FORMS = [
("page0", forms.ProviderSignUp0),
("page1", forms.ProviderSignUp1),
("page2", forms.ProviderSignUp2),
("page3", forms.ProviderSignUp3),
("page4", forms.ProviderSignUp4),
("page5", forms.ProviderSignUp5),
("page6", forms.ProviderSignUp6),
("page7", forms.ProviderSignUp7),
("page8a", forms.ProviderSignUp8a),
("page8b", forms.ProviderSignUp8b),
("page9", forms.ProviderSignUp9),
("page10", forms.ProviderSignUp10),
]
def accredited_only_condition(wizard):
cleaned_data = wizard.get_cleaned_data_for_step('page1') or {}
return cleaned_data.get('childcare_type_accredited', True)
def informal_only_condition(wizard):
cleaned_data = wizard.get_cleaned_data_for_step('page1') or {}
return cleaned_data.get('childcare_type_informal', True)
class ProviderSignUpWizard(SessionWizardView):
form_list = PROVIDER_SIGNUP_FORMS
condition_dict = {
'page2': accredited_only_condition,
'page8a': accredited_only_condition,
'page8b': informal_only_condition,
'page9': informal_only_condition,
}
def get_form_instance(self, step):
if step == 'page4':
return self.instance_dict.get(step, self.request.user)
return self.instance_dict.get(step, self.request.user.provider)
def get_template_names(self):
return [PROVIDER_SIGNUP_TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
provider_instance = models.Provider.objects.get(id=self.request.user.provider.id)
user_instance = models.User.objects.get(id=self.request.user.id)
for form in form_list:
provider_instance = construct_instance(form, provider_instance, form._meta.fields, form._meta.exclude)
user_instance = construct_instance(form, user_instance, form._meta.fields, form._meta.exclude)
provider_instance.save()
user_instance.save()
return redirect(self.request.user.get_provider_profile_url())
def post(self, *args, **kwargs):
form = self.get_form(data=self.request.POST, files=self.request.FILES)
if form.is_valid():
form.save()
if 'services' in form.cleaned_data:
models.Provider.objects.get(id=self.request.user.provider.id).services.set(form.cleaned_data['services'])
if 'features' in form.cleaned_data:
models.Provider.objects.get(id=self.request.user.provider.id).features.set(form.cleaned_data['features'])
if 'informal_phrases' in form.cleaned_data:
models.Provider.objects.get(id=self.request.user.provider.id).informal_phrases.set(form.cleaned_data['informal_phrases'])
return super().post(*args, **kwargs)
My widget is being ignored and the standard widget is being used. Please note, I seem unable to change any of the widgets from the standard and can only add attributes to the existing widget. What am I doing wrong?
Just in case anyone else comes across the same issue, I found if I define __init__ within the first form in the wizard, I can then override the widgets within __init__ in whichever form I need to use it. But it doesn't work if I don't specify __init__ in the first form.
I think this more a workaround than solution.

how we save form through Class Based Generic View in django

i am using class based generic view in my Subject_En roll application
my view.py is
cc = 0
#login_required
def add_subject_enroll(request):
user = request.user
obj = StudentRegistration.objects.get(user=user)
print "obj.first_name",obj.first_name
first_name = obj.first_name
print "first_name",first_name
if obj.user:
print "object exist"
#form = Subject_EnrollForm(request.POST or None, initial={'student_name' : first_name})
#form = Subject_EnrollForm( initial={'student_name' : obj.first_name})
form = Subject_EnrollForm(request.POST or None, request.FILES or None)
form.fields["student_name"].initial = first_name
form.fields["birth_place"].initial = obj.birth_place
form.fields["gender"].initial = obj.gender
form.fields["phone"].initial = obj.phone
form.fields["email"].initial = obj.email
form.fields["phone"].initial = obj.phone
form.fields["nationality"].initial = obj.nationality
form.fields["religion"].initial = obj.religion
form.fields["blood_group"].initial = obj.blood_group
form.fields["nationality"].initial = obj.nationality
form.fields["nationality"].initial = obj.nationality
form.fields["nationality"].initial = obj.nationality
form.fields["nationality"].initial = obj.nationality
else:
print "object not found"
Subject_EnrollForm(request.POST or None, request.FILES or None)
if request.POST:
if form.is_valid():
a = form.save()
a.user = request.user
a.save()
#user.save()
messages.add_message(request,messages.SUCCESS, "your Profile was added")
#return HttpResponseRedirect('/app/all')
return HttpResponseRedirect('/')
args = {}
args.update(csrf(request))
args['form'] = form
context = RequestContext(request,
{'request': request,
'user': request.user,
'form': form})
return render_to_response('subject_enroll/add_subject_enroll.html', args, context)
class Subject_EnrollListView(ListView):
"""View to display all published and visible news entries."""
template_name = "subject_enroll/subject_enroll_list.html"
def get_queryset(self):
return Subject_Enroll.objects.all()
class DetailViewMixin(object):
"""Mixin to handle different DetailView variations."""
model = Subject_Enroll
#slug_field = 'translations__slug'
def get_queryset(self):
#return Subject_Enroll.objects.all()
return Subject_Enroll.objects.lang(self.request, False)
class Subject_EnrollDetailView(DetailViewMixin, DetailView):
def get_context_data(self, **kwargs):
context = super(Subject_EnrollDetailView, self).get_context_data(**kwargs)
context['subject_enrolls'] = Subject_Enroll.objects.all()
return context
class Subject_EnrollUpdateView(UpdateView):
form_class = Subject_EnrollForm
model = Subject_Enroll
template_name = 'subject_enroll/subject_enroll_detail.html'
def get(self, request, **kwargs):
self.object = Subject_Enroll.objects.get(id=self.request.id)
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 get_object(self, queryset=None):
obj = Subject_Enroll.objects.get(id=self.kwargs['id'])
return obj
i try with pass form in context of Detilviewmixin
class DetailViewMixin(object):
"""Mixin to handle different DetailView variations."""
model = Subject_Enroll
#slug_field = 'translations__slug'
def get_context_data(self, **kwargs):
context = super(DetailViewMixin, self).get_context_data(**kwargs)
#context['form'] = Subject_EnrollForm
#context['form'] = Subject_EnrollForm()
return context
def get_queryset(self):
#return Subject_Enroll.objects.all()
return Subject_Enroll.objects.lang(self.request, False)
in that form are render on template but when i press save button so it can't save record
from this code i get all field access in "subject_enroll/subject_enroll_detail.html" like {{ object.student_name }}
{{ object.enroll_status }}
so it gives value of that field but now i want to edit record in subject_enroll_detail.html template like s
subject_enroll values "draft" to "submit" with click on some buttons in subject_enroll_detail.html template
i tried with form view and updateview but can't find solution
pls help!!!
Thanks in advance!!
from django.views.generic import UpdateView
class StudentRegistrationUpdateView(UpdateView):
model = StudentRegistration
form_class = Subject_EnrollForm #don't need if you are editing all the fields
template_name = 'subject_enroll/add_subject_enroll.html'
https://docs.djangoproject.com/en/1.7/ref/class-based-views/generic-editing/#updateview
in your urls.py
import StudentRegistrationUpdateView
in urls.py don't forget to include 'pk' like below, this determines which object to be updated
url(r'student/(?P<pk>\d+)/update/$', StudentRegistrationUpdateView.as_view(), name='student_registration_update'),

Two model forms in one view/template in Django using CBV

Can someone show the example of usage of two model forms in one view/template? The task is to process more than one form in one CBV, where model of the second form has FK to first form model, so value from select widget from first form must be processed as value for object, created in second form.
My forms looks like this:
class CompanyEditForm(ModelForm):
name = CharField(label="Наименование", required=True)
type = ModelChoiceField(queryset=CompanyTypes.objects.all(), label="Тип компании", empty_label=None, initial=3)
description = CharField(label="Описание компании", required=False, widget=forms.Textarea(attrs={'cols': 40, 'rows':3}))
www = CharField(label="WEB сайт", required=False)
class Meta:
model = Companies
fields = ('type', 'name', 'description', 'www')
class BranchEditForm(ModelForm):
name = CharField(label="Наименование офиса", required=True)
type = ModelChoiceField(queryset=BranchTypes.objects.all(), label="Тип отделения", empty_label=None, initial=1)
class Meta:
model = Branches
exclude = ('company', 'address')
class AddressEditForm(ModelForm):
postalcode = IntegerField(label="Почтовый код", required=False)
city = CharField(label="Город", required=True)
street = CharField(label="Улица", required=True)
app = CharField(label="Дом", required=True)
app_extra = CharField(label="Корпус / Строение", required=False)
comment = CharField(label="Примечание к адресу", required=False)
exclude = ('company',)
class Meta:
model = Addresses
fields = ('postalcode', 'city', 'street', 'app', 'app_extra', 'comment')
UPDATE
I wrote this mixin:
class MultiFormCreate(FormMixin, TemplateResponseMixin, View):
formconf = None
def get_form_classes(self):
form_classes = {}
for key, params in self.formconf.items():
form_classes[key] = params.formclass
return self.form_classes
def get_initial(self, classname):
inicial = {}
if 'inicial' in self.formconf[classname]:
inicial = self.formconf[classname]['inicial'].copy()
return inicial
def get_form_kwargs(self, classname):
kwargs = {'initial': self.get_initial(classname), 'prefix': classname}
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
return kwargs
def get_forms(self):
for classname, params in self.formconf.items():
log.info("Name: %s, Params: %s" % (classname, params))
return dict(
[(classname, params['formclass'](**self.get_form_kwargs(classname))) for classname, params in self.formconf.items()])
def get(self, request, *args, **kwargs):
forms = self.get_forms()
return self.render_to_response(self.get_context_data(forms=forms))
def get_success_url(self):
if self.success_url:
url = force_text(self.success_url)
else:
raise ImproperlyConfigured(
"No URL to redirect to. Provide a success_url.")
return url
then in a view i only need to write processing in post:
class CompanyCreate(MultiFormCreate):
template_name = 'company/edit.html'
success_url = '/forbidden/'
formconf = {
'company': {'formclass': CompanyEditForm, 'inicial': {'name': "TESTNAME"}},
'branch': {'formclass': BranchEditForm},
'address': {'formclass': AddressEditForm}
}
def post(self, request, *args, **kwargs):
forms = self.get_forms()
cform = forms['company']
aform = forms['address']
bform = forms['branch']
if cform.is_valid() and aform.is_valid() and bform.is_valid():
''' Creating main form form object (by saving tthe form) '''
company_object = cform.save()
''' Creating dependant object '''
address_object = aform.save(commit=False)
branch_object = bform.save(commit=False)
''' assigning dependent fields '''
address_object.company = company_object
''' saving dependent _object_ '''
address_object.save()
''' managing another dependent fields '''
branch_object.company = company_object
branch_object.address = address_object
''' saving last object '''
branch_object.save()
return HttpResponseRedirect(self.get_success_url())
else:
forms = self.get_forms()
return self.render_to_response(self.get_context_data(forms=forms))
Code for view file :
if request.method == "POST":
company_form = CompanyEditForm(request.POST)
if company_form.is_valid():
company_object = company_form.save()
post_data = request.POST.copy()
branch_form = BranchEditForm(post_data)
branch_form.data['company'] = company_object
if branch_form.is_valid():
branch_object.save()
rest implement your business logic ..