Package: django-generic-scaffold
With django-generic-scaffold you can quickly create CRUD generic class based views for your models so you will have a basic CRUD interface to your models by writing only a couple of lines of extra code! The purpose of this CRUD interface is, as opposed to django-admin, to be used by users and not staff members.django-generic-scaffold is different from other scaffolding tools because it generates all views/url routeson-the-fly(by creating subclasses of normal django class-based views) andnotby outputing python code. This way you can re-configure
your views anytime you wish.As you can understand the main purpose of this library is to be able to add CRUD for as many models in your project with as little mental effort as possible. Nothing beats the django-admin for that of course but usually you don’t want to give access to /admin to all the users that will do data entry. I’ve found this project to be invaluable to my work (I mostly create apps to by used internally by the members of a public sector org); I guess it should also be very useful when you need to create a quick MVP for your project.ExampleI’ve added an example project of using django-generic-scaffold:https://github.com/spapas/generic-scaffold-demoInstallationInstall it withpip installdjango-generic-scaffold, or if you want to use the latest version on github, trypip installgit+https://github.com/spapas/django-generic-scaffold.If you want to use the template tags and the fallback templates of django-generic-scaffold, please putgeneric_scaffoldin yourINSTALLED_APPSsetting. If you
don’t need the template tags or fallback templates then no modifying of your settings is needed, just go ahead and use it!Simple usageLet’s say you have defined a model namedBookin yourmodels.py. In yourviews.pyor, even better in a module namedscaffolding.pydefine a class that overridesCrudManager:fromgeneric_scaffoldimportCrudManagerimportmodelsclassBookCrudManager(CrudManager):model=models.Bookprefix='books'Now, include the following lines to theurls.pyof your application:fromscaffoldingimportBookCrudManager# or from views import BookCrudManager depending on where you've put itbook_crud=BookCrudManager()# [...] define your urlpatters hereurlpatterns+=book_crud.get_url_patterns()You may now visithttp://127.0.0.1:8000/books(or whatever was yourprefix) to get a list of yourBookinstances.
The following methods have also been created:Create:http://127.0.0.1:8000/bookscreateDetail:http://127.0.0.1:8000/booksdetail/<id>Edit:http://127.0.0.1:8000/booksupdate/<id>Delete:http://127.0.0.1:8000/booksdelete/<id>If you don’t do anything else, the default fallback templates will be used (they are ugly and should only be used for testing).
You should add a template namedapp_name/testmodel_list.html(which is the default template for theListView) to override
the fallback templates - please read the next section for more info on that.Theprefixoption you set to theBooksCrudManagermethod will just prepend this prefix to all created urls
and can also be used to get your url names for reversing.Template selectionThere’s a bunch of fallback templates that will be used if no other template can be used instead.
These template are for testing purposes only and should be overriden (unless you want to
quickly see that everything works). Now, there are two ways you can redefine your templates:Implicitly: Just add appropriate templates depending on your app/model name (similarly to normal class-based-views), for example forapp_nameandTestModelyou can add the following templates:For create/update addapp_name/testmodel_form.html,
for list addapp_name/testmodel_list.html,
for detail addapp_name/testmodel_detail.html,
for delete addapp_name/testmodel_confirm_delete.html.Explicitly: You can use theaction_template_nameconfiguration option to explicitly set which templates will be used for each action. Theactioncould belist, detail, update, createordelete. So to configure the detail template name to befoo.htmlyou’ll use the optiondetail_template_name = 'foo.html'.So, the priority of templates is:Explicit templates (if configured)Implicit templates (if found)Fallback templates (as a last resort)ConfigurationMost of the time, you’ll need to configure three things before usingdjango-generic-scaffold: The form class used for create and update views, the access permissions for each generic class based view and the templates that each view will use. These can be configured just by settings attributes to yourCrudManagerclass.To configure the form class that will be used, use the optionform_class.To set the permissions you have to set thepermissionsattribute to a dictionary of callables. The keys of that dictionary should belist, detail, update, createordeletewhile the values should be callables likelogin_requiredorpermission_required('permission')etc.To configure the template names explicitly, useaction_template_name.For any other configuration of the generated class based views you’ll need to define mixins that will be passed to the generated CBV classes as a list using the optionaction_mixins(again action is eitherlist, detail, etc).Using mixins you can do whatever you want to your resulting CBV classes – also, by forcing you to use mixins django-generic-scaffold will help you follow bet code practices (DRY).However, sometimes mixins are not enough and you may need to completely override the parent Views to use something else. For this, you may set theaction_view_classproperty to your own parent class view (i.elist_view_class = OverridenListView).API and template tagsIf you want to use the provided template tags to your templates, you’ll need to add{% load generic_scaffold_tags %}near
the top of your template. Then you may useset_urls_for_scaffoldwhich will output the URLs of the
selected scaffold depending on your configuration. This tag can receive
three parameters: The django app name, the model name and the prefix name. You can either use
the combination of app name / model name or just the prefix.It will return a dictionary with all
the scaffolded urls for this model. For example, to get the url names for the modeltest2(careful you must use the internal model name so forTest2usetest2)
belonging to the apptest1you’ll use{% set_urls_for_scaffold "test1" "test2" as url_names %}and then you could use the attributeslist, create, detail, update, deleteof that object to reverse and get the corresponding urls, for example
use{% url url_names.list }to get the url for list.There’s also a similar API function namedget_url_names thatyou can use to get the urls for your scaffolds.For example, you can do something like:fromgeneric_scaffoldimportget_url_namesfromdjango.core.urlresolversimportreversenames=get_url_names(prefix='test')list_url=reverse(names['list'])Please notice above that if you need to call the above template tag or function with the prefix you need to pass the parameter name i.e call it like{% set_urls_for_scaffoldprefix="my_prefix"as url_names %}.Finally, if for some reason you’d prefer to access the url name directly without using the above you can generate the url name of a scaffolded view yourself using the following algorithm:{prefix}_{app_name}_{model_name}_{method}where the method is one of list/create/update/detail/delete. This could then be used directly with{% url %}orreverse.Sample configurationA sample config that uses a different form (TestForm), defines different behavior using mixins for create and update and needs a logged in user for update / delete / create (but anonymous users can list and detail) is the following:fromdjango.contrib.auth.decoratorsimportlogin_requiredclassTestCrudManager(CrudManager):prefix='test'model=models.TestModelform_class=forms.TestFormcreate_mixins=(CreateMixin,)update_mixins=(UpdateMixin,)permissions={'update':login_required,'delete':login_required,'create':login_required,}Django/python version supportAs can be seen from tox.ini, the tests are run for Python 2.7 with Django
1.8-1.11 and for Python 3.8 and Python 3.11 with Django 1.11-4.2, so these are the
supported versions. Intermediate versions should also work without problems.Python Django Version SupportPython VersionDjango Version2.71.8-1.113.8+1.11-4.2Some trickery for django-generic-scaffoldHere are some more tricks and advice to make even better usage of this package:For a model calledCompanyI would use a prefix“companies/”(notice the slash at the end). This may seem a little strange at first but it creates nice looking urls like:/companies/(for list),/companies/detail/3(for detail) etc.Add aget_absolute_urlmethod to your models to avoid having to declare where to redirect after a successful post when creating/editing instances. For example for the same Company model I’d do it like this:fromgeneric_scaffoldimportget_url_namesclassCompany(models.Model):defget_absolute_url(self):returnreverse(get_url_names(prefix='companies/')['detail'],args=[self.id])Continuing the aboveCompanyexample you could add the following template tag to the company related templates:{%loadgeneric_scaffold_tags%}[...]{%set_urls_for_scaffoldprefix="companies/"asco_url_names%}And then you’d be able to access the urls like:{% url co_url_names.list %}or{% url co_url_names.detail %}.As mentioned above, If for some reason you’d prefer to access the url name directly you can generate yourself using the following algorithm:{prefix}_{app_name}_{model_name}_{method}. Thus for ourCompanyexample, if the app name is calledcorethe name of the list view would becompanies/_core_company_detail(notice that the prefix iscompanies/).Sometimes django-generic-scaffold creates more views than you’d like! For example, for various reasons I usually avoid having delete views. Also for small models you may don’t need a detail view. To “disable” a view you can use the following simple mixin:fromdjango.core.exceptionsimportPermissionDeniedclassNotAllowedMixin(object,):defget_queryset(self):raisePermissionDeniedThen when you define yourCrudManageruse that as the mixin for your method, for example if you want to disable delete you’ll add:delete_mixins = (NotAllowedMixin, ). I guess it would be better if theCrudManagerhad a way to actually define which methods you need but this solution is much easier (for me) :)If you want to change the fields that appear in the Create/Update views you’ll need to define aform_class. Without it all fields will be visible.You’ll probably need to fix your query to avoid n+1 problems. This can easily be done with a mixin like this:classFixQuerysetMixin(object,):defget_queryset(self):returnsuper(FixQuerysetMixin,self).get_queryset().select_related('field1','field2')You can then add that mixin to either yourCrudManagercorrespondinglist_mixinsordetail_mixinslist.My list viewsalwaysuse a table (fromhttps://github.com/jieter/django-tables2) and a filter (fromhttps://github.com/carltongibson/django-filter). If you want to move your DRYness to the next level, you can add the following mixin to your CrudManager’slist_mixinsto auto-add both a table and a filter to your list view:importfilters,tablesclassAddFilterTableMixin(object,):defget_context_data(self,**kwargs):context=super(AddFilterTableMixin,self).get_context_data(**kwargs)qs=self.get_queryset()filter=getattr(filters,self.model.__name__+'Filter')(self.request.GET,qs)table=getattr(tables,self.model.__name__+'Table')(filter.qs)RequestConfig(self.request,paginate={"per_page":15}).configure(table)context['table']=tablecontext['filter']=filterreturncontextThis will try to find afilters.XFilterandtables.XTableclass in thefiltersandtablesmodules (you need to import them ofcourse). So if your model name isCompanyit will use theCompanyFilterandCompanyTableclasses!Now this could be made even more DRY by using sometypemagic to auto-generate the table and filer class on the fly; however I’ve concluded that you’ll almost always need to configure them to define which fields to display at the table and which fields to use at te filter so I don’t think it’s really worth it.Changelogv.0.5.7Add Django 4.1 and 4.2 to tox.iniv.0.5.6Add Django 4.0 to tox.iniv.0.5.5Add Django 3.0 to tox.iniv.0.5.4Add Django 2.2 to tox.iniDrop support for Django < 1.8v.0.5.3Add Django 2.1 to tox.iniv.0.5.2Upload readme to pypiv.0.5.0Add support for Django 2v.0.4.1Add support for Django 1.11v.0.4.0Add support for Django 1.10Allow overriding the parent classes of all viewsv.0.3.3Fix bug with django 1.9 not containing the (url) patterns functionv.0.3.2Include templates in pip package (old version did not include them due to wrong setup.py configuration)v.0.3.1Fix bug with ‘__all__’ fields when adding form_classv.0.3.0Drop support for Django 1.4 and 1.5Add support for python 3 (python 3.5) for Django 1.8 and 1.9v.0.2.0Braking changes for API and template tagsAdd example projectAdd support and configure tox for Django 1.9A bunch of fallback templates have been added (generic_scaffold/{list,detail, form,confirm_delete}.html)Use API (get_url_names) for tests and add it to docsAdd (url) prefix as an attribute to CrudManager and fix templatetag to use it.Prefix has to be unique to make API and template tags easier to useModel also has to be uniquev.0.1.2Add tests and integrate with toxAdd some basic templates (non-empty, mainly for tests)v.0.1.1Add template tags to get crud urlsv.0.1Initial