How to utilize django generic view? - python

For example, I want a page, which will let user add data for different categories of goods.
Like:
Model: Category is foreign key of item
Category1(detail url):
Item 1(detail url):
Date(textbox), Amount(textbox), Price(textbox)
Item 2:
...
Category2:
...
Save button, add more button, etc...
Since this is an example, I what those thing all display in a page.
I don't mind hard writing them with normal functions, but I wonder if I can utilize the views, since if they are so heavily introduced and developed, they might be powerful. So why not utilize it?
Can anyone tell me tricks about how to use them or we shouldn't use them if we want more functionality?

Django's generic views cover a lot of common use cases. For example:
CreateView - a view for creating an instance of a model
UpdateView - a view for updating an existing instance of a model
DeleteView - a view for deleting an existing instance of a model
DetailView - a view for displaying the details of an exsting instance of a model
ListView - a view for displaying a list of instances of a model
There are more around if you need them, and they cover the majority of views you are likely to need. You can also extend them to meet your needs quite easily. As a general rule of thumb, they make such a huge difference to how quickly you can get something built that I would recommend using them by default, and only switching over to writing your own views when absolutely necessary. If you haven't yet learned them, I think doing so will be a very good investment of your time - you will make up the time spent very quickly. For a lot of view types, it's just a case of specifying the model, setting up the URLs and the template, and you're done.
If you need to pass through additional data, then you can extend the generic view in question and override the get_context_data() method. If the same needs to be applied to several different generic views, you can create a mixin that includes that method and include it in that generic view.
For views that include forms, like the CreateView and UpdateView, as Drewness said, you can pass through a ModelForm instance to tell it what form to use, and that form can itself be overriden, so you still have a lot of control over what the form will do. For instance, you might define the following form:
from django.forms import ModelForm
class CategoryForm(ModelForm):
exclude = ['date_created']
And the following view
from django.views.generic.edit import CreateView
class CategoryCreateView(CreateView):
model = Category
form_class = CategoryForm
The Django tutorial covers generic views pretty well.

You can use Django's ModelForm with a FormView.
Then all of the fields in your model will be available in your form and in your form view. You should also look at mixins. Mixins allow you to use combinations of class-based views.
Finally, if you want to use more than one form (model) in a view you can use a FormSet.

Related

Is it necessary to have a model and inheritance in class based views?

class home(ListView):
template_name='blog/base.html'
This doesn't work and gives this error --
ImproperlyConfigured at /
home is missing a QuerySet. Define home.model, home.queryset, or override
home.get_queryset().
but when I create a model with no data
class home(ListView):
model = Post
template_name='blog/base.html'
This works perfectly fine
-> In same way when I don't inherit ListView
class home():
model = Post
template_name='blog/base.html'
It gives the following error in urls.py
from django.urls import path,include
from . import views
from .views import home
urlpatterns = [
# path('',views.home,name='blog-home'),
path('',home.as_view(),name='blog-home')
]
AttributeError: type object 'home' has no attribute 'as_view'
I don't have any idea about both of these
Yes, passing the modal is important in django generic views because ListView inherits from BaseListView which is again inherits from MultipleObjectMixin. The MultipleObjectMixin makes it mandatory to pass modal in the query_set.
See Django code of MultipleObjectMixin to get a better understanding.
I agree to the answer by "Vivek Singh".
But apart from that, your second question where you do not inherit ListView you get the error in urls is because, for as_view() to work, you have to inherit some sort of View class. Such as ListView, DetailView (which come under Generic Views) or just simply View.
In my understanding your questions is rather aiming at "the reason why" and not so much for code:
Django class based ListView/DetailedView etc. are made with the purpose to simplify the typical web pages with a list and details of e.g. products which are stored in a database table (=django model). Thus reducing coding effort. Therefore a model is required that contains the items to list and to detail. If the model given is empty can only be found at runtime when the list page is called an the query is executed - you then just get a web page with an empty product list.
Also inheriting from ListView and defining the model only makes sense if on the rendered html template you use the (automatically) filled context to display the model list.
roughly what happens when you call YourListView.as_view():
-> request
-> dispatch request via urls.py
-> YourListView.as_view()
-> instantiate YourListView with model
-> fill context with query result of the model (!!!)
-> render html template with context
-> return response
(and this is only a small basic example of what ListView can simplify for you)
If you dont need a list/details of a model, there is obviously no need to inherit from those standard views. Then you have simply different needs.
You are free to define your own ClassBased Views, without that functionality provided by ListView etc.
Hope that helps you.

What is the recommended approach to implement admin-actions-alike functionality outside admin?

I've been searching a way to reproduce admin-actions behavior on my own tables using django-tables2. I haven't found any module to introduce this functionality to a ListView to derive from it and looking at ModelAdmin I see there are many methods implied on this.
Of course, I can add a form around my table to get the checkboxes and a submit button pointing to a view that works with the ids but I'm looging to get a combo to choose among different actions as in django-admin but also to have that 'actions' meta option to list some methods as the possible actions to perform.
I found django-actions which is still very young but also it introduces it's own page for operations and I just need to integrate functionality on my own model so I can connect some input type=select with the model actions.
Any comment is appreciated :)
There is no built-in solution for it. You have to implement your actions in your views and the functionality to your templates.
Add, edit and delete operations are very easy to implement in your views.py. This depends on your models, but you can trigger database manipulations from within your templates and keep the logic in your views.py.
You can also easily add a form to your templates as it is described in the docs:
# forms.py
from django.forms import ModelForm
from myapp.models import Article
# Create the form class.
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['pub_date', 'headline', 'content', 'reporter']
model := Choose your model which you want to modify / add
fields := Select some fields from your model, which you want to show up in your form
This defines a form corresponding to your model, which can be used in your templates to modify or add an entity to your database.

Django form to create several objects with one-to-one relation

I have several models with one-to-one relation. For example
class Task(models.Model):
initial_comment = models.OneToOneField('Comment')
# A pack of other fields
class Comment(models.Model)
body = RichTextField()
# A pack of other fields
I want to create "create view" based on form, that gives user ability to create task and initial comment there.
I can't use CreateView because it is based on only one model
I can't use ModelForm because it is based on only one model
I can create several forms, but I can't join them into one formset (forms are different)
I feel "inlineformset_factory" (InlineFormSet) should be used here, but I am not sure it suits best. Is there any 3rd party Django app to do that?
Sure I can create form myself, but I do not want to copy/paste all fields, their types, localized labels, validations and so on. I just want to list their names (like fields attibute).
I can also have 2 forms and support them everywhere and track dependencies manually (save comments first), like in How can create a model form in django with a one-to-one relation with another model , but I hope there has to be better solution.
If you wonder why do I need one-to-one: Comments are used heavily in other places and have different relations with different models.
The inline_formset factory is correct. There are no standard generic views for this, but there is a third party package with generic views to do what you are wanting. Its in the standard Django way of doing things.
https://github.com/AndrewIngram/django-extra-views
You probably want to use the CreateWithInlinesView for that.
Well, I found solution.
CreateWithInlinesView works perfectly with OneToOneField (after all, 1-to-1 is just a foreign key with constraint), but my main model here is Comment, not Task. So I should set Comment as model field in this view and Task as inline. It looks silly. I will create custom form or review my model structure.

Why does one need to register both app name and app admin name in Django admin?

I am trying to understand why, when adding a custom Admin site for a django app, one needs to add both the model and the admin function. Say, you have an application called Story, and thus the admin site will be called StoryAdmin. When registering this on the django administration interface, you need to add this line:
# Registering all the changes to admin.site
admin.site.register(Story, StoryAdmin)
My question is, is there a way to just do this:
admin.site.register(StoryAdmin)
Adding only one thing, not two, because this makes things simpler, and there is a smaller chance for an error, and the code just looks less redundant. It would make things look much better, because in the end, you could have a clean list of all the admin panels:
admin.site.register(
StoryAdmin,
SomeAdmin,
FooAdmin,
)
That's not how admin.site.register is built. It expects a Model and then optionally the ModelAdmin with which to display that Model:
def register(self, model_or_iterable, admin_class=None, **options):
"""
Registers the given model(s) with the given admin class.
The model(s) should be Model classes, not instances.
If an admin class isn't given, it will use ModelAdmin (the default
admin options). If keyword arguments are given -- e.g., list_display --
they'll be applied as options to the admin class.
If a model is already registered, this will raise AlreadyRegistered.
If a model is abstract, this will raise ImproperlyConfigured.
"""
This allows you to use the same ModelAdmin on multiple Models (which can be desirable when, for example, you subclass a model off the same abstract Model).
It doesn't suit your style but it's just one of those things you just have to accept and get on with.
That's a good question, it could have been designed that way, but that's not the case.
I asume the main reason is to allow the admin class to be optional and use the default base ModelAdmin class for simple cases and to allow to use the same ModelAdmin subclass with many models, see implementation at: https://github.com/django/django/blob/master/django/contrib/admin/sites.py#L52-101
Also you don't need to define the class yourself if you need to customize a ModelAdmin, you can just pass kwargs to the register function:
admin.site.register(Story, list_display=['field1', 'field2'])
So that's my bet, they try to minimize the boilerplate when registering a model and allow it to be more flexible.

Django: user profile creation forms

As I've understood the deal, the standard way of extending the User Django model is by implementing profiles.
This suits me wonderfully, since I have 3 types of profiles (3 different Model subclasses) all based upon the User model for uniqueness and authentication.
I'm having trouble deciding, however, on the best way of implementing a user creation form. Should I...
Use mixins: inherit a ModelForm with model=User and one with model=Profile, manually overriding save() and clean() to call the bases' methods and perform the foreign key assignment.
Use composition: inherit Form and manually instantiate and manage two ModelForms.
Instantiate the forms separately, and save() them in a manually ordered fashion.
The Best Way I Didn't Think Of.
I would appreciate a (however minimal) implementation so I can be sure I'm making the right calls.
Thanks in advance.
You can write a single form that acts as a combined ModelForm for both your Profile model and the contrib User model. To accomplish this, a little manipulation of the forms kwargs on init is required. See this snippet: http://djangosnippets.org/snippets/2081/

Categories