Two model in one UpdateView "Django" - django

my views :
from .models import Settings, SocialMediaSetting
class UpdateSocialMediaSetting(LoginRequiredMixin, UpdateView):
model = SocialMediaSetting
fields = '__all__'
template_name = "staff/settings/social-media-settings-update.html"
class UpdateSettings(LoginRequiredMixin, UpdateView):
model = Settings
fields = '__all__'
template_name = "staff/settings/settings-update.html"
two different class in models without any relation, I want show both in one html and one form both models has just one object

you'll need to ditch the UpdateView, but this way won't take long to implement
Use a TemplateView (at least you won't have to change your other mixin)
Create two ModelForms
override the get_context_data() to pass the forms to the template
when forms are submitted, override the post() method to save them yourself
mchesler613 wrote an awesome article explaining how to do this here.
(make sure to give him a star)

Related

How to overwrite clean and clean_fieldname for ModelFormMixin

I found this
How to properly overwrite clean() method
and this
Can `clean` and `clean_fieldname` methods be used together in Django ModelForm?
but it seems to work differently if one is using the generic class mixins ModelFormMixin.
My class is also derived from ProcessFormView.
Is def form_valid(self, form): the only point where I can overwrite the form handling process?
You are confusing views and forms. A CreateView for example makes use of a ModelForm to create an object. But instead of letting the view construct the ModelForm, you can specify such form yourself and then pass this as form_class to the view.
For example say you have a Category model with a name field, and you wish to validate that the name of the Category is all written in lowercase, you can define a ModelForm to do that:
from django import forms
from django.core.exceptions import ValidationError
class CategoryForm(forms.ModelForm):
def clean_name(self):
data = self.cleaned_data['recipients']
if not data.islower():
raise ValidationError('The name of the category should be written in lowercase')
return data
class Meta:
model = Category
fields = ['name']
now we can plug in that ModelForm as form for our CategoryCreateView:
from django.views.generic import CreateView
class CategoryCreateView(CreateView):
model = Category
form_class = CategoryForm
The validation thus should be done in the ModelForm, and you can then use that form in your CreateView, UpdateView, etc.

Django admin: postgres DateTimeRangeField not displayed properly

Some of my models have postgres-specific django.contrib.postgres.fields.DateTimeRangeFields, and those fields are exposed in the corresponding admin panels. I expected that the ranges forms would consist of two Django-style datetime pickers, with a separate one for the date part and a separate part for the time part (just like the DateTimeField would). However, I get two text inputs which expect input in a very particular format. Is there anything I am missing or have to configure separately?
The relevant code is:
from django.contrib.postgres.fields import DateTimeRangeField
...
class MyModel(models.Model):
time_off = DateTimeRangeField()
admin:
#register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
pass
You are looking for SplitDateTimeWidget.
Simply change the admin part as:
class MyModelAdminForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'time_off': RangeWidget(SplitDateTimeWidget())
}
#register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
form = MyModelAdminForm
or use formfield_overrides to override the widget if you wish.

Django model form cant use two modelforms

I was wondering how i can use two models in a modelform
I tried :
from django import forms
from .models import Question, Choice
class CreateQuestionForm(forms.ModelForm):
class Meta:
model = question, choice
Fields = [
'question'
'choice_text
]
You have to use formsets in order to use two different forms in the same.
Firstly, you have to define each form from their models.
Then, you can use formset_factory to combine both forms.

Update two or more models at same time with UpdateView

Is there some way to update two or more models at the same time with UpdateView? For example having this:
class PEEncargadoView(UpdateModelMixin,UpdateView):
model = Encargado
form_class = FormEncargado
success_url = '/'
template_name = 'productores/PE/encargado.html'
Update other models besides of Encargado but in this same view
I know that this could be possible overriding get_context_data, but exactly how? if I don't need to pass any variables to the template.
you can't do it with UpdateModelMixin - it's designed for working with a single model.
This question shows how to work with multiple forms in CBV: Django: Can class-based views accept two forms at a time?.
Django has formsets https://docs.djangoproject.com/en/1.8/topics/forms/formsets/ which can be used together with ModelForm to allow edition of multiple models on one page.

Dynamical choices in model's field

I want my models to have order field, which will contain order of an item among all items of its kind.
And I want to use choices within that IntegerField, which would contain all the numbers of currently existing items in that table.
So it would need to be dynamic choices.
How do I load all existing "order" values of all existing items in a table, and use this list for choices?
It sounds like you want to build a manager for your model:
models.py
from django.db import models
class OrderManager(models.Manager):
def order_choices(self):
return [(i, i) for i in OrderModel.objects.values_list('order', flat=True)]
class OrderModel(models.Model):
objects = OrderManager()
order = models.IntegerField()
class Meta:
ordering = ['order']
def __unicode__(self):
return '%i' % self.order
forms.py
from django import forms
from yourapp.models import OrderModel
class OrderModelForm(forms.ModelForm):
order = forms.ChoiceField(choices=OrderModel.objects.order_choices())
class Meta:
model = OrderModel
admin.py
from django.contrib import admin
from yourapp.forms import OrderModelForm
from yourapp.models import OrderModel
class OrderModelAdmin(admin.ModelAdmin):
form = OrderModelForm
admin.site.register(OrderModel, OrderModelAdmin)
Edit
Managers are use to make general model queries without having an instance of a model object. If you don't understand the concept of managers, you can still refactor the code out of the manager class, stick it somewhere else and import that function across your code. Managers allow you to abstract custom general queryset that you can reuse. See more details https://docs.djangoproject.com/en/dev/topics/db/managers/
The code without the manager will look like
views.py or some other file
from app.models import OrderModel
def order_choices():
return [(i, i) for i in OrderModel.objects.values_list('order', flat=True)]
From anywhere in your code, if you want to reuse the above multiple times:
from app.views import oder_choices
order_choices()
as opposed to:
from app.models import OderModel
OrderModel.objects.order_choices()
If you only want to use the above once, you can leave it in the forms.py as shown in the other answer. It's really up to you on how you want to refactor your code.
Dont add the choices directly to the model, add them to a form represnting the model later, by overriding the field with a set of choices.
than, do something like:
class MyForm(..):
myfield_order_field = IntegerField(choices = [(i,i) for range(MyModel.objects.count)])
class Meta():
model = MyModel
if you want to use it in the admin, add to your Admin Class:
class MyModelAdmin(admin.ModelAdmin):
...
form = MyForm
it will override this field in the admin too.