I am having trouble posting data in an admin form. Some fields get empty after clicking the save button, others not (the inlines are keeping their data). See the images for a better explanation of the problem.
Entering some data:
After clicking on [save]...
Validation error! (The model is not saved)
My ModelForm is quite simple: I am just changing the form field for one of the m2m model fields.
class News(models.Model):
departments = models.ManyToManyField(Department, blank=True, related_name='news', through='NewsDepartmentMembership')
research_groups = models.ManyToManyField(Group, blank=True, related_name='news', through='NewsGroupMembership')
related_news = models.ManyToManyField('self', blank=True, symmetrical=False)
people_involved = models.ManyToManyField(Person, blank=True, related_name='news')
title = models.CharField(_('Title'), max_length=255)
slug = models.SlugField(_('Slug'), unique_for_date='pub_date',
help_text=_('A slug is a short name which uniquely identifies the news item for this day'), )
excerpt = RichTextField(_('Excerpt'), blank=True)
content = RichTextField(_('Content'), blank=True)
is_published = models.BooleanField(_('Published'), default=False)
pub_date = models.DateTimeField(_('Publication date'), default=datetime.datetime.now)
is_feat = models.BooleanField(
_('Featured'), default=False,
help_text=_('Administrators may use this checkbox to promote news to the main news page')
)
published = PublishedNewsManager()
objects = models.Manager()
featured = FeaturedNewsManager()
class NewNewsForm(forms.ModelForm):
class Meta:
model = News
related_news = forms.ModelMultipleChoiceField(
queryset=News.objects.none(),
required=False,
widget=FilteredSelectMultiple(
verbose_name=_('articles'),
is_stacked=False,
)
)
def __init__(self, user=None, *args, **kwargs):
super(NewNewsForm, self).__init__(*args, **kwargs)
if hasattr(user, 'is_superuser'):
self.fields['related_news'].queryset = get_objects_for_user(user, ('news.change_news',)).filter(
is_published__exact=True).order_by('pub_date')
else:
self.fields['related_news'].queryset = News.published.order_by('pub_date')
if self.instance.pk:
self.fields['related_news'].initial = self.instance.related_news.all()
def save(self, commit=True):
news = super(NewNewsForm, self).save(commit=False)
if commit:
news.save()
if news.pk:
news.related_news = self.cleaned_data['related_news']
self.save_m2m()
return news
The ModelAdmin is quite complicated, it inherits 2 ModelAdmins. The 1st one comes from the django-modeltranslation package. I adapted the 2nd one from here, just to perform cross inline formsets validation. It's working in other packages without any problem (at least until today). I just have to override the method is_cross_valid to define the cross inline validation
class NewsAdmin(TranslationAdmin, ModelAdminWithInlines):
fields = ('title', 'slug_en', 'slug_nb', 'excerpt', 'content', 'is_published', 'pub_date', 'related_news', 'is_feat')
inlines = (DepartmentsNewsInline, GroupsNewsInline, PersonNewsInline)
form = NewNewsForm
prepopulated_fields = {'slug_en': ('title',), 'slug_nb': ('title',)}
class Media:
js = (
'http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.1/jquery-ui.min.js',
'modeltranslation/js/tabbed_translation_fields.js',
)
css = {
'screen': ('modeltranslation/css/tabbed_translation_fields.css',),
}
def queryset(self, request):
return get_objects_for_user(request.user, (u'news.change_news', ))
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
if db_field.name == 'related_news':
return get_objects_for_user(request.user, ('news.change_news',), ).order_by('pub_date')
return super(NewsAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)
def is_cross_valid(self, request, form, formsets):
valid = True
# my validation code goes here...
return valid
def get_readonly_fields(self, request, obj=None):
if not request.user.groups.filter(name__exact='administration') and not request.user.is_superuser:
return ('is_feat', )
return ()
def has_change_permission(self, request, obj=None):
if super(NewsAdmin, self).has_change_permission(request, obj):
return True
return request.user.has_perm('news.change_news', obj)
This is my ModelAdminWithInlines, almost the same as here:
class ModelAdminWithInlines(ModelAdmin):
"""
Cross formsets validation. See https://stackoverflow.com/a/2746735
"""
def is_cross_valid(self, request, form, formsets):
"""
To perform cross-formset validation.
Should be overriden in every inheriting class.
"""
return True
def add_view(self, request, form_url='', extra_context=None):
"""The 'add' admin view for this model."""
model = self.model
opts = model._meta
if not self.has_add_permission(request):
raise PermissionDenied
ModelForm = self.get_form(request)
formsets = []
inline_instances = self.get_inline_instances(request, None)
if request.method == 'POST':
form = ModelForm(request.POST, request.FILES)
if form.is_valid():
new_object = self.save_form(request, form, change=False)
form_validated = True
else:
form_validated = False
new_object = self.model()
prefixes = {}
for FormSet, inline in zip(self.get_formsets(request), inline_instances):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1 or not prefix:
prefix = "%s-%s" % (prefix, prefixes[prefix])
formset = FormSet(data=request.POST, files=request.FILES,
instance=new_object,
save_as_new="_saveasnew" in request.POST,
prefix=prefix, queryset=inline.queryset(request))
formsets.append(formset)
# if all_valid(formsets) and form_validated:
formsets_validated = all_valid(formsets)
cross_validated = self.is_cross_valid(request, form, formsets)
if formsets_validated and form_validated and cross_validated:
self.save_model(request, new_object, form, False)
self.save_related(request, form, formsets, False)
self.log_addition(request, new_object)
return self.response_add(request, new_object)
else:
# Prepare the dict of initial data from the request.
# We have to special-case M2Ms as a list of comma-separated PKs.
initial = dict(request.GET.items())
for k in initial:
try:
f = opts.get_field(k)
except FieldDoesNotExist:
continue
if isinstance(f, ManyToManyField):
initial[k] = initial[k].split(",")
if ModelForm.Meta.model._meta.module_name == 'news' and ModelForm.Meta.model._meta.object_name == 'News':
form = ModelForm(initial=initial, user=request.user) # here I am injecting the user object into the form
# just to be able to access the objects for this user
else:
form = ModelForm(initial=initial)
prefixes = {}
for FormSet, inline in zip(self.get_formsets(request), inline_instances):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1 or not prefix:
prefix = "%s-%s" % (prefix, prefixes[prefix])
formset = FormSet(instance=self.model(), prefix=prefix,
queryset=inline.queryset(request))
formsets.append(formset)
adminForm = AdminForm(
form, list(self.get_fieldsets(request)),
self.get_prepopulated_fields(request),
self.get_readonly_fields(request),
model_admin=self)
media = self.media + adminForm.media
inline_admin_formsets = []
for inline, formset in zip(inline_instances, formsets):
fieldsets = list(inline.get_fieldsets(request))
readonly = list(inline.get_readonly_fields(request))
prepopulated = dict(inline.get_prepopulated_fields(request))
inline_admin_formset = InlineAdminFormSet(
inline, formset, fieldsets, prepopulated, readonly, model_admin=self
)
inline_admin_formsets.append(inline_admin_formset)
media = media + inline_admin_formset.media
context = {
'title': _('Add %s') % force_text(opts.verbose_name),
'adminform': adminForm,
'is_popup': "_popup" in request.REQUEST,
'media': media,
'inline_admin_formsets': inline_admin_formsets,
'errors': AdminErrorList(form, formsets),
'app_label': opts.app_label,
}
context.update(extra_context or {})
return self.render_change_form(request, context, form_url=form_url, add=True)
I really can't understand the source of my problem. Can anyone spot the issue?
Thanks!
UPDATE
As #GarryCairns suggested, I've tried to save an object from the shell. No problem with that.
>>> n = News.objects.create(title_en='test', slug_en='test', content_en='test')
>>> n.id
4
UPDATE 2:
Non translated fields are empty as well :-/
UPDATE 3:
>>> n = News()
>>> n
<News: >
>>> n.title_en = 'test'
>>> n.slug_en
>>> n.slug_en = 'test'
>>> n.content_en = 'blah blah'
>>> n.save()
>>> n.id
5
FIXED
It seems that both setting the ModelMultipleChoiceField queryset manually from the form init() and the NewsAdmin.formfield_for_manytomany() method were messing up the whole form data...
Related
I use django-cities-light for a travel website and I would like to filter the cities in the fields ville_de_depart and ville_destination in the newBookingForm by trip.depart and trip.destination.
I tried to pass the trip object in the instance of newBookingForm. I override the __init__ and I took the value of the depart and destination, I succeeded in filtering the fields but I could no longer save the newBooking, the view redirect to the alltrip page with no error but no new booking is added to the database.
I tried to replace the trip by the slug which is the same value as the id and it shows me this error
'int' object has no attribute '_meta'
models.py
class trip(models.Model):
depart = models.ForeignKey(default='',to=Country,on_delete=models.CASCADE,related_name='depart')
destination = models.ForeignKey(default='',to=Country,on_delete=models.CASCADE)
date_de_depart = models.DateField(default='')
prix_kg = models.PositiveIntegerField(default='')
collecte = models.BooleanField(default=False,null=False,help_text='' )
creation_date = models.DateTimeField(auto_now=True)
author = models.ForeignKey(to=settings.AUTH_USER_MODEL,on_delete=models.CASCADE,default='')
slug = models.SlugField(max_length=100, default='' )
#jouter slug
def save(self, *args , **kwargs):
super(trip, self).save(*args , **kwargs)
if not self.slug:
self.slug = self.id
self.save()
def __str__(self):
return f'{self.id} {self.author} '
class Booking(models.Model):
trip = models.ForeignKey(trip,on_delete=models.CASCADE, default='',)
author = models.ForeignKey(to=settings.AUTH_USER_MODEL,on_delete=models.CASCADE,default='')
creation_date = models.DateTimeField(auto_now=True)
ville_de_depart = models.ForeignKey(City,on_delete=models.CASCADE,default='')
slug = models.SlugField(max_length=100, default='' )
# ville_depart = models.ForeignKey(default='',to=City,on_delete=models.CASCADE,related_name='ville_dep')
sender_phone = PhoneNumberField(blank=True)
receiver_phone = PhoneNumberField()
ville_destination = models.ForeignKey(default='',to=City,on_delete=models.CASCADE,related_name='ville_dest')
#jouter slug
def save(self, *args , **kwargs):
super(Booking, self).save(*args , **kwargs)
if not self.slug:
self.slug = self.id
self.save()
def __str__(self):
return str(self.trip.author)
views.py
def detailsTrip(request, slug):
trip = get_object_or_404(models.trip,slug=slug)
auth = trip.author
bookingForm = newBookingForm(instance=slug)
context = {'trip': trip, 'auth': auth, 'form': bookingForm}
if request.method == 'POST':
form = newBookingForm(request.POST , instance=slug )
if request.user.is_authenticated:
if form.is_valid():
trip = get_object_or_404(models.trip,slug=slug)
Booking = form.save(commit=False)
Booking.trip_id= trip.id
Booking.author_id = request.user.id
Booking = form.save()
return redirect('/alltrips')
else:
trip = get_object_or_404(models.trip,slug=slug)
auth = trip.author
bookingForm = newBookingForm()
context = {'trip': trip, 'auth': auth, 'form': bookingForm}
return render(request, 'detailstrip.html', context)
else:
return render (request, 'notFound.html')
return render(request,'detailstrip.html', context , )
forms.py
class newBookingForm(forms.ModelForm,):
def __init__(self,*args,**kwargs):
# capture the instance : Slug
slug = kwargs.get('instance')
# capture current trip
Trip = get_object_or_404(trip, id=slug)
# Filter cities field by the instance : trip.depart / trip.destination
super(newBookingForm, self).__init__(*args,**kwargs)
self.fields['ville_de_depart'].queryset = City.objects.filter(country_id=Trip.depart)
self.fields['ville_destination'].queryset = City.objects.filter(country_id=Trip.destination)
class Meta:
model = Booking
fields = ['ville_de_depart','ville_destination']
exclude = ['sender_phone','receiver_phone']
solution
#view.py
def detailsTrip(request, slug):
trip = get_object_or_404(models.trip,slug=slug)
auth = trip.author
#add the trip to the form
bookingForm = newBookingForm(trip=trip)
context = {'trip': trip, 'auth': auth, 'form': bookingForm}
if request.method == 'POST':
#add the object trip to the form here too
form = newBookingForm(trip,request.POST )
if request.user.is_authenticated:
if form.is_valid():
trip = get_object_or_404(models.trip,slug=slug)
Booking = form.save(commit=False)
Booking.trip_id= trip.id
Booking.author_id = request.user.id
Booking = form.save()
return redirect('/alltrips')
else:
trip = get_object_or_404(models.trip,slug=slug)
auth = trip.author
bookingForm = newBookingForm()
context = {'trip': trip, 'auth': auth, 'form': bookingForm}
return render(request, 'detailstrip.html', context)
else:
return render (request, 'notFound.html')
return render(request,'detailstrip.html', context , )
form.py
class newBookingForm(forms.ModelForm,):
class Meta:
model = Booking
fields = ['ville_de_depart','ville_destination']
exclude = ['sender_phone','receiver_phone']
def __init__(self,trip,*args,**kwargs):
# Filter cities field by trip.depart / trip.destination
super(newBookingForm, self).__init__(*args,**kwargs)
self.fields['ville_de_depart'].queryset = City.objects.filter(country=trip.depart)
self.fields['ville_destination'].queryset = City.objects.filter(country=trip.destination)
As long as you use many-to-many fields, you need to call form.save_m2m() after saving the model instance. or you can just call form.save() without commit=False keyword argument.
Here are some quotes from Django documentation:
This save() method accepts an optional commit keyword argument, which accepts either True or False. If you call save() with commit=False, then it will return an object that hasn’t yet been saved to the database.
Another side effect of using commit=False is seen when your model has a many-to-many relation with another model. If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation.
read this documentation about the save method
I need to display just the selected value from a forms.ModelChoiceField on a view page. How would I do that?
I've looked at many different forums and couldn't get a clear answer on what I should do in my case. I am new at Python.
form:
class Manufacturer1Form(ReadOnlyFormMixin, ModelForm):
manufacturer = forms.ModelChoiceField(queryset=Vendor.objects.filter(vendor_type='manufacturer').order_by('name'))
class Meta:
model = Manufacturer1Relationship
exclude = ('part',)
model:
class Manufacturer1Relationship(models.Model):
part = models.ForeignKey(Part, on_delete=models.CASCADE)
manufacturer = models.ForeignKey(Vendor, on_delete=models.CASCADE,
limit_choices_to={'vendor_type': 'manufacturer'},)
partNumber = models.CharField(max_length=40, blank=True)
class Meta:
permissions = (
('modify_admin_site', 'Can modify, add, view, or delete manufacturer relationships'),
)
view:
def PartView(request, type_id, id):
partType = Type.objects.get(id=type_id)
instance = get_object_or_404(Part, id=id)
selection = None
if request.method == 'POST':
form = ViewPartForm(type_id, request.POST, request.FILES, instance=instance)
manu1_formset = ManufacturerFormSet(request.POST, instance=instance)
location1_formset = LocationFormSet(request.POST, instance=instance)
if form.is_valid():
selection = form.cleaned_data['active_feed']
part = form.save(commit=False)
part.partType_id = type_id
if manu1_formset.is_valid() and location1_formset.is_valid():
part.save()
manu1_formset.save()
location1_formset.save()
url = reverse('list_parts', args=[partType.pk])
return HttpResponseRedirect(url)
else:
form = ViewPartForm(type_id=type_id, instance=instance)
manu1_formset = ManufacturerFormSet(instance=instance)
location1_formset = LocationFormSet(instance=instance)
return render(request, 'part_view.html', {'view_part_form': form,
'location_formset': location1_formset,
'manu_formset': manu1_formset,
'selection': selection,
'partType': partType,
'part': instance})
class Manufacturer1Form(ReadOnlyFormMixin, ModelForm):
manufacturer = forms.ModelChoiceField(queryset=Vendor.objects.filter(vendor_type='manufacturer').order_by('name'))
class Meta:
model = Manufacturer1Relationship
exclude = ('part',)
def __init__(self, *args, **kwargs):
initial_manufacturer = kwargs.pop("manufacturer",None)
super().__init__(*args, **kwargs)
self.fields["manufacturer"].initial = initial_manufacturer
ManufacturerFormSet(request.POST, instance=instance, manufacturer=specific_manufacturer)
I would like to share with you my code in order to find a solution. I have a Django form. I would like to save data only if there is not another object with same data. In other words, objects should be unique.
If the object doesn't exist, I save it, else I display the form with an error message 'The object already exists with this features'.
This is my model:
def guide_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/guides/<guide_id>
new_filename = f'guides/{instance.site.id}'
if instance.profile_type:
new_filename += f'_{instance.profile_type}'
if instance.profile_level:
new_filename += f'_{instance.profile_level}'
if instance.language:
new_filename += f'_{instance.language}'
name, ext = os.path.splitext(filename)
if ext:
new_filename += ext
return new_filename
class UserGuide(models.Model):
""" A class for storing user guides depending on profiles """
objects = models.Manager()
site = models.ForeignKey(WebApplication, on_delete=models.PROTECT, related_name='guides',
verbose_name=_('application'))
file = models.FileField(verbose_name='file', upload_to=guide_path)
profile_type = models.CharField(verbose_name=_('profile type'), choices=UserProfile.USER_TYPES, max_length=2,
null=True, blank=True)
profile_level = models.CharField(verbose_name=_('profile level'), choices=UserProfile.USER_ROLES, max_length=2,
null=True, blank=True)
language = models.CharField(verbose_name=_('language'), choices=settings.LANGUAGES, max_length=2, default='en')
class Meta:
verbose_name = _('user guide')
verbose_name_plural = _('user guides')
unique_together = ('site', 'profile_type', 'profile_level', 'language')
This is my form:
class UserGuideForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
class Meta:
model = UserGuide
fields = ['site', 'file', 'profile_type', 'profile_level', 'language']
widgets = {
'file': CustomFileInput(attrs={'class': 'clearablefileinput'}),
}
And this is my view:
class UserGuideUpdateView(UpdateView):
""" Display a form to create a userguide
**Context**
``subtitle``
Title of the page
**Template:**
:template:`app/generic_form.html`
"""
model = UserGuide
form_class = UserGuideForm
success_url = reverse_lazy('userguide-list')
template_name = 'app/form_userguide.html'
permission_required = 'app.change_userguide'
def get_object(self, queryset=None):
pk = self.kwargs.get('pk')
return get_object_or_404(UserGuide, pk=pk)
def get_title(self):
return _('Edit user guide: ')
def get_context_data(self, **kwargs):
context = super(UserGuideUpdateView, self).get_context_data(**kwargs)
context.update({
'subtitle': self.get_title(),
})
return context
def form_valid(self, form):
site = form.cleaned_data['site']
file = form.cleaned_data['file']
profile_type = form.cleaned_data['profile_type']
profile_level = form.cleaned_data['profile_level']
language = form.cleaned_data['language']
userguide = UserGuide.objects.filter(site=site.id, profile_type=profile_type, profile_level=profile_level, language=language)
if userguide.exists():
messages.error(self.request, _('A user guide for that profile and language already exists'))
HttpResponseRedirect(self.template_name)
else:
pass
return super().form_valid(form)
How I can add condition, if my object already exists, not save the form and return the form with the error message ?
Thank you
I got a tracking model, and an evidence model wit ha foreign to it. Im trying to upload a file in evidence related to that tracking...but when i try to save i got this error:
Request Method: POST
Request URL: http://127.0.0.1:8000/myapp/change_actions/tracking/create/1/
Django Version: 1.10.1
Exception Type: RelatedObjectDoesNotExist
Exception Value:
Evidence has no tracking.
My view saves tracking form and then passes the id of that record to the evidence form as foreign.....but that error is like the form was eliminating the tracking field !!....these are my files :
Models.py
class Tracking(ModelBase):
activity = models.ForeignKey(
Activity,
verbose_name = 'Actividad', null = False)
code = models.CharField('Codigo de seguimiento', max_length=50)
observation = models.TextField('Avance a la fecha', max_length=2000)
tracking_date = models.DateTimeField('Fecha de seguimiento')
def __str__(self):
return self.observation
class Evidence(ModelBase):
tracking = models.ForeignKey(
Tracking,
related_name = 'Tracking_evidence',
verbose_name = 'Seguimiento', null = False)
evidence = models.FileField(verbose_name = 'Evidencia', null = True, upload_to='documents/')
This is the form.py:
class EvidenceForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.tracking = kwargs.pop('tracking')
super(EvidenceForm, self).__init__(*args, **kwargs)
def clean(self, *args, **kwargs):
cleaned_data = super(EvidenceForm, self).clean()
self.instance.tracking.id = self.tracking
class Meta:
model = Evidence
fields = ['tracking', 'evidence']
And the view to it :
class TrackingCreateView(View):
template_name = ['change_actions/tracking_create.html']
breadcrumb = [{'name': 'Registro de seguimiento', 'url': None}]
#method_decorator(login_required)
def get(self, request, *args, **kwargs):
form = TrackingForm()
form_evidence = EvidenceForm(tracking = None)
activity = Activity.objects.get(pk = kwargs['activity_id'])
return render(request, self.template_name,{
'form_tracking': form,'breadcrumb': self.breadcrumb,
'activity': activity,'form_evidence': form_evidence})
def post(self, request, *args, **kwargs):
form = TrackingForm(request.POST)
activity = Activity.objects.get(pk = request.POST['activity_id'])
self.breadcrumb[0]['url'] = reverse(
'change_actions:tracking_create',
kwargs = {'activity_id': activity.id })
context = {
'breadcrumb': self.breadcrumb, 'activity': activity,
'form_tracking': form}
if form.is_valid():
form.save()
form_evidence = EvidenceForm(
request.POST, request.FILES, tracking = form.instance.id)
if form_evidence.is_valid():
form_evidence.save()
messages.success(request, 'Seguimiento registrado correctamente')
return HttpResponseRedirect(reverse(
'change_actions:activity_detail',
kwargs = {'activity_id': activity.id }))
else:
context.update({'form_evidence': form_evidence})
return render(request, self.template_name, context)
else:
context['form_tracking'] = form
return render(request, self.template_name, context)
Any idea why I am getting this error? Thanks in advance!
I want to know if there's some easy way to have 2 models, for example Language, and Word. And we have another model Translation that has the string of the translation and both Models are referenced with a Foreign Key.
Imagine I have 2 languages, English and Spanish. Is there some way to make always appear every language as a label and the string of the translation as a textbox?
If I correctly understand your issue, I think you should look at inlines.
For instance, let's say you have the following models.
class Language(models.Model):
name = models.CharField()
class Word(models.Model):
value = models.CharField()
translations = models.ManyToMany(Language, through='Translation')
class Translation(models.Model):
language = models.ForeignKey(Language)
word = models.ForeignKey(Word)
value = models.CharField()
Then you could have this in your admin.py:
class TranslationInline(admin.TabularInline):
model = Translation
readonly_fields = ['language']
def get_max_num(self, *args, **kwargs):
return Language.objects.all().count()
def get_min_num(self, *args, **kwargs):
return self.get_max_num(*args, **kwargs)
def get_initial(self, request):
return [
{'language': l}
for l in Language.objects.exclude(pk__in=self.get_queryset(request))
]
#admin.register(Word)
class WordAdmin(admin.ModelAdmin):
inlines = [TranslationInline]
def _create_formsets(self, request, obj, change):
formsets = []
inline_instances = []
prefixes = {}
get_formsets_args = [request]
if change:
get_formsets_args.append(obj)
for FormSet, inline in self.get_formsets_with_inlines(*get_formsets_args):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1 or not prefix:
prefix = "%s-%s" % (prefix, prefixes[prefix])
formset_params = {
'instance': obj,
'prefix': prefix,
'queryset': inline.get_queryset(request),
}
if hasattr(inline, 'get_initial'):
formset_params['initial'] = inline.get_initial(request)
if request.method == 'POST':
formset_params.update({
'data': request.POST,
'files': request.FILES,
'save_as_new': '_saveasnew' in request.POST
})
formsets.append(FormSet(**formset_params))
inline_instances.append(inline)
return formsets, inline_instances
This will enable you to add/edit translations of a word in the admin.
If you set editable=False in the field properties, the field will be read-only in admin. For example:
language = models.ForeignKey(Language, editable=False)