I'm getting a validation error with django form - python

I'm facing with a validation form problem.
I have this model:
class Documenti(models.Model):
descr = models.CharField('descrizione ', max_length=200)
data = models.DateField('data', blank=True)
objects = models.Manager()
class Meta:
verbose_name = 'Documenti'
this is the form:
class DocForm(ModelForm):
def __init__(self, *args, **kwargs):
super(DocForm, self).__init__(*args, **kwargs)
class Meta:
model = Documenti
exclude = ['id']
widgets = {
'data': forms.DateInput(format=FORMATO_INPUT_DATE, attrs={'type': 'date', 'class': 'stdh-data'}),
'descr': forms.TextInput(attrs={SIZE: '80'}),
}
and this is the edit function:
def edit_doc(request, doc_id=None):
"""
:param request:
:param doc_id:
"""
if not (doc_id is None):
doc_that = get_object_or_404(Documenti.objects.all(), pk=doc_id)
titolo = ED_DOCUMENTO
else:
doc_that = Documenti()
titolo = INS_DOCUMENTO
form = DocForm(request.POST or None, instance=doc_that)
redirect_to = Documenti().get_absolute_url() + current_page(request)
if form.is_valid(): # All validation rules pass
doc = form.save(commit=False)
doc.save()
return HttpResponseRedirect(redirect_to) # Redirect after POST
else:
print(form)
from documenti.urls import url_views_lista_doc
url_after_close = full_url(request, 'doc:%s' % url_views_lista_doc)
dizio = {FORM: form, TitleScheda: titolo, TAG_url_after_close: url_after_close, }
return generic_render(request, HTML_generic_edit, dizio)
I always get FALSE when I check form.is_valid().
I tried to get error list with {{ form.non_field_errors }} {{ form.field_errors }}
but they seems void.
No idea.
many thanks in advance

I solved!
I had a dot in my action form.
e.g. form name='x' method='POST' action='.'
I remeved that malefic dot (action='') and TADA!!! it works
don't ask me why!

Related

Django 3 - CreateView with initial ForeignKey field

I am trying to create a "restaurant rating" app on Django 3.
I have set up the following models:
# Table storing the different restaurants
class Restaurant(models.Model):
restaurant_name = models.CharField(max_length=200, unique=True)
restaurant_address = models.CharField(max_length=200)
restaurant_street_number = models.CharField(max_length=10)
restaurant_city = models.CharField(max_length=200)
restaurant_cuisine_type = models.CharField(max_length=200)
def __str__(self):
return self.restaurant_name + ' - ' + self.restaurant_city
class UserReview(models.Model):
# Defining the possible grades
Grade_1 = 1
Grade_2 = 2
Grade_3 = 3
Grade_4 = 4
Grade_5 = 5
# All those grades will sit under Review_Grade to appear in choices
Review_Grade = (
(1, '1'),
(2, '2'),
(3, '3'),
(4, '4'),
(5, '5')
)
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
user_review_grade = models.IntegerField(default=None, choices=Review_Grade) # default=None pour eviter d'avoir un bouton vide sur ma template
user_review_comment = models.CharField(max_length=1500)
def get_absolute_url(self):
return reverse('restaurants:reviews', args=[self.id])
This is the form I am using:
# Form for user reviews per restaurant
class UserReviewForm(forms.ModelForm):
class Meta:
model = UserReview
# restaurant = forms.ModelChoiceField(queryset=Restaurant.objects.filter(pk=id))
fields = [
'restaurant',
'user_review_grade',
'user_review_comment'
]
widgets = {
'restaurant': forms.HiddenInput,
'user_review_grade': forms.RadioSelect,
'user_review_comment': forms.Textarea
}
labels = {
'user_review_grade': 'Chose a satisfaction level:',
'user_review_comment': 'And write your comments:'
}
Here are my URLs:
app_name = 'restaurants'
urlpatterns = [
# ex: /restaurants/
path('', views.index, name='index'),
# ex: /restaurants/15
path('<int:restaurant_id>/', views.details, name='details'),
# ex: /restaurants/test
path('<int:restaurant_id>/test', views.Test.as_view(), name='test')
]
Template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>TEST</title>
</head>
<body>
<h1>Write a review for this restaurant:</h1>
<form method="post">
{% csrf_token %}
<input type="Hidden" name="restaurant" value="{{restaurant.restaurant_id}}">
{{ form.as_p }}
<br>
<input type="submit" value="Submit">
</form>
</body>
</html>
And finally my view:
# Test class to be renamed posts reviews as it should
class Test (CreateView):
template_name = 'restaurants/TEST.html'
form_class = UserReviewForm
# Get the initial information needed for the form to function: restaurant field
def get_initial(self, restaurant_id, *args, **kwargs):
initial = super(Test, self).get_initial(**kwargs)
initial['restaurant'] = 9
return initial()
# Post the data into the DB
def post(self, request, *args, **kwargs):
form = UserReviewForm(request.POST)
if form.is_valid():
review = form.save()
print(review) # Print so I cna see in cmd prompt that something posts as it should
review.save()
return render(request, 'restaurants/reviews.html', {'form': form})
I am facing an issue as when I define initial as an integrer (let's say 9 - as I put it to test if my form was actually posting) it posts with no issue the review in the DB for restaurant that holds id=9
However I can't get it to have the restaurant_id automatically populated depending on which restaurant's page we're visiting.
I tried the following as well as few other 'tricks' found here and there but nothing seems to do the cut...
# Test class to be renamed later IF it works...
class Test (CreateView):
template_name = 'restaurants/TEST.html'
form_class = UserReviewForm
# Get the initial information needed for the form to function: restaurant field
def get_initial(self, restaurant_id, *args, **kwargs):
restaurant = get_object_or_404(Restaurant, pk=restaurant_id)
initial = super(Test, self).get_initial(**kwargs)
initial['restaurant'] = self.request.restaurant.pk
return initial()
# Post the data into the DB
def post(self, request, *args, **kwargs):
form = UserReviewForm(request.POST)
if form.is_valid():
review = form.save()
print(review) # Print so I cna see in cmd prompt that something posts as it should
review.save()
return render(request, 'restaurants/reviews.html', {'form': form})
Any help would be appreciated to point me in the right direction :)
You can obtain the restaurant_id in the url parameters with self.kwargs['restaurant_id']. So you can ue:
class Test(CreateView):
def get_initial(self, *args, **kwargs):
initial = super(Test, self).get_initial(**kwargs)
initial['restaurant'] = self.kwargs['restaurant_id']
return initial
# …
That being said, it is rather odd to store this in a form anyway. You can simply set this when the form is valid. So we define the form without a restaurant:
class UserReviewForm(forms.ModelForm):
class Meta:
model = UserReview
fields = [
'user_review_grade',
'user_review_comment'
]
widgets = {
'user_review_grade': forms.RadioSelect,
'user_review_comment': forms.Textarea
}
labels = {
'user_review_grade': 'Chose a satisfaction level:',
'user_review_comment': 'And write your comments:'
}
and in the CreateView, we then set the restaurant of that instance:
class Test(CreateView):
template_name = 'restaurants/TEST.html'
model = UserReview
form_class = UserReviewForm
success_url = …
def form_valid(self, form):
form.instance.restaurant_id = self.kwargs['restaurant_id']
super().form_valid(form)
You here need to specify a success_url to which it will redirect in case the submission is succesful. In case a POST is successful, you need to make a redirect to implement the Post/Redirect/Get pattern [wiki].

Django NameError: request is not defined in class based view [duplicate]

How do I get the current logged in user in forms.py? I am trying to pre-populate the email field of the current user.
class ContactMe(forms.Form):
name = forms.CharField(label = "Name")
email_address = forms.CharField(label = "Email Address", intital = request.user.email)
subject = forms.CharField(label = "Subject")
message = forms.CharField(label = "Message", widget=forms.Textarea(attrs={'cols': 10, 'rows': 3}))
additional_comments = forms.CharField(required = False)
class Meta:
model = Contact_me
I tried passing request from views.py as :
contact_form = ContactMe(request.POST or None, request)
and then receiving the request inside of class ContactMe as :
class ContactMe(forms.Form, request):
name = forms.CharField(label = "Name")
email_address = forms.CharField(label = "Email Address", intital = **request.user.email**)
subject = forms.CharField(label = "Subject")
message = forms.CharField(label = "Message", widget=forms.Textarea(attrs={'cols': 10, 'rows': 3}))
additional_comments = forms.CharField(required = False)
class Meta:
model = Contact_me
It throws the error NameError: name 'request' is not defined. I know request is accessible in html, models.py, views.py. How to get it in forms.py?
The views.py :
def list_posts(request):
request.session.set_expiry(request.session.get_expiry_age()) # Renew session expire time
instance_list = Post.objects.all()
register_form = UserRegisterForm(data=request.POST or None)
if register_form.is_valid():
personal.views.register_form_validation(request, register_form)
login_form = UserLoginForm(request.POST or None)
if login_form.is_valid() :
personal.views.login_form_validation(request, login_form)
feedback_form = FeedbackForm(request.POST or None)
if feedback_form.is_valid() :
personal.views.feedback_form_validation(request, feedback_form)
contact_form = ContactMe(request.POST or None, request)
if contact_form.is_valid() :
personal.views.contact_form_validation(request, login_form)
if request.POST and not(register_form.is_valid() or login_form.is_valid()):
if request.POST.get("login"):
return accounts.views.login_view(request)
else:
return accounts.views.register_view(request)
template = 'blog/archives.html'
dictionary = {
"object_list" : content,
"register_form" : register_form,
"login_form" : login_form,
"feedback_form" : feedback_form,
"contact_form" : contact_form,
}
return render(request,template,dictionary)
You are trying to pass the request when constructing the form class. At this point there is no request. The request only exists inside your view function. You should, therefore, pass the request in your view function when constructing the form instance. To prepopulate the form, you can use the initial keyword of the form constructor. It takes a dictionary of field names and values as input.
Example:
#views.py
from django.shortcuts import render
from django import forms
class TestForm(forms.Form):
foo = forms.CharField()
def test_form(request):
form = TestForm(initial=dict(foo=request.<some_property>))
context = dict(form=form)
template_name = 'testapp/test.html'
return render(request, template_name, context)
This line is wrong class ContactMe(forms.Form, request).
(Hint: request isn't a base class for your form)
The correct way is to access the user in the __init__ method of the form:
class ContactMe(forms.ModelForm):
class Meta:
model = Contact_me
fields = '__all__'
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ContactMe, self).__init__(*args, **kwargs)
The corresponding line in the views.py:
contact_form = ContactMe(request.POST, user=request.user)
Also you get this error if you write requests instead of request
Example
in views.py
def all_products(requests):
products = Product.objects.all()
return render(request, 'store/home.html', {'products': products})
should be:
def all_products(request):
products = Product.objects.all()
return render(request, 'store/home.html', {'products': products})
This was my issue, that's why I bring it up.

How do I prepopulate a form with values from a database in Django?

I'm writing what should be a very simple todo app. The problem is that the edit view is giving me fits! I'm trying to populate a form with data from the database, and it's just not doing the right thing. I've tried the info from this page, but the translation into class-based views must have broken something, or I'm just not using the right kind of form.
Here's the code for the model:
class Todo(models.Model):
id = models.AutoField(primary_key=True)
todo = models.CharField(max_length=255, unique=True)
todo_detail = models.TextField(default='')
date_created = models.DateField(default=timezone.now())
estimated_completion = models.DateTimeField(default=timezone.now())
maybe_completed = models.BooleanField("Completed?", default=False)
def __unicode__(self):
return self.todo
The view code, the commented out bit is from the link:
class TodoEditView(FormView):
model = Todo
form_class = TodoEditForm
template_name = 'todo_edit.html'
#def get(self, request, *args, **kwargs):
# form = self.form_class()
# form.fields['todo'].queryset = Todo.objects.get(id=self.kwargs['pk'])
# form.fields['todo_detail'].queryset = Todo.objects.get(
# id=self.kwargs['pk'])
# form.fields['date_created'].queryset = Todo.objects.get(
# id=self.kwargs['pk'])
# form.fields['estimated_completion'].queryset = Todo.objects.get(
# id=self.kwargs['pk'])
# form.fields['maybe_completed'].queryset = Todo.objects.get(
# id=self.kwargs['pk'])
# template_vars = RequestContext(request, {
# 'form': form
# })
# return render_to_response(self.template_name, template_vars)
def get_context_data(self, **kwargs):
context = super(TodoEditView, self).get_context_data(**kwargs)
context['todo'] = Todo.objects.get(id=self.kwargs['pk'])
return context
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
todo = request.POST['todo']
todo_detail = request.POST['todo_detail']
estimated_completion = request.POST['estimated_completion']
date_created = request.POST['date_created']
t = Todo(todo=todo, todo_detail=todo_detail,
estimated_completion=estimated_completion,
date_created=date_created)
t.save()
return redirect('home')
The form code:
class TodoEditForm(forms.ModelForm):
class Meta:
model = Todo
exclude = ('id', )
And the template code:
{% extends 'todos.html'%}
{% block content %}
<form method="post" action="{% url 'add' %}">
<ul>
{{ form.as_ul }}
{% csrf_token %}
</ul>
{{todo.todo}}
</form>
{% endblock %}
What the heck am I doing wrong?
You should use an UpdateView, not a FormView. That will take care of prepopulating your form.
Also note you don't need any of the logic in the post method - that is all taken care of by the generic view class.

ChoiceField from model - Django - MongoEngine

I'm trying to make this work, with no success so far.
I'm using Django 1.6.5 and mongoengine 0.8.7.
I have some ReferenceField field types in my models.py, which I need to show in a Choice Field type, into a forms.py file.
So, these choices must be filled with the queryset from the referenced (or related models). So when I for example choose to register something in my app, I can relate for example 'users' to 'brands' or 'causes', etc...
Anyways, this was a brief explanation of what I'm trying to achieve with my app, here's my models.py:
from mongoengine import *
class Brand(DynamicDocument):
name = StringField(min_length=3,max_length=10,unique=True)
admins = ListField(ReferenceField("Peer", dbref=True))
campaigns = ListField(ReferenceField("Campaign"))
peers_partner = ListField(ReferenceField("Peer"))
payments = ListField(ReferenceField("Payment_Campaign"))
medias = ListField(EmbeddedDocumentField("Media"))
description = StringField(min_length=10,max_length=500)
socials = ListField(DictField())
def __unicode__(self):
return self.name
#property
def pic_profile(self):
for x in self.medias:
if x.tag == "profile":
return x.url
#property
def pic_banner(self):
for x in self.medias:
if x.tag == "banner":
return x.url
#property
def video_profile(self):
for x in self.medias:
if x.tag == "video":
return x.url
As you can see, there are some ReferenceField fields on my class, these are relationships with other models, but I'm still stuck trying to populate a choice field from forms.py with these references, here's my forms.py:
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Fieldset, ButtonHolder, Submit, Field, Div
from bson.objectid import ObjectId
from mongoengine.queryset import Q
from mongoengine import *
from hdb.brand.models import *
class Form_save_brand(forms.Form):
name = forms.CharField()
admins = forms.ModelChoiceField(queryset=Brand.objects.get_or_create(id=Peer),empty_label="")
campaigns = forms.ChoiceField()
peers_partner = forms.ChoiceField()
payments = forms.ChoiceField()
medias = forms.ChoiceField()
socials = forms.ChoiceField()
def __init__(self, *args, **kwargs):
self.instance = kwargs.pop('instance', None)
super(Form_save_brand, self).__init__(*args, **kwargs)
if self.instance:
self.fields['name'].initial = self.instance.name
self.fields['admins'].initial = self.instance.admins
self.fields['campaigns'].initial = self.instance.campaigns
self.fields['peers_partner'].initial = self.instance.peers_partner
self.fields['payments'].initial = self.instance.payments
self.fields['medias'].initial = self.instance.medias
self.fields['socials'].initial = self.instance.socials
def save(self, commit=True):
brand = self.instance if self.instance else Brand()
brand.name = self.cleaned_data['name']
brand.admins = self.cleaned_data['admins']
brand.campaigns = self['campaigns']
brand.peers_partner = self.cleaned_data['peers_partner']
brand.payments = self.cleaned_data['payments']
brand.medias = self.cleaned_data['medias']
brand.socials = self.cleaned_data['socials']
if commit:
brand.save()
return brand
The only field where I'm doing tests it's the fisrt ReferenceField (admins), which is where I'm stuck, if I manage to solve this I can continue with the other ones.
This is the traceback from Django:
NameError at /brand/nuevo/
name 'Peer' is not defined
Request Method: GET
Request URL: http://localhost:9000/brand/nuevo/
Django Version: 1.6.5
Exception Type: NameError
Exception Value:
name 'Peer' is not defined
Exception Location: /home/kkoci/hipeers/hweb/hweb/hweb/brand/forms.py in Form_save_brand, line 11
Python Executable: /home/kkoci/hipeers/hweb/hipeersweb/bin/python
As you can see right now the query it's like (id=Peer) but I've tried with (id=field), (id=name), etc... with no luck.
I hope I've explained myself...
Any ideas?
Any help would be greatly appreciated, please I'm stuck with this.
Thanks in advance!
EDIT
This is how I initiliaze the form in views.py:
class AddBrand(CreateView):
model = Brand
form_class = Form_save_brand
def get_template_names(self):
return ["brand/brand_nuevo.html"]
def get_success_url(self):
return reverse('list')
def brand_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
messages.success(self.request, "The brand has been created.")
return super(AddBrand, self).brand_valid(form)
Then in template brand/brand_nuevo.html:
{% extends "base.html" %}
{% block body %}
<form action="." method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit"/>
</form>
{% endblock body %}
So, what you need is to instantiate the Form_save_brand with a specific peer so you can work out the dependencies and what is shown. This can be achieved by this (most of the code is kept the same)
You have to change the form to the following:
class Form_save_brand(forms.Form):
name = forms.CharField()
campaigns = forms.ChoiceField()
peers_partner = forms.ChoiceField()
payments = forms.ChoiceField()
medias = forms.ChoiceField()
socials = forms.ChoiceField()
def __init__(self, peer, *args, **kwargs):
# we pass a peer parameter that will be used in the queryset query
self.instance = kwargs.pop('instance', None)
self.fields['admins'] = forms.ModelChoiceField(queryset=Brand.objects.get_or_create(id=peer),empty_label="")
and then, on your view
class AddBrand(CreateView):
model = Brand
# you don't need a form class here
def get_form(self, form_class=None):
return Form_save_brand(<you set the peer value here>, **self.get-form_kwargs())

django admin form empty after POST

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...

Categories

Resources